mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 03:46:02 +03:00
Fix check if nested function can access outer function frame
The previous check wouldn't check intermediate aggregates for static-ness, that was one problem. The other was the assertion that the outer function can be reached as long as there are no static functions inbetween, which isn't always the case, as issue #1864 clearly shows, which is resolved by this.
This commit is contained in:
parent
734398a225
commit
0de021fe32
5 changed files with 31 additions and 37 deletions
|
@ -852,7 +852,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
// data from the template function itself, but it would still mess up our
|
||||
// nested context creation code.
|
||||
FuncDeclaration *parent = fd;
|
||||
while ((parent = getParentFunc(parent, true))) {
|
||||
while ((parent = getParentFunc(parent))) {
|
||||
if (parent->semanticRun != PASSsemantic3done || parent->semantic3Errors) {
|
||||
IF_LOG Logger::println(
|
||||
"Ignoring nested function with unanalyzed parent.");
|
||||
|
|
|
@ -1733,13 +1733,11 @@ llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
|
|||
nullptr, tlsModel);
|
||||
}
|
||||
|
||||
FuncDeclaration *getParentFunc(Dsymbol *sym, bool stopOnStatic) {
|
||||
FuncDeclaration *getParentFunc(Dsymbol *sym) {
|
||||
if (!sym) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check if symbol is itself a static function/aggregate
|
||||
if (stopOnStatic) {
|
||||
// Static functions and function (not delegate) literals don't allow
|
||||
// access to a parent context, even if they are nested.
|
||||
if (FuncDeclaration *fd = sym->isFuncDeclaration()) {
|
||||
|
@ -1757,21 +1755,18 @@ FuncDeclaration *getParentFunc(Dsymbol *sym, bool stopOnStatic) {
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Dsymbol *parent = sym->parent; parent; parent = parent->parent) {
|
||||
if (FuncDeclaration *fd = parent->isFuncDeclaration()) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
if (stopOnStatic) {
|
||||
if (AggregateDeclaration *ad = parent->isAggregateDeclaration()) {
|
||||
if (!ad->isNested()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
|
|||
llvm::StringRef name,
|
||||
bool isThreadLocal = false);
|
||||
|
||||
FuncDeclaration *getParentFunc(Dsymbol *sym, bool stopOnStatic);
|
||||
FuncDeclaration *getParentFunc(Dsymbol *sym);
|
||||
|
||||
void Declaration_codegen(Dsymbol *decl);
|
||||
void Declaration_codegen(Dsymbol *decl, IRState *irs);
|
||||
|
|
|
@ -42,15 +42,14 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|||
|
||||
// Check whether we can access the needed frame
|
||||
FuncDeclaration *fd = irfunc->decl;
|
||||
while (fd != vdparent) {
|
||||
if (fd->isStatic()) {
|
||||
while (fd && fd != vdparent) {
|
||||
fd = getParentFunc(fd);
|
||||
}
|
||||
if (!fd) {
|
||||
error(loc, "function %s cannot access frame of function %s",
|
||||
irfunc->decl->toPrettyChars(), vdparent->toPrettyChars());
|
||||
return new DLValue(astype, llvm::UndefValue::get(DtoPtrToType(astype)));
|
||||
}
|
||||
fd = getParentFunc(fd, false);
|
||||
assert(fd);
|
||||
}
|
||||
|
||||
// is the nested variable in this scope?
|
||||
if (vdparent == irfunc->decl) {
|
||||
|
@ -261,7 +260,7 @@ LLValue *DtoNestedContext(Loc &loc, Dsymbol *sym) {
|
|||
} else if (FuncDeclaration *symfd = sym->isFuncDeclaration()) {
|
||||
// If sym is a nested function, and its parent context is different
|
||||
// than the one we got, adjust it.
|
||||
frameToPass = getParentFunc(symfd, true);
|
||||
frameToPass = getParentFunc(symfd);
|
||||
}
|
||||
|
||||
if (frameToPass) {
|
||||
|
@ -269,7 +268,7 @@ LLValue *DtoNestedContext(Loc &loc, Dsymbol *sym) {
|
|||
FuncDeclaration *ctxfd = irFunc.decl;
|
||||
IF_LOG Logger::println("Current function is %s", ctxfd->toChars());
|
||||
if (fromParent) {
|
||||
ctxfd = getParentFunc(ctxfd, true);
|
||||
ctxfd = getParentFunc(ctxfd);
|
||||
assert(ctxfd && "Context from outer function, but no outer function?");
|
||||
}
|
||||
IF_LOG Logger::println("Context is from %s", ctxfd->toChars());
|
||||
|
@ -319,7 +318,7 @@ static void DtoCreateNestedContextType(FuncDeclaration *fd) {
|
|||
}
|
||||
irFunc.nestedContextCreated = true;
|
||||
|
||||
FuncDeclaration *parentFunc = getParentFunc(fd, true);
|
||||
FuncDeclaration *parentFunc = getParentFunc(fd);
|
||||
// Make sure the parent has already been analyzed.
|
||||
if (parentFunc) {
|
||||
DtoCreateNestedContextType(parentFunc);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 56c5a640ec6fa34d69b42ef2bea726c3f5991d71
|
||||
Subproject commit a6d0fc716643ceee52a7a63d70d7c860e12e5f6d
|
Loading…
Add table
Add a link
Reference in a new issue