Skip to content

Commit

Permalink
[clang][bytecode] Create dummy pointers for non-reference DeclRefExprs (
Browse files Browse the repository at this point in the history
llvm#113202)

... with non-constant initializers.
  • Loading branch information
tbaederr authored Oct 22, 2024
1 parent 0412d71 commit 9ae41c2
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 39 deletions.
76 changes: 39 additions & 37 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2371,9 +2371,9 @@ bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {

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

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

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

assert(classifyPrim(E) == PT_Ptr);
if (std::optional<unsigned> I = P.getOrCreateDummy(E))
return this->emitGetPtrGlobal(*I, E);
if (DiscardResult)
return true;

return false;
assert(classifyPrim(E) == PT_Ptr);
return this->emitDummyPtr(E, E);
}

template <class Emitter>
Expand Down Expand Up @@ -4483,15 +4480,9 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
BuiltinID == Builtin::BI__builtin_function_start) {
if (std::optional<unsigned> GlobalOffset = P.getOrCreateDummy(E)) {
if (!this->emitGetPtrGlobal(*GlobalOffset, E))
return false;

if (PrimType PT = classifyPrim(E); PT != PT_Ptr && isPtrType(PT))
return this->emitDecayPtr(PT_Ptr, PT, E);
if (DiscardResult)
return true;
}
return false;
return this->emitDummyPtr(E, E);
}

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

if (VD->evaluateValue())
return revisit(VD);

if (!D->getType()->isReferenceType())
return this->emitDummyPtr(D, E);

return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
/*InitializerFailed=*/true, E);
}
Expand All @@ -6109,23 +6104,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
}

if (std::optional<unsigned> I = P.getOrCreateDummy(D)) {
if (!this->emitGetPtrGlobal(*I, E))
return false;
if (E->getType()->isVoidType())
return true;
// Convert the dummy pointer to another pointer type if we have to.
if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
if (isPtrType(PT))
return this->emitDecayPtr(PT_Ptr, PT, E);
return false;
}
return true;
}

if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
return this->emitInvalidDeclRef(DRE, /*InitializerFailed=*/false, E);
return false;
return this->emitDummyPtr(D, E);
}

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

/// Create a dummy pointer for the given decl (or expr) and
/// push a pointer to it on the stack.
template <class Emitter>
bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
assert(!DiscardResult && "Should've been checked before");

unsigned DummyID = P.getOrCreateDummy(D);

if (!this->emitGetPtrGlobal(DummyID, E))
return false;
if (E->getType()->isVoidType())
return true;

// Convert the dummy pointer to another pointer type if we have to.
if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
if (isPtrType(PT))
return this->emitDecayPtr(PT_Ptr, PT, E);
return false;
}

return true;
}

namespace clang {
namespace interp {

Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
const BinaryOperator *E);
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
bool emitDummyPtr(const DeclTy &D, const Expr *E);
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
return std::nullopt;
}

std::optional<unsigned> Program::getOrCreateDummy(const DeclTy &D) {
unsigned Program::getOrCreateDummy(const DeclTy &D) {
assert(D);
// Dedup blocks since they are immutable and pointers cannot be compared.
if (auto It = DummyVariables.find(D.getOpaqueValue());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Program final {
const Expr *Init = nullptr);

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

/// Creates a global and returns its index.
std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *Init);
Expand Down
15 changes: 15 additions & 0 deletions clang/test/AST/ByteCode/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1661,3 +1661,18 @@ namespace NullptrUpcast {
constexpr A &ra = *nb; // both-error {{constant expression}} \
// both-note {{cannot access base class of null pointer}}
}

namespace NonConst {
template <int I>
struct S {
static constexpr int Size = I;
constexpr int getSize() const { return I; }
explicit S(int a) {}
};

void func() {
int a,b ;
const S<10> s{a};
static_assert(s.getSize() == 10, "");
}
}

0 comments on commit 9ae41c2

Please sign in to comment.