Skip to content

Commit 0cdb911

Browse files
tbaederraokblast
authored andcommitted
[clang][bytecode] Fix instance pointer in IndirectFieldDecl inits (llvm#164751)
Points to the first chain link in this case.
1 parent 6de2205 commit 0cdb911

File tree

2 files changed

+61
-42
lines changed

2 files changed

+61
-42
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5384,55 +5384,57 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
53845384
// instance pointer of the current function frame, but e.g. to the declaration
53855385
// currently being initialized. Here we emit the necessary instruction(s) for
53865386
// this scenario.
5387-
if (!InitStackActive)
5387+
if (!InitStackActive || InitStack.empty())
53885388
return this->emitThis(E);
53895389

5390-
if (!InitStack.empty()) {
5391-
// If our init stack is, for example:
5392-
// 0 Stack: 3 (decl)
5393-
// 1 Stack: 6 (init list)
5394-
// 2 Stack: 1 (field)
5395-
// 3 Stack: 6 (init list)
5396-
// 4 Stack: 1 (field)
5397-
//
5398-
// We want to find the LAST element in it that's an init list,
5399-
// which is marked with the K_InitList marker. The index right
5400-
// before that points to an init list. We need to find the
5401-
// elements before the K_InitList element that point to a base
5402-
// (e.g. a decl or This), optionally followed by field, elem, etc.
5403-
// In the example above, we want to emit elements [0..2].
5404-
unsigned StartIndex = 0;
5405-
unsigned EndIndex = 0;
5406-
// Find the init list.
5407-
for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
5408-
if (InitStack[StartIndex].Kind == InitLink::K_InitList ||
5409-
InitStack[StartIndex].Kind == InitLink::K_This) {
5410-
EndIndex = StartIndex;
5411-
--StartIndex;
5412-
break;
5413-
}
5390+
// If our init stack is, for example:
5391+
// 0 Stack: 3 (decl)
5392+
// 1 Stack: 6 (init list)
5393+
// 2 Stack: 1 (field)
5394+
// 3 Stack: 6 (init list)
5395+
// 4 Stack: 1 (field)
5396+
//
5397+
// We want to find the LAST element in it that's an init list,
5398+
// which is marked with the K_InitList marker. The index right
5399+
// before that points to an init list. We need to find the
5400+
// elements before the K_InitList element that point to a base
5401+
// (e.g. a decl or This), optionally followed by field, elem, etc.
5402+
// In the example above, we want to emit elements [0..2].
5403+
unsigned StartIndex = 0;
5404+
unsigned EndIndex = 0;
5405+
// Find the init list.
5406+
for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
5407+
if (InitStack[StartIndex].Kind == InitLink::K_InitList ||
5408+
InitStack[StartIndex].Kind == InitLink::K_This) {
5409+
EndIndex = StartIndex;
5410+
--StartIndex;
5411+
break;
54145412
}
5413+
}
54155414

5416-
// Walk backwards to find the base.
5417-
for (; StartIndex > 0; --StartIndex) {
5418-
if (InitStack[StartIndex].Kind == InitLink::K_InitList)
5419-
continue;
5415+
// Walk backwards to find the base.
5416+
for (; StartIndex > 0; --StartIndex) {
5417+
if (InitStack[StartIndex].Kind == InitLink::K_InitList)
5418+
continue;
54205419

5421-
if (InitStack[StartIndex].Kind != InitLink::K_Field &&
5422-
InitStack[StartIndex].Kind != InitLink::K_Elem)
5423-
break;
5424-
}
5420+
if (InitStack[StartIndex].Kind != InitLink::K_Field &&
5421+
InitStack[StartIndex].Kind != InitLink::K_Elem)
5422+
break;
5423+
}
54255424

5426-
// Emit the instructions.
5427-
for (unsigned I = StartIndex; I != EndIndex; ++I) {
5428-
if (InitStack[I].Kind == InitLink::K_InitList)
5429-
continue;
5430-
if (!InitStack[I].template emit<Emitter>(this, E))
5431-
return false;
5432-
}
5433-
return true;
5425+
if (StartIndex == 0 && EndIndex == 0)
5426+
EndIndex = InitStack.size() - 1;
5427+
5428+
assert(StartIndex < EndIndex);
5429+
5430+
// Emit the instructions.
5431+
for (unsigned I = StartIndex; I != (EndIndex + 1); ++I) {
5432+
if (InitStack[I].Kind == InitLink::K_InitList)
5433+
continue;
5434+
if (!InitStack[I].template emit<Emitter>(this, E))
5435+
return false;
54345436
}
5435-
return this->emitThis(E);
5437+
return true;
54365438
}
54375439

54385440
template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {
@@ -6294,6 +6296,10 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
62946296
}
62956297
assert(NestedField);
62966298

6299+
unsigned FirstLinkOffset =
6300+
R->getField(cast<FieldDecl>(IFD->chain()[0]))->Offset;
6301+
InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(InitExpr));
6302+
InitLinkScope<Emitter> ILS(this, InitLink::Field(FirstLinkOffset));
62976303
if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr,
62986304
IsUnion))
62996305
return false;

clang/test/AST/ByteCode/records.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,19 @@ namespace IndirectFieldInit {
11621162
static_assert(s2.x == 1 && s2.y == 2 && s2.a == 3 && s2.b == 4);
11631163

11641164
#endif
1165+
1166+
1167+
struct B {
1168+
struct {
1169+
union {
1170+
int x = 3;
1171+
};
1172+
int y = this->x;
1173+
};
1174+
1175+
constexpr B() {}
1176+
};
1177+
static_assert(B().y == 3, "");
11651178
}
11661179

11671180
namespace InheritedConstructor {

0 commit comments

Comments
 (0)