Skip to content

Commit f926e19

Browse files
committed
Reapply "[clang][Interp] Fix init chain in local initializers"
This reverts commit 2dda8a2.
1 parent cc53b95 commit f926e19

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,12 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
8585
case K_Field:
8686
// We're assuming there's a base pointer on the stack already.
8787
return Ctx->emitGetPtrFieldPop(Offset, E);
88+
case K_Temp:
89+
return Ctx->emitGetPtrLocal(Offset, E);
8890
case K_Decl:
8991
return Ctx->visitDeclRef(D, E);
92+
default:
93+
llvm_unreachable("Unhandled InitLink kind");
9094
}
9195
return true;
9296
}
@@ -1330,6 +1334,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
13301334

13311335
auto initCompositeField = [=](const Record::Field *FieldToInit,
13321336
const Expr *Init) -> bool {
1337+
InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));
13331338
// Non-primitive case. Get a pointer to the field-to-initialize
13341339
// on the stack and recurse into visitInitializer().
13351340
if (!this->emitGetPtrField(FieldToInit->Offset, Init))
@@ -2271,6 +2276,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
22712276
const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
22722277
if (std::optional<unsigned> LocalIndex =
22732278
allocateLocal(Inner, E->getExtendingDecl())) {
2279+
InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
22742280
if (!this->emitGetPtrLocal(*LocalIndex, E))
22752281
return false;
22762282
return this->visitInitializer(SubExpr);
@@ -2449,6 +2455,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
24492455

24502456
// Trivial copy/move constructor. Avoid copy.
24512457
if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
2458+
Ctor->isTrivial() &&
24522459
E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),
24532460
T->getAsCXXRecordDecl()))
24542461
return this->visitInitializer(E->getArg(0));
@@ -3583,6 +3590,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
35833590
return !Init || (checkDecl() && initGlobal(*GlobalIndex));
35843591
} else {
35853592
VariableScope<Emitter> LocalScope(this, VD);
3593+
InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
35863594

35873595
if (VarT) {
35883596
unsigned Offset = this->allocateLocalPrimitive(
@@ -3917,7 +3925,8 @@ bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
39173925
SourceLocScope<Emitter> SLS(this, E);
39183926

39193927
bool Old = InitStackActive;
3920-
InitStackActive = !isa<FunctionDecl>(E->getUsedContext());
3928+
InitStackActive =
3929+
!(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor);
39213930
bool Result = this->delegate(E->getExpr());
39223931
InitStackActive = Old;
39233932
return Result;
@@ -3979,8 +3988,14 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
39793988
// currently being initialized. Here we emit the necessary instruction(s) for
39803989
// this scenario.
39813990
if (InitStackActive && !InitStack.empty()) {
3982-
for (const InitLink &IL : InitStack) {
3983-
if (!IL.emit<Emitter>(this, E))
3991+
unsigned StartIndex = 0;
3992+
for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
3993+
if (InitStack[StartIndex].Kind != InitLink::K_Field)
3994+
break;
3995+
}
3996+
3997+
for (unsigned I = StartIndex, N = InitStack.size(); I != N; ++I) {
3998+
if (!InitStack[I].emit<Emitter>(this, E))
39843999
return false;
39854000
}
39864001
return true;

clang/lib/AST/Interp/Compiler.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ struct InitLink {
4747
enum {
4848
K_This = 0,
4949
K_Field = 1,
50-
K_Decl = 2,
50+
K_Temp = 2,
51+
K_Decl = 3,
5152
};
5253

5354
static InitLink This() { return InitLink{K_This}; }
@@ -56,6 +57,11 @@ struct InitLink {
5657
IL.Offset = Offset;
5758
return IL;
5859
}
60+
static InitLink Temp(unsigned Offset) {
61+
InitLink IL{K_Temp};
62+
IL.Offset = Offset;
63+
return IL;
64+
}
5965
static InitLink Decl(const ValueDecl *D) {
6066
InitLink IL{K_Decl};
6167
IL.D = D;
@@ -66,7 +72,6 @@ struct InitLink {
6672
template <class Emitter>
6773
bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;
6874

69-
private:
7075
uint32_t Kind;
7176
union {
7277
unsigned Offset;

clang/lib/AST/Interp/EvalEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
5757
bool CheckFullyInitialized) {
5858
this->CheckFullyInitialized = CheckFullyInitialized;
5959
S.EvaluatingDecl = VD;
60+
EvalResult.setSource(VD);
6061

6162
if (const Expr *Init = VD->getAnyInitializer()) {
6263
QualType T = VD->getType();

clang/lib/AST/Interp/Pointer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ class Pointer {
638638
/// Returns the embedded descriptor preceding a field.
639639
InlineDescriptor *getInlineDesc() const {
640640
assert(asBlockPointer().Base != sizeof(GlobalInlineDescriptor));
641+
assert(asBlockPointer().Base <= asBlockPointer().Pointee->getSize());
641642
return getDescriptor(asBlockPointer().Base);
642643
}
643644

clang/test/AST/Interp/records.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,3 +1482,15 @@ namespace FloatAPValue {
14821482
ClassTemplateArgRefTemplate<ClassTemplateArgObj.Arg> ClassTemplateArgRefObj;
14831483
}
14841484
#endif
1485+
1486+
namespace LocalWithThisPtrInit {
1487+
struct S {
1488+
int i;
1489+
int *p = &i;
1490+
};
1491+
constexpr int foo() {
1492+
S s{2};
1493+
return *s.p;
1494+
}
1495+
static_assert(foo() == 2, "");
1496+
}

0 commit comments

Comments
 (0)