diff --git a/lib/Interpreter/IncrementalExecutor.cpp b/lib/Interpreter/IncrementalExecutor.cpp index 34d45528..fff5de75 100644 --- a/lib/Interpreter/IncrementalExecutor.cpp +++ b/lib/Interpreter/IncrementalExecutor.cpp @@ -310,15 +310,25 @@ IncrementalExecutor::runStaticInitializersOnce(llvm::Module* m) { return kExeSuccess; } -void -IncrementalExecutor::runStaticDestructorsOnce() { +void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) { + assert(T && "Must be set"); + // Collect all the dtors bound to this transaction. + AtExitFunctions boundToT; + for (AtExitFunctions::iterator I = m_AtExitFuncs.begin(); + I != m_AtExitFuncs.end();) + if (I->m_FromT == T) { + boundToT.push_back(*I); + I = m_AtExitFuncs.erase(I); + } + else + ++I; + // 'Unload' the cxa_atexit entities. - for (AtExitFunctions::reverse_iterator I = m_AtExitFuncs.rbegin(), - E = m_AtExitFuncs.rend(); I != E; ++I) { + for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(), + E = boundToT.rend(); I != E; ++I) { const CXAAtExitElement& AEE = *I; (*AEE.m_Func)(AEE.m_Arg); } - m_AtExitFuncs.clear(); } void diff --git a/lib/Interpreter/IncrementalExecutor.h b/lib/Interpreter/IncrementalExecutor.h index 3e19541d..40f74fc2 100644 --- a/lib/Interpreter/IncrementalExecutor.h +++ b/lib/Interpreter/IncrementalExecutor.h @@ -130,7 +130,12 @@ namespace cling { } ExecutionResult runStaticInitializersOnce(llvm::Module* m); - void runStaticDestructorsOnce(); + + ///\brief Runs all destructors bound to the given transaction and removes + /// them from the list. + ///\param[in] T - Transaction to which the dtors were bound. + /// + void runAndRemoveStaticDestructors(Transaction* T); ExecutionResult executeFunction(llvm::StringRef function, StoredValueRef* returnValue = 0); diff --git a/test/CodeUnloading/Dtors.C b/test/CodeUnloading/Dtors.C new file mode 100644 index 00000000..99900662 --- /dev/null +++ b/test/CodeUnloading/Dtors.C @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +// CLING - the C++ LLVM-based InterpreterG :) +// +// This file is dual-licensed: you can choose to license it under the University +// of Illinois Open Source License or the GNU Lesser General Public License. See +// LICENSE.TXT for details. +//------------------------------------------------------------------------------ + +// RUN: cat %s | %cling 2>&1 | FileCheck %s + +extern "C" int printf(const char* fmt, ...); +.storeState "preUnload" +class ClassWithDtor{ +private: + int N; +public: + ClassWithDtor() : N(0){ N++; } + ~ClassWithDtor() { + N--; + printf("Dtor called, N=%d\n", N); + } +}; ClassWithDtor m; +.U +//CHECK: Dtor called, N=0 +.compareState "preUnload" + +//CHECK-NOT: Differences +.q