[clang] [clang][bytecode] Create dummy pointers for non-reference DeclRefExprs (PR #113202)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 22 00:47:51 PDT 2024
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/113202
>From 92e2b7ac0510a2355bddb8f1feb09a9bd954310a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 21 Oct 2024 18:36:37 +0200
Subject: [PATCH] [clang][bytecode] Create dummy pointers for non-reference
DeclRefExprs
... with non-constant initializers.
---
clang/lib/AST/ByteCode/Compiler.cpp | 76 +++++++++++++++--------------
clang/lib/AST/ByteCode/Compiler.h | 1 +
clang/lib/AST/ByteCode/Program.cpp | 2 +-
clang/lib/AST/ByteCode/Program.h | 2 +-
clang/test/AST/ByteCode/records.cpp | 15 ++++++
5 files changed, 57 insertions(+), 39 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index b960954d4754a8..59e09a44d747b9 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -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>
@@ -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)
@@ -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>
@@ -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();
@@ -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);
}
@@ -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>
@@ -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 {
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 4253e7b3248c9f..5627d5071e810a 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -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);
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index cd2665f755d7cb..0da518ec92afae 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -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());
diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h
index f676672fb7ced5..9aabe67b550ec7 100644
--- a/clang/lib/AST/ByteCode/Program.h
+++ b/clang/lib/AST/ByteCode/Program.h
@@ -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);
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 215f26bd5da8ea..2eeaafc04c516c 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -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, "");
+ }
+}
More information about the cfe-commits
mailing list