Skip to content

Commit 1aeb64c

Browse files
committed
Reapply "[clang][Interp] Create full type info for dummy pointers"
This reverts commit 6195e22.
1 parent 62c2959 commit 1aeb64c

File tree

6 files changed

+33
-56
lines changed

6 files changed

+33
-56
lines changed

clang/lib/AST/Interp/Descriptor.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -347,14 +347,6 @@ Descriptor::Descriptor(const DeclTy &D)
347347
assert(Source && "Missing source");
348348
}
349349

350-
/// Dummy array.
351-
Descriptor::Descriptor(const DeclTy &D, UnknownSize)
352-
: Source(D), ElemSize(1), Size(UnknownSizeMark), MDSize(0),
353-
AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
354-
IsTemporary(false), IsArray(true), IsDummy(true) {
355-
assert(Source && "Missing source");
356-
}
357-
358350
QualType Descriptor::getType() const {
359351
if (auto *E = asExpr())
360352
return E->getType();

clang/lib/AST/Interp/Descriptor.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ struct Descriptor final {
128128
/// Flag indicating if the block is an array.
129129
const bool IsArray = false;
130130
/// Flag indicating if this is a dummy descriptor.
131-
const bool IsDummy = false;
131+
bool IsDummy = false;
132132

133133
/// Storage management methods.
134134
const BlockCtorFn CtorFn = nullptr;
@@ -162,8 +162,8 @@ struct Descriptor final {
162162
/// Allocates a dummy descriptor.
163163
Descriptor(const DeclTy &D);
164164

165-
/// Allocates a dummy array descriptor.
166-
Descriptor(const DeclTy &D, UnknownSize);
165+
/// Make this descriptor a dummy descriptor.
166+
void makeDummy() { IsDummy = true; }
167167

168168
QualType getType() const;
169169
QualType getElemQualType() const;

clang/lib/AST/Interp/Interp.h

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -823,9 +823,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
823823
// element in the same array are NOT equal. They have the same Base value,
824824
// but a different Offset. This is a pretty rare case, so we fix this here
825825
// by comparing pointers to the first elements.
826-
if (!LHS.isZero() && !LHS.isDummy() && LHS.isArrayRoot())
826+
if (!LHS.isZero() && LHS.isArrayRoot())
827827
VL = LHS.atIndex(0).getByteOffset();
828-
if (!RHS.isZero() && !RHS.isDummy() && RHS.isArrayRoot())
828+
if (!RHS.isZero() && RHS.isArrayRoot())
829829
VR = RHS.atIndex(0).getByteOffset();
830830

831831
S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
@@ -1241,14 +1241,16 @@ inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
12411241
!CheckNull(S, OpPC, Ptr, CSK_Field))
12421242
return false;
12431243

1244-
if (CheckDummy(S, OpPC, Ptr)) {
1245-
if (!CheckExtern(S, OpPC, Ptr))
1246-
return false;
1247-
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1248-
return false;
1249-
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1250-
return false;
1251-
}
1244+
if (!CheckExtern(S, OpPC, Ptr))
1245+
return false;
1246+
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1247+
return false;
1248+
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
1249+
return false;
1250+
1251+
if (Ptr.isBlockPointer() && Off > Ptr.block()->getSize())
1252+
return false;
1253+
12521254
S.Stk.push<Pointer>(Ptr.atField(Off));
12531255
return true;
12541256
}
@@ -2034,11 +2036,6 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
20342036
if (!Ptr.isZero()) {
20352037
if (!CheckArray(S, OpPC, Ptr))
20362038
return false;
2037-
2038-
if (Ptr.isDummy()) {
2039-
S.Stk.push<Pointer>(Ptr);
2040-
return true;
2041-
}
20422039
}
20432040

20442041
if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
@@ -2055,11 +2052,6 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
20552052
if (!Ptr.isZero()) {
20562053
if (!CheckArray(S, OpPC, Ptr))
20572054
return false;
2058-
2059-
if (Ptr.isDummy()) {
2060-
S.Stk.push<Pointer>(Ptr);
2061-
return true;
2062-
}
20632055
}
20642056

20652057
if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
@@ -2113,12 +2105,12 @@ inline bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex, uint32_t
21132105
inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
21142106
const Pointer &Ptr = S.Stk.pop<Pointer>();
21152107

2116-
if (Ptr.isZero() || Ptr.isDummy()) {
2108+
if (Ptr.isZero()) {
21172109
S.Stk.push<Pointer>(Ptr);
21182110
return true;
21192111
}
21202112

2121-
if (!Ptr.isUnknownSizeArray()) {
2113+
if (!Ptr.isUnknownSizeArray() || Ptr.isDummy()) {
21222114
S.Stk.push<Pointer>(Ptr.atIndex(0));
21232115
return true;
21242116
}

clang/lib/AST/Interp/Program.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,17 +144,20 @@ std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *VD) {
144144
if (auto It = DummyVariables.find(VD); It != DummyVariables.end())
145145
return It->second;
146146

147-
// Create dummy descriptor.
148-
// We create desriptors of 'array of unknown size' if the type is an array
149-
// type _and_ the size isn't known (it's not a ConstantArrayType). If the size
150-
// is known however, we create a regular dummy pointer.
151147
Descriptor *Desc;
152-
if (const auto *AT = VD->getType()->getAsArrayTypeUnsafe();
153-
AT && !isa<ConstantArrayType>(AT))
154-
Desc = allocateDescriptor(VD, Descriptor::UnknownSize{});
148+
if (std::optional<PrimType> T = Ctx.classify(VD->getType()))
149+
Desc = createDescriptor(VD, *T, std::nullopt, true, false);
155150
else
151+
Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true,
152+
false);
153+
if (!Desc)
156154
Desc = allocateDescriptor(VD);
157155

156+
assert(Desc);
157+
Desc->makeDummy();
158+
159+
assert(Desc->isDummy());
160+
158161
// Allocate a block for storage.
159162
unsigned I = Globals.size();
160163

@@ -310,8 +313,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
310313
for (const FieldDecl *FD : RD->fields()) {
311314
// Note that we DO create fields and descriptors
312315
// for unnamed bitfields here, even though we later ignore
313-
// them everywhere. That's because so the FieldDecl's
314-
// getFieldIndex() matches.
316+
// them everywhere. That's so the FieldDecl's getFieldIndex() matches.
315317

316318
// Reserve space for the field's descriptor and the offset.
317319
BaseSize += align(sizeof(InlineDescriptor));
@@ -344,6 +346,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
344346
Descriptor::MetadataSize MDSize,
345347
bool IsConst, bool IsTemporary,
346348
bool IsMutable, const Expr *Init) {
349+
347350
// Classes and structures.
348351
if (const auto *RT = Ty->getAs<RecordType>()) {
349352
if (const auto *Record = getOrCreateRecord(RT->getDecl()))

clang/test/AST/Interp/builtin-align-cxx.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,6 @@
22
// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=expected,both -fexperimental-new-constant-interpreter
33
// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=ref,both
44

5-
6-
/// This is just a copy of the one from test/SemaCXX/ with some of the
7-
/// diagnostic output adapted.
8-
/// Also, align32array has an initializer now, which means it's not just
9-
/// a dummy pointer for us and we do actually have type information for it.
10-
/// In the future, we need to retain type information for dummy pointers as
11-
/// well, so here is a test that will break once we do that:
12-
namespace {
13-
_Alignas(32) char heh[4];
14-
static_assert(!__builtin_is_aligned(&heh[1], 4), ""); // expected-error {{failed}}
15-
}
16-
17-
185
// Check that we don't crash when using dependent types in __builtin_align:
196
template <typename a, a b>
207
void *c(void *d) { // both-note{{candidate template ignored}}
@@ -177,7 +164,7 @@ static_assert(wrap_align_up(static_cast<bool>(1), const_value(1 << 21)), ""); //
177164
// both-note@-1{{in instantiation of function template specialization 'wrap_align_up<bool>' requested here}}
178165

179166
// Check constant evaluation for pointers:
180-
_Alignas(32) char align32array[128] = {};
167+
_Alignas(32) char align32array[128];
181168
static_assert(&align32array[0] == &align32array[0], "");
182169
// __builtin_align_up/down can be constant evaluated as a no-op for values
183170
// that are known to have greater alignment:

clang/test/AST/Interp/c.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,6 @@ int test3(void) {
270270
a[0] = test3; // all-error {{incompatible pointer to integer conversion assigning to 'int' from 'int (void)'}}
271271
return 0;
272272
}
273+
/// This tests that we have full type info, even for values we cannot read.
274+
int dummyarray[5];
275+
_Static_assert(&dummyarray[0] < &dummyarray[1], ""); // pedantic-warning {{GNU extension}}

0 commit comments

Comments
 (0)