Traverse full chain of nested aggregates when resolving a nested variable (#3558)

Fixes #3556.
This commit is contained in:
Martin Kinkelin 2020-10-10 19:34:06 +02:00 committed by GitHub
parent f1295903f2
commit 1700e30c20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 17 deletions

View file

@ -66,16 +66,16 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
if (currentCtx) { if (currentCtx) {
Logger::println("Using own nested context of current function"); Logger::println("Using own nested context of current function");
ctx = currentCtx; ctx = currentCtx;
} else if (irfunc->decl->isMember2()) { } else if (AggregateDeclaration *ad = irfunc->decl->isMember2()) {
Logger::println( Logger::println(
"Current function is member of nested class, loading vthis"); "Current function is member of nested class, loading vthis");
LLValue *val =
AggregateDeclaration *cd = irfunc->decl->isMember2(); ad->isClassDeclaration() ? DtoLoad(irfunc->thisArg) : irfunc->thisArg;
LLValue *val = irfunc->thisArg; for (; ad; ad = ad->toParent2()->isAggregateDeclaration()) {
if (cd->isClassDeclaration()) { assert(ad->vthis);
val = DtoLoad(val); val = DtoLoad(DtoGEP(val, 0, getVthisIdx(ad), ".vthis"));
} }
ctx = DtoLoad(DtoGEP(val, 0, getVthisIdx(cd), ".vthis")); ctx = val;
skipDIDeclaration = true; skipDIDeclaration = true;
} else { } else {
Logger::println("Regular nested function, using context arg"); Logger::println("Regular nested function, using context arg");
@ -455,17 +455,13 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
LLValue *src = irFunc.nestArg; LLValue *src = irFunc.nestArg;
if (!src) { if (!src) {
assert(irFunc.thisArg); assert(irFunc.thisArg);
assert(fd->isMember2()); AggregateDeclaration *ad = fd->isMember2();
LLValue *thisval = DtoLoad(irFunc.thisArg); assert(ad);
AggregateDeclaration *cd = fd->isMember2(); assert(ad->vthis);
assert(cd); LLValue *thisptr =
assert(cd->vthis); ad->isClassDeclaration() ? DtoLoad(irFunc.thisArg) : irFunc.thisArg;
IF_LOG Logger::println("Indexing to 'this'"); IF_LOG Logger::println("Indexing to 'this'");
if (cd->isStructDeclaration()) { src = DtoLoad(DtoGEP(thisptr, 0, getVthisIdx(ad), ".vthis"));
src = DtoExtractValue(thisval, getVthisIdx(cd), ".vthis");
} else {
src = DtoLoad(DtoGEP(thisval, 0, getVthisIdx(cd), ".vthis"));
}
} }
if (depth > 1) { if (depth > 1) {
src = DtoBitCast(src, getVoidPtrType()); src = DtoBitCast(src, getVoidPtrType());

View file

@ -0,0 +1,51 @@
// https://github.com/ldc-developers/ldc/issues/3556
// RUN: %ldc -run %s
class C {
int counter = 1;
void test1() {
assert(counter == 1);
++counter;
}
void run1() {
class C2 {
int counter2 = 11;
class C3 {
void run3() {
test1();
test2();
++counter;
++counter2;
}
}
void test2() {
assert(counter == 2);
++counter;
assert(counter2 == 11);
++counter2;
}
void run2() {
auto c3 = new C3;
c3.run3();
++counter;
++counter2;
}
}
auto c2 = new C2;
c2.run2();
assert(c2.counter2 == 14);
++counter;
}
}
void main() {
auto c = new C;
c.run1();
assert(c.counter == 6);
}