[clang] f5ed917 - [clang][Interp] Fix creating variables for TemplateParamObjectDecls
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 29 05:41:38 PDT 2024
Author: Timm Bäder
Date: 2024-04-29T14:34:33+02:00
New Revision: f5ed9170464b73a7a0a386358e995ce8373ef153
URL: https://github.com/llvm/llvm-project/commit/f5ed9170464b73a7a0a386358e995ce8373ef153
DIFF: https://github.com/llvm/llvm-project/commit/f5ed9170464b73a7a0a386358e995ce8373ef153.diff
LOG: [clang][Interp] Fix creating variables for TemplateParamObjectDecls
Actually initialize them with their value. While at it, fix doing
it for non-primitive (only struct so far) types as well.
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/Program.cpp
clang/test/AST/Interp/records.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index aebefd716e27cc..626c30157b228f 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2372,41 +2372,8 @@ bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
assert(V.isStruct());
assert(V.getStructNumBases() == 0);
- // FIXME: This could be useful in visitAPValue, too.
- for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I) {
- const APValue &F = V.getStructField(I);
- const Record::Field *RF = R->getField(I);
-
- if (F.isInt()) {
- PrimType T = classifyPrim(RF->Decl->getType());
- if (!this->visitAPValue(F, T, E))
- return false;
- if (!this->emitInitField(T, RF->Offset, E))
- return false;
- } else if (F.isArray()) {
- assert(RF->Desc->isPrimitiveArray());
- const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe();
- PrimType ElemT = classifyPrim(ArrType->getElementType());
- assert(ArrType);
-
- if (!this->emitDupPtr(E))
- return false;
- if (!this->emitGetPtrField(RF->Offset, E))
- return false;
-
- for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) {
- if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E))
- return false;
- if (!this->emitInitElem(ElemT, A, E))
- return false;
- }
-
- if (!this->emitPopPtr(E))
- return false;
- } else {
- assert(false && "I don't think this should be possible");
- }
- }
+ if (!this->visitAPValueInitializer(V, E))
+ return false;
return this->emitFinishInit(E);
}
@@ -2971,6 +2938,54 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
return false;
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
+ const Expr *E) {
+ if (Val.isStruct()) {
+ const Record *R = this->getRecord(E->getType());
+ assert(R);
+
+ for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {
+ const APValue &F = Val.getStructField(I);
+ const Record::Field *RF = R->getField(I);
+
+ if (F.isInt()) {
+ PrimType T = classifyPrim(RF->Decl->getType());
+ if (!this->visitAPValue(F, T, E))
+ return false;
+ if (!this->emitInitField(T, RF->Offset, E))
+ return false;
+ } else if (F.isArray()) {
+ assert(RF->Desc->isPrimitiveArray());
+ const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe();
+ PrimType ElemT = classifyPrim(ArrType->getElementType());
+ assert(ArrType);
+
+ if (!this->emitDupPtr(E))
+ return false;
+ if (!this->emitGetPtrField(RF->Offset, E))
+ return false;
+
+ for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) {
+ if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E))
+ return false;
+ if (!this->emitInitElem(ElemT, A, E))
+ return false;
+ }
+
+ if (!this->emitPopPtr(E))
+ return false;
+ } else {
+ assert(false && "I don't think this should be possible");
+ }
+ }
+ return true;
+ }
+ // TODO: Other types.
+
+ return false;
+}
+
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
const Function *Func = getFunction(E->getDirectCallee());
@@ -3492,9 +3507,17 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
} else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
const Function *F = getFunction(FuncDecl);
return F && this->emitGetFnPtr(F, E);
- } else if (isa<TemplateParamObjectDecl>(D)) {
- if (std::optional<unsigned> Index = P.getOrCreateGlobal(D))
- return this->emitGetPtrGlobal(*Index, E);
+ } else if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {
+ if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) {
+ if (!this->emitGetPtrGlobal(*Index, E))
+ return false;
+ if (std::optional<PrimType> T = classify(E->getType())) {
+ if (!this->visitAPValue(TPOD->getValue(), *T, E))
+ return false;
+ return this->emitInitGlobal(*T, *Index, E);
+ }
+ return this->visitAPValueInitializer(TPOD->getValue(), E);
+ }
return false;
}
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 4a57f76ae5b372..2c3127968a1c77 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -181,6 +181,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool visitVarDecl(const VarDecl *VD);
/// Visit an APValue.
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
+ bool visitAPValueInitializer(const APValue &Val, const Expr *E);
/// Visits an expression and converts it to a boolean.
bool visitBool(const Expr *E);
diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp
index 3773e0662f784c..02075c20cf556d 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -173,7 +173,8 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
IsExtern = Var->hasExternalStorage();
- } else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl>(VD)) {
+ } else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl,
+ TemplateParamObjectDecl>(VD)) {
IsStatic = true;
IsExtern = false;
} else {
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index ba5c58c96c7bf5..866fa7240d2fae 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1420,3 +1420,17 @@ namespace ZeroInit {
constexpr S3 s3d; // both-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}}
static_assert(s3d.n == 0, "");
}
+
+namespace {
+#if __cplusplus >= 202002L
+ struct C {
+ template <unsigned N> constexpr C(const char (&)[N]) : n(N) {}
+ unsigned n;
+ };
+ template <C c>
+ constexpr auto operator""_c() { return c.n; }
+
+ constexpr auto waldo = "abc"_c;
+ static_assert(waldo == 4, "");
+#endif
+}
More information about the cfe-commits
mailing list