Skip to content

Commit 32b74ca

Browse files
committed
[clang][Interp] Load value from MemberExpr if required
1 parent 36b3c26 commit 32b74ca

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,12 +1272,23 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
12721272
if (DiscardResult)
12731273
return this->discard(Base);
12741274

1275+
// MemberExprs are almost always lvalues, in which case we don't need to
1276+
// do the load. But sometimes they aren't.
1277+
const auto maybeLoadValue = [&]() -> bool {
1278+
if (E->isGLValue())
1279+
return true;
1280+
if (std::optional<PrimType> T = classify(E))
1281+
return this->emitLoadPop(*T, E);
1282+
return false;
1283+
};
1284+
12751285
if (const auto *VD = dyn_cast<VarDecl>(Member)) {
12761286
// I am almost confident in saying that a var decl must be static
12771287
// and therefore registered as a global variable. But this will probably
12781288
// turn out to be wrong some time in the future, as always.
12791289
if (auto GlobalIndex = P.getGlobal(VD))
1280-
return this->emitGetPtrGlobal(*GlobalIndex, E);
1290+
return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();
1291+
return false;
12811292
}
12821293

12831294
if (Initializing) {
@@ -1295,8 +1306,8 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
12951306
const Record::Field *F = R->getField(FD);
12961307
// Leave a pointer to the field on the stack.
12971308
if (F->Decl->getType()->isReferenceType())
1298-
return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
1299-
return this->emitGetPtrField(F->Offset, E);
1309+
return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
1310+
return this->emitGetPtrField(F->Offset, E) && maybeLoadValue();
13001311
}
13011312

13021313
return false;

clang/test/AST/Interp/cxx03.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,17 @@ namespace NonInitializingMemberExpr {
1010
// both-note {{required by}} \
1111
// both-note {{subexpression not valid}}
1212
}
13+
14+
15+
namespace NonLValueMemberExpr {
16+
struct PODType {
17+
int value;
18+
};
19+
20+
#define ATTR __attribute__((require_constant_initialization))
21+
struct TT1 {
22+
ATTR static const int &subobj_init;
23+
};
24+
25+
const int &TT1::subobj_init = PODType().value;
26+
}

0 commit comments

Comments
 (0)