diff --git a/lib/Interpreter/ASTNodeEraser.cpp b/lib/Interpreter/ASTNodeEraser.cpp index ac8bb522..80c0c51c 100644 --- a/lib/Interpreter/ASTNodeEraser.cpp +++ b/lib/Interpreter/ASTNodeEraser.cpp @@ -313,12 +313,20 @@ namespace cling { llvm::GlobalValue* GV = m_CurTransaction->getModule()->getNamedValue(mangledName); - // Remove the mapping from the JIT, otherwise it locks the GV and - // replaceAllUsesWith doesn't work - m_EEngine->updateGlobalMapping(GV, 0); - if (!GV->use_empty()) - GV->replaceAllUsesWith(llvm::UndefValue::get(GV->getType())); + if (!GV->use_empty()) { + // Assert that if there was a use it is not coming from the explicit AST + // node, but from the implicitly generated functions, which ensure + // the initialization order semantics. Such functions are: + // _GLOBAL__I* and __cxx_global_var_init* + // + assert(GV->hasOneUse() + && "Must have only one use coming from the static inits"); + // We can 'afford' to drop all the references because we know that the + // static init functions must be called only once, and that was already + // done. + GV->use_back()->dropAllReferences(); + } GV->eraseFromParent(); } diff --git a/test/CodeUnloading/Simple.C b/test/CodeUnloading/Simple.C index a3960095..c81767c2 100644 --- a/test/CodeUnloading/Simple.C +++ b/test/CodeUnloading/Simple.C @@ -6,9 +6,12 @@ int f = 0; .U .rawInput 1 extern "C" int printf(const char* fmt, ...); -void f() { +int f() { printf("Now f is a function\n"); -} + return 0; +} int a = f(); +.U .rawInput 0 -f() - //CHECK: Now f is a function +//CHECK: Now f is a function +double f = 3.14 +//CHECK: (double) 3.14