From 265d3ee069d7d9fa3bc7ad6119b89e8d5e5bab26 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 21:37:53 +0200 Subject: [PATCH] Do not try to emit nested functions with unanalyzed parents. GitHub: Fixes #497. --- gen/functions.cpp | 16 ++++++++++++++++ gen/llvmhelpers.cpp | 17 +++++++++++++++++ gen/llvmhelpers.h | 1 + gen/nested.cpp | 17 ----------------- tests/d2/dmd-testsuite | 2 +- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index 57d4fb78..8dc20e7f 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -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); diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index e2cef943..d7170fe3 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -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); +} \ No newline at end of file diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 14d3adf6..7833e93c 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -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 diff --git a/gen/nested.cpp b/gen/nested.cpp index fe79627d..41d5ad12 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -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; diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index cd99578c..9ff3c32d 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit cd99578c148392e2685e12cd03d029081fdbf39f +Subproject commit 9ff3c32d45c7dcc2f1a71007bc8905d263d999f2