Fix for Interpreter hanging on to states that can refer to a deleted llvm::Module.

This commit is contained in:
Frederich Munch 2017-02-02 12:44:32 -05:00 committed by sftnight
parent f057cf9b0c
commit 4dd1ce8e56
3 changed files with 52 additions and 2 deletions

View File

@ -81,6 +81,10 @@ namespace cling {
const char* type = nullptr, bool verbose = false,
const llvm::SmallVectorImpl<llvm::StringRef>* ignores = 0) const;
///\brief Return the llvm::Module this state is bound too.
///
const llvm::Module* getModule() const { return m_Module; }
static void printLookupTables(llvm::raw_ostream& Out, const clang::ASTContext& C);
static void printIncludedFiles(llvm::raw_ostream& Out,
const clang::SourceManager& SM);

View File

@ -314,10 +314,14 @@ namespace cling {
}
Interpreter::~Interpreter() {
if (m_Executor)
m_Executor->shuttingDown();
// Do this first so m_StoredStates will be ignored if Interpreter::unload
// is called later on.
for (size_t i = 0, e = m_StoredStates.size(); i != e; ++i)
delete m_StoredStates[i];
m_StoredStates.clear();
if (m_Executor)
m_Executor->shuttingDown();
if (CompilerInstance* CI = getCIOrNull())
getCI()->getDiagnostics().getClient()->EndSourceFile();
@ -1177,6 +1181,29 @@ namespace cling {
}
void Interpreter::unload(Transaction& T) {
// Clear any stored states that reference the llvm::Module.
// Do it first in case
if (!m_StoredStates.empty()) {
const llvm::Module* const module = T.getModule();
std::vector<unsigned> badStates;
for (unsigned i = 0, N = m_StoredStates.size(); i < N; ++i) {
if (m_StoredStates[i]->getModule() == module) {
badStates.push_back(i);
if (m_Opts.Verbose()) {
cling::errs() << "Unloading Transaction forced state '"
<< m_StoredStates[i]->getName()
<< "' to be destroyed\n";
}
}
}
// Pop off the back so as not to recompute index.
// Should the user be warned in verbose mode?
for (std::vector<unsigned>::reverse_iterator it = badStates.rbegin(),
e = badStates.rend(); it != e; ++it) {
m_StoredStates.erase(m_StoredStates.begin()+(*it));
}
}
if (InterpreterCallbacks* callbacks = getCallbacks())
callbacks->TransactionUnloaded(T);
if (m_Executor) { // we also might be in fsyntax-only mode.

View File

@ -0,0 +1,19 @@
//------------------------------------------------------------------------------
// 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 -v -Xclang -verify 2>&1 | FileCheck %s
int i = 0;
.storeState "A"
.undo
// CHECK: Unloading Transaction forced state 'A' to be destroyed
// expected-no-diagnostics
.q