diff options
author | Timm Bäder <tbaeder@redhat.com> | 2024-04-15 15:41:33 +0200 |
---|---|---|
committer | Timm Bäder <tbaeder@redhat.com> | 2024-04-16 13:04:28 +0200 |
commit | 32b74ca6e41768c91eee8b8ca26235b110a65deb (patch) | |
tree | 0f5001c99e1fe480c7ee8adc0cb9cef9f57b0a8d | |
parent | 36b3c26451bf9a42f0b6b415993d3942bb73abdd (diff) |
[clang][Interp] Load value from MemberExpr if required
-rw-r--r-- | clang/lib/AST/Interp/ByteCodeExprGen.cpp | 17 | ||||
-rw-r--r-- | clang/test/AST/Interp/cxx03.cpp | 14 |
2 files changed, 28 insertions, 3 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index a069f3ec27e7..00c4a9f16130 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1272,12 +1272,23 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) { if (DiscardResult) return this->discard(Base); + // MemberExprs are almost always lvalues, in which case we don't need to + // do the load. But sometimes they aren't. + const auto maybeLoadValue = [&]() -> bool { + if (E->isGLValue()) + return true; + if (std::optional<PrimType> T = classify(E)) + return this->emitLoadPop(*T, E); + return false; + }; + if (const auto *VD = dyn_cast<VarDecl>(Member)) { // I am almost confident in saying that a var decl must be static // and therefore registered as a global variable. But this will probably // turn out to be wrong some time in the future, as always. if (auto GlobalIndex = P.getGlobal(VD)) - return this->emitGetPtrGlobal(*GlobalIndex, E); + return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue(); + return false; } if (Initializing) { @@ -1295,8 +1306,8 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) { const Record::Field *F = R->getField(FD); // Leave a pointer to the field on the stack. if (F->Decl->getType()->isReferenceType()) - return this->emitGetFieldPop(PT_Ptr, F->Offset, E); - return this->emitGetPtrField(F->Offset, E); + return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue(); + return this->emitGetPtrField(F->Offset, E) && maybeLoadValue(); } return false; diff --git a/clang/test/AST/Interp/cxx03.cpp b/clang/test/AST/Interp/cxx03.cpp index d30cbb2fd7a2..b6aaf0840cfb 100644 --- a/clang/test/AST/Interp/cxx03.cpp +++ b/clang/test/AST/Interp/cxx03.cpp @@ -10,3 +10,17 @@ namespace NonInitializingMemberExpr { // both-note {{required by}} \ // both-note {{subexpression not valid}} } + + +namespace NonLValueMemberExpr { + struct PODType { + int value; + }; + +#define ATTR __attribute__((require_constant_initialization)) + struct TT1 { + ATTR static const int &subobj_init; + }; + + const int &TT1::subobj_init = PODType().value; +} |