diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp | 734 |
1 files changed, 400 insertions, 334 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp index cf0267549e75..688f21dd0908 100644 --- a/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/LangStandard.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" @@ -49,8 +50,6 @@ #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" -#include <sys/stat.h> -#include <system_error> #include <time.h> #include <utility> @@ -76,7 +75,7 @@ void CompilerInstance::setInvocation( bool CompilerInstance::shouldBuildGlobalModuleIndex() const { return (BuildGlobalModuleIndex || - (ModuleManager && ModuleManager->isGlobalIndexUnavailable() && + (TheASTReader && TheASTReader->isGlobalIndexUnavailable() && getFrontendOpts().GenerateGlobalModuleIndex)) && !ModuleBuildFailed; } @@ -85,6 +84,16 @@ void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) { Diagnostics = Value; } +void CompilerInstance::setVerboseOutputStream(raw_ostream &Value) { + OwnedVerboseOutputStream.release(); + VerboseOutputStream = &Value; +} + +void CompilerInstance::setVerboseOutputStream(std::unique_ptr<raw_ostream> Value) { + OwnedVerboseOutputStream.swap(Value); + VerboseOutputStream = OwnedVerboseOutputStream.get(); +} + void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; } void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; } @@ -126,13 +135,13 @@ std::unique_ptr<Sema> CompilerInstance::takeSema() { return std::move(TheSema); } -IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const { - return ModuleManager; +IntrusiveRefCntPtr<ASTReader> CompilerInstance::getASTReader() const { + return TheASTReader; } void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) { assert(ModuleCache.get() == &Reader->getModuleManager().getModuleCache() && "Expected ASTReader to use the same PCM cache"); - ModuleManager = std::move(Reader); + TheASTReader = std::move(Reader); } std::shared_ptr<ModuleDependencyCollector> @@ -161,7 +170,7 @@ static void collectIncludePCH(CompilerInstance &CI, StringRef PCHInclude = PPOpts.ImplicitPCHInclude; FileManager &FileMgr = CI.getFileManager(); - const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude); + auto PCHDir = FileMgr.getDirectory(PCHInclude); if (!PCHDir) { MDC->addFile(PCHInclude); return; @@ -169,7 +178,7 @@ static void collectIncludePCH(CompilerInstance &CI, std::error_code EC; SmallString<128> DirNative; - llvm::sys::path::native(PCHDir->getName(), DirNative); + llvm::sys::path::native((*PCHDir)->getName(), DirNative); llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); SimpleASTReaderListener Validator(CI.getPreprocessor()); for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; @@ -214,9 +223,9 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts, raw_ostream *OS = &llvm::errs(); if (DiagOpts->DiagnosticLogFile != "-") { // Create the output stream. - auto FileOS = llvm::make_unique<llvm::raw_fd_ostream>( + auto FileOS = std::make_unique<llvm::raw_fd_ostream>( DiagOpts->DiagnosticLogFile, EC, - llvm::sys::fs::F_Append | llvm::sys::fs::F_Text); + llvm::sys::fs::OF_Append | llvm::sys::fs::OF_Text); if (EC) { Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) << DiagOpts->DiagnosticLogFile << EC.message(); @@ -228,7 +237,7 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts, } // Chain in the diagnostic client which will log the diagnostics. - auto Logger = llvm::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts, + auto Logger = std::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts, std::move(StreamOwner)); if (CodeGenOpts) Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); @@ -342,7 +351,7 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags, // Remap files in the source manager (with other files). for (const auto &RF : InitOpts.RemappedFiles) { // Find the file that we're mapping to. - const FileEntry *ToFile = FileMgr.getFile(RF.second); + auto ToFile = FileMgr.getFile(RF.second); if (!ToFile) { Diags.Report(diag::err_fe_remap_missing_to_file) << RF.first << RF.second; continue; @@ -350,7 +359,7 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags, // Create the file entry for the file that we're mapping from. const FileEntry *FromFile = - FileMgr.getVirtualFile(RF.first, ToFile->getSize(), 0); + FileMgr.getVirtualFile(RF.first, (*ToFile)->getSize(), 0); if (!FromFile) { Diags.Report(diag::err_fe_remap_missing_from_file) << RF.first; continue; @@ -358,7 +367,7 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags, // Override the contents of the "from" file with the contents of // the "to" file. - SourceMgr.overrideFileContents(FromFile, ToFile); + SourceMgr.overrideFileContents(FromFile, *ToFile); } SourceMgr.setOverridenFilesKeepOriginalName( @@ -371,7 +380,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { const PreprocessorOptions &PPOpts = getPreprocessorOpts(); // The module manager holds a reference to the old preprocessor (if any). - ModuleManager.reset(); + TheASTReader.reset(); // Create the Preprocessor. HeaderSearch *HeaderInfo = @@ -485,7 +494,7 @@ void CompilerInstance::createPCHExternalASTSource( StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, void *DeserializationListener, bool OwnDeserializationListener) { bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; - ModuleManager = createPCHExternalASTSource( + TheASTReader = createPCHExternalASTSource( Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation, AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(), getASTContext(), getPCHContainerReader(), @@ -509,7 +518,8 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( PP, ModuleCache, &Context, PCHContainerRdr, Extensions, Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation, AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false, - HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex)); + HSOpts.ModulesValidateSystemHeaders, HSOpts.ValidateASTInputFilesContent, + UseGlobalModuleIndex)); // We need the external source to be set up before we read the AST, because // eagerly-deserialized declarations may use it. @@ -558,7 +568,7 @@ static bool EnableCodeCompletion(Preprocessor &PP, unsigned Column) { // Tell the source manager to chop off the given file at a specific // line and column. - const FileEntry *Entry = PP.getFileManager().getFile(Filename); + auto Entry = PP.getFileManager().getFile(Filename); if (!Entry) { PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) << Filename; @@ -566,7 +576,7 @@ static bool EnableCodeCompletion(Preprocessor &PP, } // Truncate the named file at the given line/column. - PP.SetCodeCompletionPoint(Entry, Line, Column); + PP.SetCodeCompletionPoint(*Entry, Line, Column); return false; } @@ -662,11 +672,11 @@ CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile, StringRef Extension) { return createOutputFile(getFrontendOpts().OutputFile, Binary, /*RemoveFileOnSignal=*/true, InFile, Extension, - /*UseTemporary=*/true); + getFrontendOpts().UseTemporary); } std::unique_ptr<raw_pwrite_stream> CompilerInstance::createNullOutputFile() { - return llvm::make_unique<llvm::raw_null_ostream>(); + return std::make_unique<llvm::raw_null_ostream>(); } std::unique_ptr<raw_pwrite_stream> @@ -775,7 +785,7 @@ std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile( OSFile = OutFile; OS.reset(new llvm::raw_fd_ostream( OSFile, Error, - (Binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text))); + (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text))); if (Error) return nullptr; } @@ -792,7 +802,7 @@ std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile( if (!Binary || OS->supportsSeeking()) return std::move(OS); - auto B = llvm::make_unique<llvm::buffer_ostream>(*OS); + auto B = std::make_unique<llvm::buffer_ostream>(*OS); assert(!NonSeekStream); NonSeekStream = std::move(OS); return std::move(B); @@ -830,32 +840,39 @@ bool CompilerInstance::InitializeSourceManager( // Figure out where to get and map in the main file. if (InputFile != "-") { - const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true); - if (!File) { + auto FileOrErr = FileMgr.getFileRef(InputFile, /*OpenFile=*/true); + if (!FileOrErr) { + // FIXME: include the error in the diagnostic. + consumeError(FileOrErr.takeError()); Diags.Report(diag::err_fe_error_reading) << InputFile; return false; } + FileEntryRef File = *FileOrErr; // The natural SourceManager infrastructure can't currently handle named // pipes, but we would at least like to accept them for the main // file. Detect them here, read them with the volatile flag so FileMgr will // pick up the correct size, and simply override their contents as we do for // STDIN. - if (File->isNamedPipe()) { - auto MB = FileMgr.getBufferForFile(File, /*isVolatile=*/true); + if (File.getFileEntry().isNamedPipe()) { + auto MB = + FileMgr.getBufferForFile(&File.getFileEntry(), /*isVolatile=*/true); if (MB) { // Create a new virtual file that will have the correct size. - File = FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0); - SourceMgr.overrideFileContents(File, std::move(*MB)); + const FileEntry *FE = + FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0); + SourceMgr.overrideFileContents(FE, std::move(*MB)); + SourceMgr.setMainFileID( + SourceMgr.createFileID(FE, SourceLocation(), Kind)); } else { Diags.Report(diag::err_cannot_open_file) << InputFile << MB.getError().message(); return false; } + } else { + SourceMgr.setMainFileID( + SourceMgr.createFileID(File, SourceLocation(), Kind)); } - - SourceMgr.setMainFileID( - SourceMgr.createFileID(File, SourceLocation(), Kind)); } else { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> SBOrErr = llvm::MemoryBuffer::getSTDIN(); @@ -884,9 +901,12 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); - // FIXME: Take this as an argument, once all the APIs we used have moved to - // taking it as an input instead of hard-coding llvm::errs. - raw_ostream &OS = llvm::errs(); + // Mark this point as the bottom of the stack if we don't have somewhere + // better. We generally expect frontend actions to be invoked with (nearly) + // DesiredStackSpace available. + noteBottomOfStack(); + + raw_ostream &OS = getVerboseOutputStream(); if (!Act.PrepareToExecute(*this)) return false; @@ -897,8 +917,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { if (!hasTarget()) return false; - // Create TargetInfo for the other side of CUDA and OpenMP compilation. - if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) && + // Create TargetInfo for the other side of CUDA/OpenMP/SYCL compilation. + if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice || + getLangOpts().SYCLIsDevice) && !getFrontendOpts().AuxTriple.empty()) { auto TO = std::make_shared<TargetOptions>(); TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple); @@ -986,8 +1007,8 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { StringRef StatsFile = getFrontendOpts().StatsFile; if (!StatsFile.empty()) { std::error_code EC; - auto StatS = llvm::make_unique<llvm::raw_fd_ostream>(StatsFile, EC, - llvm::sys::fs::F_Text); + auto StatS = std::make_unique<llvm::raw_fd_ostream>( + StatsFile, EC, llvm::sys::fs::OF_Text); if (EC) { getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file) << StatsFile << EC.message(); @@ -1001,14 +1022,14 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { /// Determine the appropriate source input kind based on language /// options. -static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { +static Language getLanguageFromOptions(const LangOptions &LangOpts) { if (LangOpts.OpenCL) - return InputKind::OpenCL; + return Language::OpenCL; if (LangOpts.CUDA) - return InputKind::CUDA; + return Language::CUDA; if (LangOpts.ObjC) - return LangOpts.CPlusPlus ? InputKind::ObjCXX : InputKind::ObjC; - return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C; + return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC; + return LangOpts.CPlusPlus ? Language::CXX : Language::C; } /// Compile a module file for the given module, using the options @@ -1154,16 +1175,17 @@ static const FileEntry *getPublicModuleMap(const FileEntry *File, llvm::sys::path::append(PublicFilename, "module.modulemap"); else return nullptr; - return FileMgr.getFile(PublicFilename); + if (auto FE = FileMgr.getFile(PublicFilename)) + return *FE; + return nullptr; } -/// Compile a module file for the given module, using the options -/// provided by the importing compiler instance. Returns true if the module -/// was built without errors. -static bool compileModuleImpl(CompilerInstance &ImportingInstance, - SourceLocation ImportLoc, - Module *Module, - StringRef ModuleFileName) { +/// Compile a module file for the given module in a separate compiler instance, +/// using the options provided by the importing compiler instance. Returns true +/// if the module was built without errors. +static bool compileModule(CompilerInstance &ImportingInstance, + SourceLocation ImportLoc, Module *Module, + StringRef ModuleFileName) { InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()), InputKind::ModuleMap); @@ -1223,10 +1245,17 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, return Result; } -static bool compileAndLoadModule(CompilerInstance &ImportingInstance, - SourceLocation ImportLoc, - SourceLocation ModuleNameLoc, Module *Module, - StringRef ModuleFileName) { +/// Compile a module in a separate compiler instance and read the AST, +/// returning true if the module compiles without errors. +/// +/// Uses a lock file manager and exponential backoff to reduce the chances that +/// multiple instances will compete to create the same module. On timeout, +/// deletes the lock file in order to avoid deadlock from crashing processes or +/// bugs in the lock file manager. +static bool compileModuleAndReadAST(CompilerInstance &ImportingInstance, + SourceLocation ImportLoc, + SourceLocation ModuleNameLoc, + Module *Module, StringRef ModuleFileName) { DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics(); auto diagnoseBuildFailure = [&] { @@ -1254,8 +1283,8 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, LLVM_FALLTHROUGH; case llvm::LockFileManager::LFS_Owned: // We're responsible for building the module ourselves. - if (!compileModuleImpl(ImportingInstance, ModuleNameLoc, Module, - ModuleFileName)) { + if (!compileModule(ImportingInstance, ModuleNameLoc, Module, + ModuleFileName)) { diagnoseBuildFailure(); return false; } @@ -1285,7 +1314,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, // Try to read the module file, now that we've compiled it. ASTReader::ASTReadResult ReadResult = - ImportingInstance.getModuleManager()->ReadAST( + ImportingInstance.getASTReader()->ReadAST( ModuleFileName, serialization::MK_ImplicitModule, ImportLoc, ModuleLoadCapabilities); @@ -1367,22 +1396,22 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, /// Write a new timestamp file with the given path. static void writeTimestampFile(StringRef TimestampFile) { std::error_code EC; - llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None); + llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::OF_None); } /// Prune the module cache of modules that haven't been accessed in /// a long time. static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { - struct stat StatBuf; + llvm::sys::fs::file_status StatBuf; llvm::SmallString<128> TimestampFile; TimestampFile = HSOpts.ModuleCachePath; assert(!TimestampFile.empty()); llvm::sys::path::append(TimestampFile, "modules.timestamp"); // Try to stat() the timestamp file. - if (::stat(TimestampFile.c_str(), &StatBuf)) { + if (std::error_code EC = llvm::sys::fs::status(TimestampFile, StatBuf)) { // If the timestamp file wasn't there, create one now. - if (errno == ENOENT) { + if (EC == std::errc::no_such_file_or_directory) { writeTimestampFile(TimestampFile); } return; @@ -1390,7 +1419,8 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { // Check whether the time stamp is older than our pruning interval. // If not, do nothing. - time_t TimeStampModTime = StatBuf.st_mtime; + time_t TimeStampModTime = + llvm::sys::toTimeT(StatBuf.getLastModificationTime()); time_t CurrentTime = time(nullptr); if (CurrentTime - TimeStampModTime <= time_t(HSOpts.ModuleCachePruneInterval)) return; @@ -1422,11 +1452,11 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { // Look at this file. If we can't stat it, there's nothing interesting // there. - if (::stat(File->path().c_str(), &StatBuf)) + if (llvm::sys::fs::status(File->path(), StatBuf)) continue; // If the file has been used recently enough, leave it there. - time_t FileAccessTime = StatBuf.st_atime; + time_t FileAccessTime = llvm::sys::toTimeT(StatBuf.getLastAccessedTime()); if (CurrentTime - FileAccessTime <= time_t(HSOpts.ModuleCachePruneAfter)) { continue; @@ -1448,51 +1478,52 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { } } -void CompilerInstance::createModuleManager() { - if (!ModuleManager) { - if (!hasASTContext()) - createASTContext(); +void CompilerInstance::createASTReader() { + if (TheASTReader) + return; - // If we're implicitly building modules but not currently recursively - // building a module, check whether we need to prune the module cache. - if (getSourceManager().getModuleBuildStack().empty() && - !getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty() && - getHeaderSearchOpts().ModuleCachePruneInterval > 0 && - getHeaderSearchOpts().ModuleCachePruneAfter > 0) { - pruneModuleCache(getHeaderSearchOpts()); - } + if (!hasASTContext()) + createASTContext(); - HeaderSearchOptions &HSOpts = getHeaderSearchOpts(); - std::string Sysroot = HSOpts.Sysroot; - const PreprocessorOptions &PPOpts = getPreprocessorOpts(); - std::unique_ptr<llvm::Timer> ReadTimer; - if (FrontendTimerGroup) - ReadTimer = llvm::make_unique<llvm::Timer>("reading_modules", - "Reading modules", - *FrontendTimerGroup); - ModuleManager = new ASTReader( - getPreprocessor(), getModuleCache(), &getASTContext(), - getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions, - Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, - /*AllowASTWithCompilerErrors=*/false, - /*AllowConfigurationMismatch=*/false, - HSOpts.ModulesValidateSystemHeaders, - getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer)); - if (hasASTConsumer()) { - ModuleManager->setDeserializationListener( + // If we're implicitly building modules but not currently recursively + // building a module, check whether we need to prune the module cache. + if (getSourceManager().getModuleBuildStack().empty() && + !getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty() && + getHeaderSearchOpts().ModuleCachePruneInterval > 0 && + getHeaderSearchOpts().ModuleCachePruneAfter > 0) { + pruneModuleCache(getHeaderSearchOpts()); + } + + HeaderSearchOptions &HSOpts = getHeaderSearchOpts(); + std::string Sysroot = HSOpts.Sysroot; + const PreprocessorOptions &PPOpts = getPreprocessorOpts(); + std::unique_ptr<llvm::Timer> ReadTimer; + if (FrontendTimerGroup) + ReadTimer = std::make_unique<llvm::Timer>("reading_modules", + "Reading modules", + *FrontendTimerGroup); + TheASTReader = new ASTReader( + getPreprocessor(), getModuleCache(), &getASTContext(), + getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions, + Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, + /*AllowASTWithCompilerErrors=*/false, + /*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders, + HSOpts.ValidateASTInputFilesContent, + getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer)); + if (hasASTConsumer()) { + TheASTReader->setDeserializationListener( getASTConsumer().GetASTDeserializationListener()); - getASTContext().setASTMutationListener( - getASTConsumer().GetASTMutationListener()); - } - getASTContext().setExternalSource(ModuleManager); - if (hasSema()) - ModuleManager->InitializeSema(getSema()); - if (hasASTConsumer()) - ModuleManager->StartTranslationUnit(&getASTConsumer()); - - for (auto &Listener : DependencyCollectors) - Listener->attachToASTReader(*ModuleManager); + getASTContext().setASTMutationListener( + getASTConsumer().GetASTMutationListener()); } + getASTContext().setExternalSource(TheASTReader); + if (hasSema()) + TheASTReader->InitializeSema(getSema()); + if (hasASTConsumer()) + TheASTReader->StartTranslationUnit(&getASTConsumer()); + + for (auto &Listener : DependencyCollectors) + Listener->attachToASTReader(*TheASTReader); } bool CompilerInstance::loadModuleFile(StringRef FileName) { @@ -1517,12 +1548,9 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { } void registerAll() { - for (auto *II : LoadedModules) { - CI.KnownModules[II] = CI.getPreprocessor() - .getHeaderSearchInfo() - .getModuleMap() - .findModule(II->getName()); - } + ModuleMap &MM = CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + for (auto *II : LoadedModules) + MM.cacheModuleLoad(*II, MM.findModule(II->getName())); LoadedModules.clear(); } @@ -1552,8 +1580,8 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { }; // If we don't already have an ASTReader, create one now. - if (!ModuleManager) - createModuleManager(); + if (!TheASTReader) + createASTReader(); // If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the // ASTReader to diagnose it, since it can produce better errors that we can. @@ -1562,13 +1590,13 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { SourceLocation()) <= DiagnosticsEngine::Warning; - auto Listener = llvm::make_unique<ReadModuleNames>(*this); + auto Listener = std::make_unique<ReadModuleNames>(*this); auto &ListenerRef = *Listener; - ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager, + ASTReader::ListenerScope ReadModuleNamesListener(*TheASTReader, std::move(Listener)); // Try to load the module file. - switch (ModuleManager->ReadAST( + switch (TheASTReader->ReadAST( FileName, serialization::MK_ExplicitModule, SourceLocation(), ConfigMismatchIsRecoverable ? ASTReader::ARR_ConfigurationMismatch : 0)) { case ASTReader::Success: @@ -1591,6 +1619,220 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { } } +namespace { +enum ModuleSource { + MS_ModuleNotFound, + MS_ModuleCache, + MS_PrebuiltModulePath, + MS_ModuleBuildPragma +}; +} // end namespace + +/// Select a source for loading the named module and compute the filename to +/// load it from. +static ModuleSource +selectModuleSource(Module *M, StringRef ModuleName, std::string &ModuleFilename, + const std::map<std::string, std::string> &BuiltModules, + HeaderSearch &HS) { + assert(ModuleFilename.empty() && "Already has a module source?"); + + // Check to see if the module has been built as part of this compilation + // via a module build pragma. + auto BuiltModuleIt = BuiltModules.find(ModuleName); + if (BuiltModuleIt != BuiltModules.end()) { + ModuleFilename = BuiltModuleIt->second; + return MS_ModuleBuildPragma; + } + + // Try to load the module from the prebuilt module path. + const HeaderSearchOptions &HSOpts = HS.getHeaderSearchOpts(); + if (!HSOpts.PrebuiltModuleFiles.empty() || + !HSOpts.PrebuiltModulePaths.empty()) { + ModuleFilename = HS.getPrebuiltModuleFileName(ModuleName); + if (!ModuleFilename.empty()) + return MS_PrebuiltModulePath; + } + + // Try to load the module from the module cache. + if (M) { + ModuleFilename = HS.getCachedModuleFileName(M); + return MS_ModuleCache; + } + + return MS_ModuleNotFound; +} + +ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( + StringRef ModuleName, SourceLocation ImportLoc, + SourceLocation ModuleNameLoc, bool IsInclusionDirective) { + // Search for a module with the given name. + HeaderSearch &HS = PP->getHeaderSearchInfo(); + Module *M = HS.lookupModule(ModuleName, true, !IsInclusionDirective); + + // Select the source and filename for loading the named module. + std::string ModuleFilename; + ModuleSource Source = + selectModuleSource(M, ModuleName, ModuleFilename, BuiltModules, HS); + if (Source == MS_ModuleNotFound) { + // We can't find a module, error out here. + getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) + << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); + ModuleBuildFailed = true; + // FIXME: Why is this not cached? + return ModuleLoadResult::OtherUncachedFailure; + } + if (ModuleFilename.empty()) { + if (M && M->HasIncompatibleModuleFile) { + // We tried and failed to load a module file for this module. Fall + // back to textual inclusion for its headers. + return ModuleLoadResult::ConfigMismatch; + } + + getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled) + << ModuleName; + ModuleBuildFailed = true; + // FIXME: Why is this not cached? + return ModuleLoadResult::OtherUncachedFailure; + } + + // Create an ASTReader on demand. + if (!getASTReader()) + createASTReader(); + + // Time how long it takes to load the module. + llvm::Timer Timer; + if (FrontendTimerGroup) + Timer.init("loading." + ModuleFilename, "Loading " + ModuleFilename, + *FrontendTimerGroup); + llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); + llvm::TimeTraceScope TimeScope("Module Load", ModuleName); + + // Try to load the module file. If we are not trying to load from the + // module cache, we don't know how to rebuild modules. + unsigned ARRFlags = Source == MS_ModuleCache + ? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing + : Source == MS_PrebuiltModulePath + ? 0 + : ASTReader::ARR_ConfigurationMismatch; + switch (getASTReader()->ReadAST(ModuleFilename, + Source == MS_PrebuiltModulePath + ? serialization::MK_PrebuiltModule + : Source == MS_ModuleBuildPragma + ? serialization::MK_ExplicitModule + : serialization::MK_ImplicitModule, + ImportLoc, ARRFlags)) { + case ASTReader::Success: { + if (M) + return M; + assert(Source != MS_ModuleCache && + "missing module, but file loaded from cache"); + + // A prebuilt module is indexed as a ModuleFile; the Module does not exist + // until the first call to ReadAST. Look it up now. + M = HS.lookupModule(ModuleName, true, !IsInclusionDirective); + + // Check whether M refers to the file in the prebuilt module path. + if (M && M->getASTFile()) + if (auto ModuleFile = FileMgr->getFile(ModuleFilename)) + if (*ModuleFile == M->getASTFile()) + return M; + + ModuleBuildFailed = true; + getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt) + << ModuleName; + return ModuleLoadResult(); + } + + case ASTReader::OutOfDate: + case ASTReader::Missing: + // The most interesting case. + break; + + case ASTReader::ConfigurationMismatch: + if (Source == MS_PrebuiltModulePath) + // FIXME: We shouldn't be setting HadFatalFailure below if we only + // produce a warning here! + getDiagnostics().Report(SourceLocation(), + diag::warn_module_config_mismatch) + << ModuleFilename; + // Fall through to error out. + LLVM_FALLTHROUGH; + case ASTReader::VersionMismatch: + case ASTReader::HadErrors: + // FIXME: Should this set ModuleBuildFailed = true? + ModuleLoader::HadFatalFailure = true; + // FIXME: The ASTReader will already have complained, but can we shoehorn + // that diagnostic information into a more useful form? + return ModuleLoadResult(); + + case ASTReader::Failure: + // FIXME: Should this set ModuleBuildFailed = true? + ModuleLoader::HadFatalFailure = true; + return ModuleLoadResult(); + } + + // ReadAST returned Missing or OutOfDate. + if (Source != MS_ModuleCache) { + // We don't know the desired configuration for this module and don't + // necessarily even have a module map. Since ReadAST already produces + // diagnostics for these two cases, we simply error out here. + ModuleBuildFailed = true; + return ModuleLoadResult(); + } + + // The module file is missing or out-of-date. Build it. + assert(M && "missing module, but trying to compile for cache"); + + // Check whether there is a cycle in the module graph. + ModuleBuildStack ModPath = getSourceManager().getModuleBuildStack(); + ModuleBuildStack::iterator Pos = ModPath.begin(), PosEnd = ModPath.end(); + for (; Pos != PosEnd; ++Pos) { + if (Pos->first == ModuleName) + break; + } + + if (Pos != PosEnd) { + SmallString<256> CyclePath; + for (; Pos != PosEnd; ++Pos) { + CyclePath += Pos->first; + CyclePath += " -> "; + } + CyclePath += ModuleName; + + getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) + << ModuleName << CyclePath; + // FIXME: Should this set ModuleBuildFailed = true? + // FIXME: Why is this not cached? + return ModuleLoadResult::OtherUncachedFailure; + } + + // Check whether we have already attempted to build this module (but + // failed). + if (getPreprocessorOpts().FailedModules && + getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { + getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) + << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); + ModuleBuildFailed = true; + // FIXME: Why is this not cached? + return ModuleLoadResult::OtherUncachedFailure; + } + + // Try to compile and then read the AST. + if (!compileModuleAndReadAST(*this, ImportLoc, ModuleNameLoc, M, + ModuleFilename)) { + assert(getDiagnostics().hasErrorOccurred() && + "undiagnosed error in compileModuleAndReadAST"); + if (getPreprocessorOpts().FailedModules) + getPreprocessorOpts().FailedModules->addFailed(ModuleName); + ModuleBuildFailed = true; + // FIXME: Why is this not cached? + return ModuleLoadResult::OtherUncachedFailure; + } + + // Okay, we've rebuilt and now loaded the module. + return M; +} + ModuleLoadResult CompilerInstance::loadModule(SourceLocation ImportLoc, ModuleIdPath Path, @@ -1606,19 +1848,17 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, if (ImportLoc.isValid() && LastModuleImportLoc == ImportLoc) { // Make the named module visible. if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule) - ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility, - ImportLoc); + TheASTReader->makeModuleVisible(LastModuleImportResult, Visibility, + ImportLoc); return LastModuleImportResult; } - clang::Module *Module = nullptr; - // If we don't already have information on this module, load the module now. - llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known - = KnownModules.find(Path[0].first); - if (Known != KnownModules.end()) { - // Retrieve the cached top-level module. - Module = Known->second; + Module *Module = nullptr; + ModuleMap &MM = getPreprocessor().getHeaderSearchInfo().getModuleMap(); + if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) { + // Use the cached result, which may be nullptr. + Module = *MaybeModule; } else if (ModuleName == getLangOpts().CurrentModule) { // This is the module we're building. Module = PP->getHeaderSearchInfo().lookupModule( @@ -1632,197 +1872,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // ModuleBuildFailed = true; // return ModuleLoadResult(); //} - Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; + MM.cacheModuleLoad(*Path[0].first, Module); } else { - // Search for a module with the given name. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, - !IsInclusionDirective); - HeaderSearchOptions &HSOpts = - PP->getHeaderSearchInfo().getHeaderSearchOpts(); - - std::string ModuleFileName; - enum ModuleSource { - ModuleNotFound, ModuleCache, PrebuiltModulePath, ModuleBuildPragma - } Source = ModuleNotFound; - - // Check to see if the module has been built as part of this compilation - // via a module build pragma. - auto BuiltModuleIt = BuiltModules.find(ModuleName); - if (BuiltModuleIt != BuiltModules.end()) { - ModuleFileName = BuiltModuleIt->second; - Source = ModuleBuildPragma; - } - - // Try to load the module from the prebuilt module path. - if (Source == ModuleNotFound && (!HSOpts.PrebuiltModuleFiles.empty() || - !HSOpts.PrebuiltModulePaths.empty())) { - ModuleFileName = - PP->getHeaderSearchInfo().getPrebuiltModuleFileName(ModuleName); - if (!ModuleFileName.empty()) - Source = PrebuiltModulePath; - } - - // Try to load the module from the module cache. - if (Source == ModuleNotFound && Module) { - ModuleFileName = PP->getHeaderSearchInfo().getCachedModuleFileName(Module); - Source = ModuleCache; - } - - if (Source == ModuleNotFound) { - // We can't find a module, error out here. - getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) - << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - if (ModuleFileName.empty()) { - if (Module && Module->HasIncompatibleModuleFile) { - // We tried and failed to load a module file for this module. Fall - // back to textual inclusion for its headers. - return ModuleLoadResult::ConfigMismatch; - } - - getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled) - << ModuleName; - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - // If we don't already have an ASTReader, create one now. - if (!ModuleManager) - createModuleManager(); - - llvm::Timer Timer; - if (FrontendTimerGroup) - Timer.init("loading." + ModuleFileName, "Loading " + ModuleFileName, - *FrontendTimerGroup); - llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); - llvm::TimeTraceScope TimeScope("Module Load", ModuleName); - - // Try to load the module file. If we are not trying to load from the - // module cache, we don't know how to rebuild modules. - unsigned ARRFlags = Source == ModuleCache ? - ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing : - Source == PrebuiltModulePath ? - 0 : - ASTReader::ARR_ConfigurationMismatch; - switch (ModuleManager->ReadAST(ModuleFileName, - Source == PrebuiltModulePath - ? serialization::MK_PrebuiltModule - : Source == ModuleBuildPragma - ? serialization::MK_ExplicitModule - : serialization::MK_ImplicitModule, - ImportLoc, ARRFlags)) { - case ASTReader::Success: { - if (Source != ModuleCache && !Module) { - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, - !IsInclusionDirective); - if (!Module || !Module->getASTFile() || - FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { - // Error out if Module does not refer to the file in the prebuilt - // module path. - getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt) - << ModuleName; - ModuleBuildFailed = true; - KnownModules[Path[0].first] = nullptr; - return ModuleLoadResult(); - } - } - break; - } - - case ASTReader::OutOfDate: - case ASTReader::Missing: { - if (Source != ModuleCache) { - // We don't know the desired configuration for this module and don't - // necessarily even have a module map. Since ReadAST already produces - // diagnostics for these two cases, we simply error out here. - ModuleBuildFailed = true; - KnownModules[Path[0].first] = nullptr; - return ModuleLoadResult(); - } - - // The module file is missing or out-of-date. Build it. - assert(Module && "missing module file"); - // Check whether there is a cycle in the module graph. - ModuleBuildStack ModPath = getSourceManager().getModuleBuildStack(); - ModuleBuildStack::iterator Pos = ModPath.begin(), PosEnd = ModPath.end(); - for (; Pos != PosEnd; ++Pos) { - if (Pos->first == ModuleName) - break; - } - - if (Pos != PosEnd) { - SmallString<256> CyclePath; - for (; Pos != PosEnd; ++Pos) { - CyclePath += Pos->first; - CyclePath += " -> "; - } - CyclePath += ModuleName; - - getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) - << ModuleName << CyclePath; - return ModuleLoadResult(); - } - - // Check whether we have already attempted to build this module (but - // failed). - if (getPreprocessorOpts().FailedModules && - getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { - getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) - << ModuleName - << SourceRange(ImportLoc, ModuleNameLoc); - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - // Try to compile and then load the module. - if (!compileAndLoadModule(*this, ImportLoc, ModuleNameLoc, Module, - ModuleFileName)) { - assert(getDiagnostics().hasErrorOccurred() && - "undiagnosed error in compileAndLoadModule"); - if (getPreprocessorOpts().FailedModules) - getPreprocessorOpts().FailedModules->addFailed(ModuleName); - KnownModules[Path[0].first] = nullptr; - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - // Okay, we've rebuilt and now loaded the module. - break; - } - - case ASTReader::ConfigurationMismatch: - if (Source == PrebuiltModulePath) - // FIXME: We shouldn't be setting HadFatalFailure below if we only - // produce a warning here! - getDiagnostics().Report(SourceLocation(), - diag::warn_module_config_mismatch) - << ModuleFileName; - // Fall through to error out. - LLVM_FALLTHROUGH; - case ASTReader::VersionMismatch: - case ASTReader::HadErrors: - ModuleLoader::HadFatalFailure = true; - // FIXME: The ASTReader will already have complained, but can we shoehorn - // that diagnostic information into a more useful form? - KnownModules[Path[0].first] = nullptr; - return ModuleLoadResult(); - - case ASTReader::Failure: - ModuleLoader::HadFatalFailure = true; - // Already complained, but note now that we failed. - KnownModules[Path[0].first] = nullptr; - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - // Cache the result of this top-level module lookup for later. - Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; + ModuleLoadResult Result = findOrCompileModuleAndReadAST( + ModuleName, ImportLoc, ModuleNameLoc, IsInclusionDirective); + // FIXME: Can we pull 'ModuleBuildFailed = true' out of the return + // sequences for findOrCompileModuleAndReadAST and do it here (as long as + // the result is not a config mismatch)? See FIXMEs there. + if (!Result.isNormal()) + return Result; + Module = Result; + MM.cacheModuleLoad(*Path[0].first, Module); + if (!Module) + return Module; } - // If we never found the module, fail. + // If we never found the module, fail. Otherwise, verify the module and link + // it up. if (!Module) return ModuleLoadResult(); @@ -1942,7 +2008,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return ModuleLoadResult(); } - ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc); + TheASTReader->makeModuleVisible(Module, Visibility, ImportLoc); } // Check for any configuration macros that have changed. @@ -1963,9 +2029,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return LastModuleImportResult; } -void CompilerInstance::loadModuleFromSource(SourceLocation ImportLoc, - StringRef ModuleName, - StringRef Source) { +void CompilerInstance::createModuleFromSource(SourceLocation ImportLoc, + StringRef ModuleName, + StringRef Source) { // Avoid creating filenames with special characters. SmallString<128> CleanModuleName(ModuleName); for (auto &C : CleanModuleName) @@ -2019,27 +2085,27 @@ void CompilerInstance::loadModuleFromSource(SourceLocation ImportLoc, void CompilerInstance::makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, SourceLocation ImportLoc) { - if (!ModuleManager) - createModuleManager(); - if (!ModuleManager) + if (!TheASTReader) + createASTReader(); + if (!TheASTReader) return; - ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc); + TheASTReader->makeModuleVisible(Mod, Visibility, ImportLoc); } GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( SourceLocation TriggerLoc) { if (getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty()) return nullptr; - if (!ModuleManager) - createModuleManager(); + if (!TheASTReader) + createASTReader(); // Can't do anything if we don't have the module manager. - if (!ModuleManager) + if (!TheASTReader) return nullptr; // Get an existing global index. This loads it if not already // loaded. - ModuleManager->loadGlobalIndex(); - GlobalModuleIndex *GlobalIndex = ModuleManager->getGlobalIndex(); + TheASTReader->loadGlobalIndex(); + GlobalModuleIndex *GlobalIndex = TheASTReader->getGlobalIndex(); // If the global index doesn't exist, create it. if (!GlobalIndex && shouldBuildGlobalModuleIndex() && hasFileManager() && hasPreprocessor()) { @@ -2055,9 +2121,9 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( consumeError(std::move(Err)); return nullptr; } - ModuleManager->resetForReload(); - ModuleManager->loadGlobalIndex(); - GlobalIndex = ModuleManager->getGlobalIndex(); + TheASTReader->resetForReload(); + TheASTReader->loadGlobalIndex(); + GlobalIndex = TheASTReader->getGlobalIndex(); } // For finding modules needing to be imported for fixit messages, // we need to make the global index cover all modules, so we do that here. @@ -2086,9 +2152,9 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( consumeError(std::move(Err)); return nullptr; } - ModuleManager->resetForReload(); - ModuleManager->loadGlobalIndex(); - GlobalIndex = ModuleManager->getGlobalIndex(); + TheASTReader->resetForReload(); + TheASTReader->loadGlobalIndex(); + GlobalIndex = TheASTReader->getGlobalIndex(); } HaveFullGlobalModuleIndex = true; } |
