Prepone callback initialization in cling.
We should setup our callbacks for ExternalASTSource/ExternalSemaSource before we parse *any* code to prevent that any part of the code stores a reference to a non-cling external sources. If this happens, then the clang data structures such redecl chain could go out of sync if they reference different sources and produce errors like failing to merge declarations correctly or creating invalid redecl chains. To fix this, we move this initalization before the initalization of the incremental parser which is the first part that can generate any AST nodes. We only do this for the modules case because in the non-modules case the clang PCH overwrites our callback in the ExternalASTSource and therefore would destroy our external source.
This commit is contained in:
parent
d411ed7885
commit
016eaa7620
@ -182,6 +182,20 @@ namespace cling {
|
||||
return Opts.ShowVersion || Opts.Help;
|
||||
}
|
||||
|
||||
static void setupCallbacks(Interpreter& Interp,
|
||||
const Interpreter* parentInterp) {
|
||||
// We need InterpreterCallbacks only if it is a parent Interpreter.
|
||||
if (parentInterp) return;
|
||||
|
||||
// Disable suggestions for ROOT
|
||||
bool showSuggestions =
|
||||
!llvm::StringRef(ClingStringify(CLING_VERSION)).startswith("ROOT");
|
||||
|
||||
std::unique_ptr<InterpreterCallbacks> AutoLoadCB(
|
||||
new AutoloadCallback(&Interp, showSuggestions));
|
||||
Interp.setCallbacks(std::move(AutoLoadCB));
|
||||
}
|
||||
|
||||
Interpreter::Interpreter(int argc, const char* const *argv,
|
||||
const char* llvmdir /*= 0*/, bool noRuntime,
|
||||
const Interpreter* parentInterp) :
|
||||
@ -226,6 +240,17 @@ namespace cling {
|
||||
DiagnosticConsumer& DClient = getCI()->getDiagnosticClient();
|
||||
DClient.BeginSourceFile(getCI()->getLangOpts(), &PP);
|
||||
|
||||
bool usingCxxModules = getSema().getLangOpts().Modules;
|
||||
|
||||
// When using C++ modules, we setup the callbacks now that we have them
|
||||
// ready before we parse code for the first time. Without C++ modules
|
||||
// we can't setup the calls now because the clang PCH currently just
|
||||
// overwrites it in the Initialize method and we have no simple way to
|
||||
// initialize them earlier. We handle the non-modules case below.
|
||||
if (usingCxxModules) {
|
||||
setupCallbacks(*this, parentInterp);
|
||||
}
|
||||
|
||||
llvm::SmallVector<IncrementalParser::ParseResultTransaction, 2>
|
||||
IncrParserTransactions;
|
||||
if (!m_IncrParser->Initialize(IncrParserTransactions, parentInterp)) {
|
||||
@ -237,6 +262,13 @@ namespace cling {
|
||||
return;
|
||||
}
|
||||
|
||||
// When not using C++ modules, we now have a PCH and we can safely setup
|
||||
// our callbacks without fearing that they get ovewritten by clang code.
|
||||
// The modules setup is handled above.
|
||||
if (!usingCxxModules) {
|
||||
setupCallbacks(*this, parentInterp);
|
||||
}
|
||||
|
||||
llvm::SmallVector<llvm::StringRef, 6> Syms;
|
||||
Initialize(noRuntime || m_Opts.NoRuntime, isInSyntaxOnlyMode(), Syms);
|
||||
|
||||
@ -269,16 +301,6 @@ namespace cling {
|
||||
}
|
||||
}
|
||||
|
||||
// Disable suggestions for ROOT
|
||||
bool showSuggestions = !llvm::StringRef(ClingStringify(CLING_VERSION)).startswith("ROOT");
|
||||
|
||||
// We need InterpreterCallbacks only if it is a parent Interpreter.
|
||||
if (!parentInterp) {
|
||||
std::unique_ptr<InterpreterCallbacks>
|
||||
AutoLoadCB(new AutoloadCallback(this, showSuggestions));
|
||||
setCallbacks(std::move(AutoLoadCB));
|
||||
}
|
||||
|
||||
m_IncrParser->SetTransformers(parentInterp);
|
||||
|
||||
if (!m_LLVMContext) {
|
||||
|
Loading…
Reference in New Issue
Block a user