Do not try to emit nested functions with unanalyzed parents.

GitHub: Fixes #497.
This commit is contained in:
David Nadlinger
2013-10-13 21:37:53 +02:00
parent 07eec1840e
commit 265d3ee069
5 changed files with 35 additions and 18 deletions

View File

@@ -910,6 +910,22 @@ void DtoDefineFunction(FuncDeclaration* fd)
if (fd->ir.defined) return;
fd->ir.defined = true;
// We cannot emit nested functions with parents that have not gone through
// semantic analysis. This can happen as DMD leaks some template instances
// from constraints into the module member list. DMD gets away with being
// sloppy as functions in template contraints obviously never need to access
// 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)))
{
if (parent->semanticRun != PASSsemantic3done)
{
Logger::println("Ignoring nested function with unanalyzed parent.");
return;
}
}
if (fd->isUnitTestDeclaration()) {
if (global.params.useUnitTests)
gIR->unitTests.push_back(fd);

View File

@@ -2012,3 +2012,20 @@ llvm::GlobalVariable* getOrCreateGlobal(Loc loc, llvm::Module& module,
init, name, 0, isThreadLocal);
#endif
}
FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic) {
if (!sym)
return NULL;
Dsymbol* parent = sym->parent;
assert(parent);
while (parent && !parent->isFuncDeclaration()) {
if (stopOnStatic) {
Declaration* decl = sym->isDeclaration();
if (decl && decl->isStatic())
return NULL;
}
parent = parent->parent;
}
return (parent ? parent->isFuncDeclaration() : NULL);
}

View File

@@ -239,5 +239,6 @@ llvm::GlobalVariable* getOrCreateGlobal(Loc loc, llvm::Module& module,
llvm::Type* type, bool isConstant, llvm::GlobalValue::LinkageTypes linkage,
llvm::Constant* init, llvm::StringRef name, bool isThreadLocal = false);
FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic);
#endif

View File

@@ -24,23 +24,6 @@ namespace cl = llvm::cl;
// NESTED VARIABLE HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/
static FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic) {
if (!sym)
return NULL;
Dsymbol* parent = sym->parent;
assert(parent);
while (parent && !parent->isFuncDeclaration()) {
if (stopOnStatic) {
Declaration* decl = sym->isDeclaration();
if (decl && decl->isStatic())
return NULL;
}
parent = parent->parent;
}
return (parent ? parent->isFuncDeclaration() : NULL);
}
static void storeVariable(VarDeclaration *vd, LLValue *dst)
{
LLValue *value = vd->ir.irLocal->value;