Skip to content

Commit 58df80e

Browse files
committed
asdf
1 parent f5ed863 commit 58df80e

File tree

5 files changed

+83
-26
lines changed

5 files changed

+83
-26
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,30 +1143,12 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
11431143
}
11441144

11451145
if (Pointer::hasSameBase(LHS, RHS)) {
1146-
if (LHS.inUnion() && RHS.inUnion()) {
1147-
// If the pointers point into a union, things are a little more
1148-
// complicated since the offset we save in interp::Pointer can't be used
1149-
// to compare the pointers directly.
1150-
size_t A = LHS.computeOffsetForComparison();
1151-
size_t B = RHS.computeOffsetForComparison();
1152-
S.Stk.push<BoolT>(BoolT::from(Fn(Compare(A, B))));
1153-
return true;
1154-
}
1155-
1156-
unsigned VL = LHS.getByteOffset();
1157-
unsigned VR = RHS.getByteOffset();
1158-
// In our Pointer class, a pointer to an array and a pointer to the first
1159-
// element in the same array are NOT equal. They have the same Base value,
1160-
// but a different Offset. This is a pretty rare case, so we fix this here
1161-
// by comparing pointers to the first elements.
1162-
if (!LHS.isZero() && LHS.isArrayRoot())
1163-
VL = LHS.atIndex(0).getByteOffset();
1164-
if (!RHS.isZero() && RHS.isArrayRoot())
1165-
VR = RHS.atIndex(0).getByteOffset();
1166-
1167-
S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
1146+
size_t A = LHS.computeOffsetForComparison();
1147+
size_t B = RHS.computeOffsetForComparison();
1148+
S.Stk.push<BoolT>(BoolT::from(Fn(Compare(A, B))));
11681149
return true;
11691150
}
1151+
11701152
// Otherwise we need to do a bunch of extra checks before returning Unordered.
11711153
if (LHS.isOnePastEnd() && !RHS.isOnePastEnd() && !RHS.isZero() &&
11721154
RHS.getOffset() == 0) {

clang/lib/AST/ByteCode/Pointer.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,16 +349,28 @@ void Pointer::print(llvm::raw_ostream &OS) const {
349349
}
350350
}
351351

352-
/// Compute an integer that can be used to compare this pointer to
353-
/// another one.
354352
size_t Pointer::computeOffsetForComparison() const {
353+
if (isIntegralPointer())
354+
return asIntPointer().Value + Offset;
355+
if (isTypeidPointer())
356+
return reinterpret_cast<uintptr_t>(asTypeidPointer().TypePtr) + Offset;
357+
355358
if (!isBlockPointer())
356359
return Offset;
357360

358361
size_t Result = 0;
359362
Pointer P = *this;
360-
while (!P.isRoot()) {
361-
if (P.isArrayRoot()) {
363+
while (true) {
364+
365+
if (P.isVirtualBaseClass()) {
366+
Result += getInlineDesc()->Offset;
367+
P = P.getBase();
368+
continue;
369+
}
370+
371+
if (P.isBaseClass()) {
372+
if (P.getRecord()->getNumVirtualBases() > 0)
373+
Result += P.getInlineDesc()->Offset;
362374
P = P.getBase();
363375
continue;
364376
}
@@ -369,14 +381,26 @@ size_t Pointer::computeOffsetForComparison() const {
369381
continue;
370382
}
371383

384+
if (P.isRoot()) {
385+
if (P.isOnePastEnd())
386+
++Result;
387+
break;
388+
}
389+
372390
if (const Record *R = P.getBase().getRecord(); R && R->isUnion()) {
373391
// Direct child of a union - all have offset 0.
374392
P = P.getBase();
375393
continue;
376394
}
377395

396+
// Fields, etc.
378397
Result += P.getInlineDesc()->Offset;
398+
if (P.isOnePastEnd())
399+
++Result;
400+
379401
P = P.getBase();
402+
if (P.isRoot())
403+
break;
380404
}
381405

382406
return Result;

clang/lib/AST/ByteCode/Pointer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,9 @@ class Pointer {
761761
/// Prints the pointer.
762762
void print(llvm::raw_ostream &OS) const;
763763

764+
/// Compute an integer that can be used to compare this pointer to
765+
/// another one. This is usually NOT the same as the pointer offset
766+
/// regarding the AST record layout.
764767
size_t computeOffsetForComparison() const;
765768

766769
private:

clang/test/AST/ByteCode/literals.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,3 +1418,15 @@ constexpr int usingDirectiveDecl() {
14181418
return FB;
14191419
}
14201420
static_assert(usingDirectiveDecl() == 10, "");
1421+
1422+
namespace OnePastEndCmp {
1423+
struct S {
1424+
int a;
1425+
int b;
1426+
};
1427+
1428+
constexpr S s{12,13};
1429+
constexpr const int *p = &s.a;
1430+
constexpr const int *q = &s.a + 1;
1431+
static_assert(p != q, "");
1432+
}

clang/test/AST/ByteCode/new-delete.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,42 @@ namespace OpNewNothrow {
10221022
// both-note {{in call to}}
10231023
}
10241024

1025+
namespace BaseCompare {
1026+
struct Cmp {
1027+
void *p;
1028+
1029+
template<typename T>
1030+
constexpr Cmp(T *t) : p(t) {}
1031+
1032+
constexpr friend bool operator==(Cmp a, Cmp b) {
1033+
return a.p == b.p;
1034+
}
1035+
};
1036+
1037+
class Base {};
1038+
class Derived : public Base {};
1039+
constexpr bool foo() {
1040+
Derived *D = std::allocator<Derived>{}.allocate(1);;
1041+
std::construct_at<Derived>(D);
1042+
1043+
Derived *d = D;
1044+
Base *b = D;
1045+
1046+
Cmp ca(d);
1047+
Cmp cb(b);
1048+
1049+
if (ca == cb) {
1050+
std::allocator<Derived>{}.deallocate(D);
1051+
return true;
1052+
}
1053+
std::allocator<Derived>{}.deallocate(D);
1054+
1055+
return false;
1056+
1057+
}
1058+
static_assert(foo());
1059+
}
1060+
10251061
#else
10261062
/// Make sure we reject this prior to C++20
10271063
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)