Skip to content

Commit 9ae41c2

Browse files
authored
[clang][bytecode] Create dummy pointers for non-reference DeclRefExprs (#113202)
... with non-constant initializers.
1 parent 0412d71 commit 9ae41c2

File tree

5 files changed

+57
-39
lines changed

5 files changed

+57
-39
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,9 +2371,9 @@ bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {
23712371

23722372
template <class Emitter>
23732373
bool Compiler<Emitter>::VisitObjCStringLiteral(const ObjCStringLiteral *E) {
2374-
if (std::optional<unsigned> I = P.getOrCreateDummy(E))
2375-
return this->emitGetPtrGlobal(*I, E);
2376-
return false;
2374+
if (DiscardResult)
2375+
return true;
2376+
return this->emitDummyPtr(E, E);
23772377
}
23782378

23792379
template <class Emitter>
@@ -3445,11 +3445,8 @@ bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
34453445
assert(RD);
34463446
// If the definiton of the result type is incomplete, just return a dummy.
34473447
// If (and when) that is read from, we will fail, but not now.
3448-
if (!RD->isCompleteDefinition()) {
3449-
if (std::optional<unsigned> I = P.getOrCreateDummy(GuidDecl))
3450-
return this->emitGetPtrGlobal(*I, E);
3451-
return false;
3452-
}
3448+
if (!RD->isCompleteDefinition())
3449+
return this->emitDummyPtr(GuidDecl, E);
34533450

34543451
std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(GuidDecl);
34553452
if (!GlobalIndex)
@@ -3687,11 +3684,11 @@ bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
36873684
if (!E->isExpressibleAsConstantInitializer())
36883685
return this->discard(SubExpr) && this->emitInvalid(E);
36893686

3690-
assert(classifyPrim(E) == PT_Ptr);
3691-
if (std::optional<unsigned> I = P.getOrCreateDummy(E))
3692-
return this->emitGetPtrGlobal(*I, E);
3687+
if (DiscardResult)
3688+
return true;
36933689

3694-
return false;
3690+
assert(classifyPrim(E) == PT_Ptr);
3691+
return this->emitDummyPtr(E, E);
36953692
}
36963693

36973694
template <class Emitter>
@@ -4483,15 +4480,9 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
44834480
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
44844481
BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
44854482
BuiltinID == Builtin::BI__builtin_function_start) {
4486-
if (std::optional<unsigned> GlobalOffset = P.getOrCreateDummy(E)) {
4487-
if (!this->emitGetPtrGlobal(*GlobalOffset, E))
4488-
return false;
4489-
4490-
if (PrimType PT = classifyPrim(E); PT != PT_Ptr && isPtrType(PT))
4491-
return this->emitDecayPtr(PT_Ptr, PT, E);
4483+
if (DiscardResult)
44924484
return true;
4493-
}
4494-
return false;
4485+
return this->emitDummyPtr(E, E);
44954486
}
44964487

44974488
QualType ReturnType = E->getType();
@@ -6097,6 +6088,10 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
60976088

60986089
if (VD->evaluateValue())
60996090
return revisit(VD);
6091+
6092+
if (!D->getType()->isReferenceType())
6093+
return this->emitDummyPtr(D, E);
6094+
61006095
return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
61016096
/*InitializerFailed=*/true, E);
61026097
}
@@ -6109,23 +6104,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
61096104
}
61106105
}
61116106

6112-
if (std::optional<unsigned> I = P.getOrCreateDummy(D)) {
6113-
if (!this->emitGetPtrGlobal(*I, E))
6114-
return false;
6115-
if (E->getType()->isVoidType())
6116-
return true;
6117-
// Convert the dummy pointer to another pointer type if we have to.
6118-
if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
6119-
if (isPtrType(PT))
6120-
return this->emitDecayPtr(PT_Ptr, PT, E);
6121-
return false;
6122-
}
6123-
return true;
6124-
}
6125-
6126-
if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6127-
return this->emitInvalidDeclRef(DRE, /*InitializerFailed=*/false, E);
6128-
return false;
6107+
return this->emitDummyPtr(D, E);
61296108
}
61306109

61316110
template <class Emitter>
@@ -6428,6 +6407,29 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
64286407
return this->emitRecordDestruction(Desc->ElemRecord, Loc);
64296408
}
64306409

6410+
/// Create a dummy pointer for the given decl (or expr) and
6411+
/// push a pointer to it on the stack.
6412+
template <class Emitter>
6413+
bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
6414+
assert(!DiscardResult && "Should've been checked before");
6415+
6416+
unsigned DummyID = P.getOrCreateDummy(D);
6417+
6418+
if (!this->emitGetPtrGlobal(DummyID, E))
6419+
return false;
6420+
if (E->getType()->isVoidType())
6421+
return true;
6422+
6423+
// Convert the dummy pointer to another pointer type if we have to.
6424+
if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
6425+
if (isPtrType(PT))
6426+
return this->emitDecayPtr(PT_Ptr, PT, E);
6427+
return false;
6428+
}
6429+
6430+
return true;
6431+
}
6432+
64316433
namespace clang {
64326434
namespace interp {
64336435

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
370370
const BinaryOperator *E);
371371
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
372372
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
373+
bool emitDummyPtr(const DeclTy &D, const Expr *E);
373374
unsigned collectBaseOffset(const QualType BaseType,
374375
const QualType DerivedType);
375376
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);

clang/lib/AST/ByteCode/Program.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
147147
return std::nullopt;
148148
}
149149

150-
std::optional<unsigned> Program::getOrCreateDummy(const DeclTy &D) {
150+
unsigned Program::getOrCreateDummy(const DeclTy &D) {
151151
assert(D);
152152
// Dedup blocks since they are immutable and pointers cannot be compared.
153153
if (auto It = DummyVariables.find(D.getOpaqueValue());

clang/lib/AST/ByteCode/Program.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class Program final {
8585
const Expr *Init = nullptr);
8686

8787
/// Returns or creates a dummy value for unknown declarations.
88-
std::optional<unsigned> getOrCreateDummy(const DeclTy &D);
88+
unsigned getOrCreateDummy(const DeclTy &D);
8989

9090
/// Creates a global and returns its index.
9191
std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *Init);

clang/test/AST/ByteCode/records.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,3 +1661,18 @@ namespace NullptrUpcast {
16611661
constexpr A &ra = *nb; // both-error {{constant expression}} \
16621662
// both-note {{cannot access base class of null pointer}}
16631663
}
1664+
1665+
namespace NonConst {
1666+
template <int I>
1667+
struct S {
1668+
static constexpr int Size = I;
1669+
constexpr int getSize() const { return I; }
1670+
explicit S(int a) {}
1671+
};
1672+
1673+
void func() {
1674+
int a,b ;
1675+
const S<10> s{a};
1676+
static_assert(s.getSize() == 10, "");
1677+
}
1678+
}

0 commit comments

Comments
 (0)