diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index 106cc74aaf541037a13df377fe17eb1603c7ffc7..5061a5bc991edde989338772a2a12903e58e3b96 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -1074,40 +1074,18 @@ std::string TCling::ToString(const char* type, void* obj) ///\returns true if the module was loaded. static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp, bool Complain = true) { - clang::CompilerInstance &CI = *interp.getCI(); - - assert(CI.getLangOpts().Modules && "Function only relevant when C++ modules are turned on!"); - - clang::Preprocessor &PP = CI.getPreprocessor(); - clang::HeaderSearch &headerSearch = PP.getHeaderSearchInfo(); - - cling::Interpreter::PushTransactionRAII RAII(&interp); - if (clang::Module *M = headerSearch.lookupModule(ModuleName, true /*AllowSearch*/, true /*AllowExtraSearch*/)) { - clang::IdentifierInfo *II = PP.getIdentifierInfo(M->Name); - SourceLocation ValidLoc = M->DefinitionLoc; - bool success = !CI.getSema().ActOnModuleImport(ValidLoc, ValidLoc, std::make_pair(II, ValidLoc)).isInvalid(); - if (success) { - // Also make the module visible in the preprocessor to export its macros. - PP.makeModuleVisible(M, ValidLoc); - return success; - } - if (Complain) { - if (M->IsSystem) - Error("TCling::LoadModule", "Module %s failed to load", M->Name.c_str()); - else - Info("TCling::LoadModule", "Module %s failed to load", M->Name.c_str()); - } - } + if (interp.loadModule(ModuleName, Complain)) + return true; // Load modulemap if we have one in current directory - SourceManager& SM = PP.getSourceManager(); - FileManager& FM = SM.getFileManager(); - const clang::DirectoryEntry *DE = FM.getDirectory("."); + Preprocessor &PP = interp.getCI()->getPreprocessor(); + FileManager& FM = PP.getFileManager(); + const DirectoryEntry *DE = FM.getDirectory("."); if (DE) { - const clang::FileEntry *FE = headerSearch.lookupModuleMapFile(DE, /*IsFramework*/ false); - // Check if "./module.modulemap is already loaded or not - if (!gCling->IsLoaded("./module.modulemap") && FE) { - if(!headerSearch.loadModuleMapFile(FE, /*IsSystem*/ false)) + HeaderSearch& HS = PP.getHeaderSearchInfo(); + const FileEntry *FE = HS.lookupModuleMapFile(DE, /*IsFramework*/ false); + if (FE && !gCling->IsLoaded("./module.modulemap")) { + if (!HS.loadModuleMapFile(FE, /*IsSystem*/ false)) return LoadModule(ModuleName, interp, Complain); Error("TCling::LoadModule", "Could not load modulemap in the current directory"); } @@ -1115,6 +1093,7 @@ static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp if (Complain) Error("TCling::LoadModule", "Module %s not found!", ModuleName.c_str()); + return false; } diff --git a/interpreter/cling/include/cling/Interpreter/Interpreter.h b/interpreter/cling/include/cling/Interpreter/Interpreter.h index 668389928c5194b590a8b95129dfd4ea31448de2..fe94b7a8cad348bf5428998b096d58a2c0233ede 100644 --- a/interpreter/cling/include/cling/Interpreter/Interpreter.h +++ b/interpreter/cling/include/cling/Interpreter/Interpreter.h @@ -40,6 +40,7 @@ namespace clang { class FunctionDecl; class GlobalDecl; class MacroInfo; + class Module; class NamedDecl; class Parser; class Preprocessor; @@ -479,16 +480,23 @@ namespace cling { /// CompilationResult parse(const std::string& input, Transaction** T = 0) const; - - ///\brief Looks for a already generated PCM for the given header file and - /// loads it. + /// Loads a C++ Module with a given name by synthesizing an Import decl. + /// This routine checks if there is a modulemap in the current directory + /// and loads it. /// - ///\param[in] headerFile - The header file for which a module should be - /// loaded. + /// This is useful when we start up the interpreter and programatically, + /// later generate a modulemap. /// - ///\returns Whether the operation was fully successful. + ///\returns true if the module was loaded. + /// + bool loadModule(const std::string& moduleName, bool complain = true); + + /// Loads a C++ Module with a given name by synthesizing an Import decl. + /// This routine checks if there is a modulemap in the current directory + /// and loads it. /// - CompilationResult loadModuleForHeader(const std::string& headerFile); + ///\returns true if the module was loaded or already visible. + bool loadModule(clang::Module* M, bool complain = true); ///\brief Parses input line, which doesn't contain statements. Code /// generation needed to make the module functional. diff --git a/interpreter/cling/lib/Interpreter/Interpreter.cpp b/interpreter/cling/lib/Interpreter/Interpreter.cpp index 9577cf043a8753162cf5a130692e577a2f1623a9..d2fa3535998da3baf509c7d1db6a773bc9503d5a 100644 --- a/interpreter/cling/lib/Interpreter/Interpreter.cpp +++ b/interpreter/cling/lib/Interpreter/Interpreter.cpp @@ -803,9 +803,66 @@ namespace cling { return DeclareInternal(input, CO, T); } - Interpreter::CompilationResult - Interpreter::loadModuleForHeader(const std::string& headerFile) { + ///\returns true if the module was loaded. + bool Interpreter::loadModule(const std::string& moduleName, + bool complain /*= true*/) { + assert(getCI()->getLangOpts().Modules + && "Function only relevant when C++ modules are turned on!"); + + Preprocessor& PP = getCI()->getPreprocessor(); + HeaderSearch &HS = PP.getHeaderSearchInfo(); + + if (Module *M = HS.lookupModule(moduleName, /*AllowSearch*/true, + /*AllowExtraSearch*/ true)) + return loadModule(M, complain); + + if (complain) + llvm::errs() << "Module " << moduleName << " not found.\n"; + + + return false; + } + + bool Interpreter::loadModule(clang::Module* M, bool complain /* = true*/) { + assert(getCI()->getLangOpts().Modules + && "Function only relevant when C++ modules are turned on!"); + assert(M && "Module missing"); + if (getSema().isModuleVisible(M)) + return true; + Preprocessor& PP = getCI()->getPreprocessor(); + + IdentifierInfo *II = PP.getIdentifierInfo(M->Name); + SourceLocation ValidLoc = M->DefinitionLoc; + Interpreter::PushTransactionRAII RAII(this); + bool success = !getCI()->getSema().ActOnModuleImport(ValidLoc, ValidLoc, + std::make_pair(II, ValidLoc)).isInvalid(); + if (success) { + // Also make the module visible in the preprocessor to export its macros. + PP.makeModuleVisible(M, ValidLoc); + return success; + } + if (complain) { + if (M->IsSystem) + llvm::errs() << "Failed to load module " << M->Name << "\n"; + else + llvm::outs() << "Failed to load module " << M->Name << "\n"; + } + + return false; + } + + ///\brief Looks for a already generated PCM for the given header file and + /// loads it. + /// + ///\param[in] headerFile - The header file for which a module should be + /// loaded. + /// + ///\returns Whether the operation was fully successful. + /// + static Interpreter::CompilationResult + loadModuleForHeader(Interpreter& interp, const std::string& headerFile) { + Preprocessor& PP = interp.getCI()->getPreprocessor(); //Copied from clang's PPDirectives.cpp bool isAngled = false; // Clang doc says: @@ -828,8 +885,7 @@ namespace cling { // Copied from PPDirectives.cpp SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> path; for (auto mod = suggestedModule.getModule(); mod; mod = mod->Parent) { - IdentifierInfo* II - = &getSema().getPreprocessor().getIdentifierTable().get(mod->Name); + IdentifierInfo* II = &PP.getIdentifierTable().get(mod->Name); path.push_back(std::make_pair(II, fileNameLoc)); } @@ -839,10 +895,10 @@ namespace cling { // will create an implicit import declaration to capture it in the AST. bool isInclude = true; SourceLocation includeLoc; - if (getCI()->loadModule(includeLoc, path, Module::AllVisible, isInclude)) { + if (interp.getCI()->loadModule(includeLoc, path, Module::AllVisible, isInclude)) { // After module load we need to "force" Sema to generate the code for // things like dynamic classes. - getSema().ActOnEndOfTranslationUnit(); + interp.getSema().ActOnEndOfTranslationUnit(); return Interpreter::kSuccess; } @@ -1599,7 +1655,7 @@ namespace cling { if (!m_DynamicLookupDeclared && value) { // No dynlookup for the dynlookup header! m_DynamicLookupEnabled = false; - if (loadModuleForHeader("cling/Interpreter/DynamicLookupRuntimeUniverse.h") + if (loadModuleForHeader(*this, "cling/Interpreter/DynamicLookupRuntimeUniverse.h") != kSuccess) declare("#include \"cling/Interpreter/DynamicLookupRuntimeUniverse.h\""); }