diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp | 306 |
1 files changed, 215 insertions, 91 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp index c996c9c486bc..eff785b99a09 100644 --- a/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp @@ -11,28 +11,37 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclGroup.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/LangStandard.h" +#include "clang/Basic/Sarif.h" +#include "clang/Basic/Stack.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/LayoutOverrideSource.h" #include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Frontend/SARIFDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/ParseAST.h" +#include "clang/Sema/HLSLExternalSemaSource.h" +#include "clang/Sema/MultiplexExternalSemaSource.h" #include "clang/Serialization/ASTDeserializationListener.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/GlobalModuleIndex.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include <memory> #include <system_error> using namespace clang; @@ -53,6 +62,11 @@ public: delete Previous; } + DelegatingDeserializationListener(const DelegatingDeserializationListener &) = + delete; + DelegatingDeserializationListener & + operator=(const DelegatingDeserializationListener &) = delete; + void ReaderInitialized(ASTReader *Reader) override { if (Previous) Previous->ReaderInitialized(Reader); @@ -143,7 +157,7 @@ void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput, Module *FrontendAction::getCurrentModule() const { CompilerInstance &CI = getCompilerInstance(); return CI.getPreprocessor().getHeaderSearchInfo().lookupModule( - CI.getLangOpts().CurrentModule, /*AllowSearch*/false); + CI.getLangOpts().CurrentModule, SourceLocation(), /*AllowSearch*/false); } std::unique_ptr<ASTConsumer> @@ -186,14 +200,17 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, FrontendPluginRegistry::entries()) { std::unique_ptr<PluginASTAction> P = Plugin.instantiate(); PluginASTAction::ActionType ActionType = P->getActionType(); - if (ActionType == PluginASTAction::Cmdline) { + if (ActionType == PluginASTAction::CmdlineAfterMainAction || + ActionType == PluginASTAction::CmdlineBeforeMainAction) { // This is O(|plugins| * |add_plugins|), but since both numbers are // way below 50 in practice, that's ok. - if (llvm::any_of(CI.getFrontendOpts().AddPluginActions, - [&](const std::string &PluginAction) { - return PluginAction == Plugin.getName(); - })) - ActionType = PluginASTAction::AddAfterMainAction; + if (llvm::is_contained(CI.getFrontendOpts().AddPluginActions, + Plugin.getName())) { + if (ActionType == PluginASTAction::CmdlineBeforeMainAction) + ActionType = PluginASTAction::AddBeforeMainAction; + else + ActionType = PluginASTAction::AddAfterMainAction; + } } if ((ActionType == PluginASTAction::AddBeforeMainAction || ActionType == PluginASTAction::AddAfterMainAction) && @@ -211,8 +228,13 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, // Add to Consumers the main consumer, then all the plugins that go after it Consumers.push_back(std::move(Consumer)); - for (auto &C : AfterConsumers) { - Consumers.push_back(std::move(C)); + if (!AfterConsumers.empty()) { + // If we have plugins after the main consumer, which may be the codegen + // action, they likely will need the ASTContext, so don't clear it in the + // codegen action. + CI.getCodeGenOpts().ClearASTBeforeBackend = false; + for (auto &C : AfterConsumers) + Consumers.push_back(std::move(C)); } return std::make_unique<MultiplexConsumer>(std::move(Consumers)); @@ -320,7 +342,7 @@ static std::error_code collectModuleHeaderIncludes( return std::error_code(); // Resolve all lazy header directives to header files. - ModMap.resolveHeaderDirectives(Module); + ModMap.resolveHeaderDirectives(Module, /*File=*/std::nullopt); // If any headers are missing, we can't build this module. In most cases, // diagnostics for this should have already been produced; we only get here @@ -348,20 +370,22 @@ static std::error_code collectModuleHeaderIncludes( } // Note that Module->PrivateHeaders will not be a TopHeader. - if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { - Module->addTopHeader(UmbrellaHeader.Entry); + if (std::optional<Module::Header> UmbrellaHeader = + Module->getUmbrellaHeaderAsWritten()) { + Module->addTopHeader(UmbrellaHeader->Entry); if (Module->Parent) // Include the umbrella header for submodules. - addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory, + addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory, Includes, LangOpts, Module->IsExternC); - } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { + } else if (std::optional<Module::DirectoryName> UmbrellaDir = + Module->getUmbrellaDirAsWritten()) { // Add all of the headers we find in this subdirectory. std::error_code EC; SmallString<128> DirNative; - llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); + llvm::sys::path::native(UmbrellaDir->Entry.getName(), DirNative); llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); - SmallVector<std::pair<std::string, const FileEntry *>, 8> Headers; + SmallVector<std::pair<std::string, FileEntryRef>, 8> Headers; for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; Dir != End && !EC; Dir.increment(EC)) { // Check whether this entry has an extension typically associated with @@ -371,7 +395,7 @@ static std::error_code collectModuleHeaderIncludes( .Default(false)) continue; - auto Header = FileMgr.getFile(Dir->path()); + auto Header = FileMgr.getOptionalFileRef(Dir->path()); // FIXME: This shouldn't happen unless there is a file system race. Is // that worth diagnosing? if (!Header) @@ -388,7 +412,7 @@ static std::error_code collectModuleHeaderIncludes( for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) Components.push_back(*PathIt); SmallString<128> RelativeHeader( - UmbrellaDir.PathRelativeToRootModuleDirectory); + UmbrellaDir->PathRelativeToRootModuleDirectory); for (auto It = Components.rbegin(), End = Components.rend(); It != End; ++It) llvm::sys::path::append(RelativeHeader, *It); @@ -402,11 +426,7 @@ static std::error_code collectModuleHeaderIncludes( // Sort header paths and make the header inclusion order deterministic // across different OSs and filesystems. - llvm::sort(Headers.begin(), Headers.end(), []( - const std::pair<std::string, const FileEntry *> &LHS, - const std::pair<std::string, const FileEntry *> &RHS) { - return LHS.first < RHS.first; - }); + llvm::sort(Headers, llvm::less_first()); for (auto &H : Headers) { // Include this header as part of the umbrella directory. Module->addTopHeader(H.second); @@ -415,11 +435,9 @@ static std::error_code collectModuleHeaderIncludes( } // Recurse into submodules. - for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), - SubEnd = Module->submodule_end(); - Sub != SubEnd; ++Sub) + for (auto *Submodule : Module->submodules()) if (std::error_code Err = collectModuleHeaderIncludes( - LangOpts, FileMgr, Diag, ModMap, *Sub, Includes)) + LangOpts, FileMgr, Diag, ModMap, Submodule, Includes)) return Err; return std::error_code(); @@ -434,7 +452,8 @@ static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem, // Map the current input to a file. FileID ModuleMapID = SrcMgr.getMainFileID(); - const FileEntry *ModuleMap = SrcMgr.getFileEntryForID(ModuleMapID); + OptionalFileEntryRef ModuleMap = SrcMgr.getFileEntryRefForID(ModuleMapID); + assert(ModuleMap && "MainFileID without FileEntry"); // If the module map is preprocessed, handle the initial line marker; // line directives are not part of the module map syntax in general. @@ -447,13 +466,23 @@ static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem, } // Load the module map file. - if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset, + if (HS.loadModuleMapFile(*ModuleMap, IsSystem, ModuleMapID, &Offset, PresumedModuleMapFile)) return true; if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset) Offset = 0; + // Infer framework module if possible. + if (HS.getModuleMap().canInferFrameworkModule(ModuleMap->getDir())) { + SmallString<128> InferredFrameworkPath = ModuleMap->getDir().getName(); + llvm::sys::path::append(InferredFrameworkPath, + CI.getLangOpts().ModuleName + ".framework"); + if (auto Dir = + CI.getFileManager().getOptionalDirectoryRef(InferredFrameworkPath)) + (void)HS.getModuleMap().inferFrameworkModule(*Dir, IsSystem, nullptr); + } + return false; } @@ -471,7 +500,7 @@ static Module *prepareToBuildModule(CompilerInstance &CI, // Dig out the module definition. HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); - Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, + Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, SourceLocation(), /*AllowSearch=*/true); if (!M) { CI.getDiagnostics().Report(diag::err_missing_module) @@ -481,13 +510,13 @@ static Module *prepareToBuildModule(CompilerInstance &CI, } // Check whether we can build this module at all. - if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), - CI.getDiagnostics(), M)) + if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), *M, + CI.getDiagnostics())) return nullptr; // Inform the preprocessor that includes from within the input buffer should // be resolved relative to the build directory of the module map file. - CI.getPreprocessor().setMainFileDir(M->Directory); + CI.getPreprocessor().setMainFileDir(*M->Directory); // If the module was inferred from a different module map (via an expanded // umbrella module definition), track that fact. @@ -496,15 +525,15 @@ static Module *prepareToBuildModule(CompilerInstance &CI, StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; if (!OriginalModuleMapName.empty()) { auto OriginalModuleMap = - CI.getFileManager().getFile(OriginalModuleMapName, - /*openFile*/ true); + CI.getFileManager().getOptionalFileRef(OriginalModuleMapName, + /*openFile*/ true); if (!OriginalModuleMap) { CI.getDiagnostics().Report(diag::err_module_map_not_found) << OriginalModuleMapName; return nullptr; } - if (*OriginalModuleMap != CI.getSourceManager().getFileEntryForID( - CI.getSourceManager().getMainFileID())) { + if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID( + CI.getSourceManager().getMainFileID())) { M->IsInferred = true; CI.getPreprocessor().getHeaderSearchInfo().getModuleMap() .setInferredModuleAllowedBy(M, *OriginalModuleMap); @@ -529,8 +558,9 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) { // Collect the set of #includes we need to build the module. SmallString<256> HeaderContents; std::error_code Err = std::error_code(); - if (Module::Header UmbrellaHeader = M->getUmbrellaHeader()) - addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory, + if (std::optional<Module::Header> UmbrellaHeader = + M->getUmbrellaHeaderAsWritten()) + addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory, HeaderContents, CI.getLangOpts(), M->IsExternC); Err = collectModuleHeaderIncludes( CI.getLangOpts(), FileMgr, CI.getDiagnostics(), @@ -558,8 +588,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, bool HasBegunSourceFile = false; bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled && usesPreprocessorOnly(); + + // If we fail, reset state since the client will not end up calling the + // matching EndSourceFile(). All paths that return true should release this. + auto FailureCleanup = llvm::make_scope_exit([&]() { + if (HasBegunSourceFile) + CI.getDiagnosticClient().EndSourceFile(); + CI.setASTConsumer(nullptr); + CI.clearOutputFiles(/*EraseFiles=*/true); + CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); + setCurrentInput(FrontendInputFile()); + setCompilerInstance(nullptr); + }); + if (!BeginInvocation(CI)) - goto failure; + return false; // If we're replaying the build of an AST file, import it and set up // the initial state from its build. @@ -578,9 +621,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( std::string(InputFile), CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly, ASTDiags, CI.getFileSystemOpts(), - CI.getCodeGenOpts().DebugTypeExtRefs); + /*HeaderSearchOptions=*/nullptr); if (!AST) - goto failure; + return false; // Options relating to how we treat the input (but not what we do with it) // are inherited from the AST unit. @@ -605,11 +648,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (&MF != &PrimaryModule) CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName); - ASTReader->visitTopLevelModuleMaps( - PrimaryModule, [&](const FileEntry *FE) { - CI.getFrontendOpts().ModuleMapFiles.push_back( - std::string(FE->getName())); - }); + ASTReader->visitTopLevelModuleMaps(PrimaryModule, [&](FileEntryRef FE) { + CI.getFrontendOpts().ModuleMapFiles.push_back( + std::string(FE.getName())); + }); } // Set up the input file for replay purposes. @@ -617,13 +659,14 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (Kind.getFormat() == InputKind::ModuleMap) { Module *ASTModule = AST->getPreprocessor().getHeaderSearchInfo().lookupModule( - AST->getLangOpts().CurrentModule, /*AllowSearch*/ false); + AST->getLangOpts().CurrentModule, SourceLocation(), + /*AllowSearch*/ false); assert(ASTModule && "module file does not define its own module"); Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind); } else { auto &OldSM = AST->getSourceManager(); FileID ID = OldSM.getMainFileID(); - if (auto *File = OldSM.getFileEntryForID(ID)) + if (auto File = OldSM.getFileEntryRefForID(ID)) Input = FrontendInputFile(File->getName(), Kind); else Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind); @@ -646,10 +689,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( std::string(InputFile), CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts(), - CI.getCodeGenOpts().DebugTypeExtRefs); + CI.getHeaderSearchOptsPtr()); if (!AST) - goto failure; + return false; // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); @@ -669,29 +712,36 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Initialize the action. if (!BeginSourceFileAction(CI)) - goto failure; + return false; // Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); if (!CI.hasASTConsumer()) - goto failure; + return false; + FailureCleanup.release(); return true; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) { if (!CI.createFileManager()) { - goto failure; + return false; } } - if (!CI.hasSourceManager()) + if (!CI.hasSourceManager()) { CI.createSourceManager(CI.getFileManager()); + if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) { + static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient()) + ->setSarifWriter( + std::make_unique<SarifDocumentWriter>(CI.getSourceManager())); + } + } // Set up embedding for any specified files. Do this before we load any // source files, including the primary module map for the compilation. for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { - if (auto FE = CI.getFileManager().getFile(F, /*openFile*/true)) + if (auto FE = CI.getFileManager().getOptionalFileRef(F, /*openFile*/true)) CI.getSourceManager().setFileIsTransient(*FE); else CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F; @@ -710,12 +760,13 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Initialize the action. if (!BeginSourceFileAction(CI)) - goto failure; + return false; // Initialize the main file entry. if (!CI.InitializeSourceManager(CurrentInput)) - goto failure; + return false; + FailureCleanup.release(); return true; } @@ -726,10 +777,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); StringRef PCHInclude = PPOpts.ImplicitPCHInclude; std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath(); - if (auto PCHDir = FileMgr.getDirectory(PCHInclude)) { + if (auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude)) { std::error_code EC; SmallString<128> DirNative; - llvm::sys::path::native((*PCHDir)->getName(), DirNative); + llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), @@ -737,9 +788,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile( - Dir->path(), FileMgr, CI.getPCHContainerReader(), - CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), - SpecificModuleCachePath)) { + Dir->path(), FileMgr, CI.getModuleCache(), + CI.getPCHContainerReader(), CI.getLangOpts(), + CI.getTargetOpts(), CI.getPreprocessorOpts(), + SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) { PPOpts.ImplicitPCHInclude = std::string(Dir->path()); Found = true; break; @@ -748,7 +800,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!Found) { CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; - goto failure; + return false; } } } @@ -763,9 +815,63 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, &CI.getPreprocessor()); HasBegunSourceFile = true; - // Initialize the main file entry. + // Handle C++20 header units. + // Here, the user has the option to specify that the header name should be + // looked up in the pre-processor search paths (and the main filename as + // passed by the driver might therefore be incomplete until that look-up). + if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() && + !Input.getKind().isPreprocessed()) { + StringRef FileName = Input.getFile(); + InputKind Kind = Input.getKind(); + if (Kind.getHeaderUnitKind() != InputKind::HeaderUnit_Abs) { + assert(CI.hasPreprocessor() && + "trying to build a header unit without a Pre-processor?"); + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); + // Relative searches begin from CWD. + auto Dir = CI.getFileManager().getOptionalDirectoryRef("."); + SmallVector<std::pair<OptionalFileEntryRef, DirectoryEntryRef>, 1> CWD; + CWD.push_back({std::nullopt, *Dir}); + OptionalFileEntryRef FE = + HS.LookupFile(FileName, SourceLocation(), + /*Angled*/ Input.getKind().getHeaderUnitKind() == + InputKind::HeaderUnit_System, + nullptr, nullptr, CWD, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr); + if (!FE) { + CI.getDiagnostics().Report(diag::err_module_header_file_not_found) + << FileName; + return false; + } + // We now have the filename... + FileName = FE->getName(); + // ... still a header unit, but now use the path as written. + Kind = Input.getKind().withHeaderUnit(InputKind::HeaderUnit_Abs); + Input = FrontendInputFile(FileName, Kind, Input.isSystem()); + } + // Unless the user has overridden the name, the header unit module name is + // the pathname for the file. + if (CI.getLangOpts().ModuleName.empty()) + CI.getLangOpts().ModuleName = std::string(FileName); + CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName; + } + if (!CI.InitializeSourceManager(Input)) - goto failure; + return false; + + if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() && + Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) { + // We have an input filename like foo.iih, but we want to find the right + // module name (and original file, to build the map entry). + // Check if the first line specifies the original source file name with a + // linemarker. + std::string PresumedInputFile = std::string(getCurrentFileOrBufferName()); + ReadOriginalFileName(CI, PresumedInputFile); + // Unless the user overrides this, the module name is the name by which the + // original file was known. + if (CI.getLangOpts().ModuleName.empty()) + CI.getLangOpts().ModuleName = std::string(PresumedInputFile); + CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName; + } // For module map files, we first parse the module map and synthesize a // "<module-includes>" buffer before more conventional processing. @@ -777,11 +883,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (loadModuleMapForModuleBuild(CI, Input.isSystem(), Input.isPreprocessed(), PresumedModuleMapFile, OffsetToContents)) - goto failure; + return false; auto *CurrentModule = prepareToBuildModule(CI, Input.getFile()); if (!CurrentModule) - goto failure; + return false; CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile; @@ -792,7 +898,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Otherwise, convert the module description to a suitable input buffer. auto Buffer = getInputBufferForModule(CI, CurrentModule); if (!Buffer) - goto failure; + return false; // Reinitialize the main file entry to refer to the new input. auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User; @@ -805,17 +911,20 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // Initialize the action. if (!BeginSourceFileAction(CI)) - goto failure; + return false; // If we were asked to load any module map files, do so now. for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { - if (auto File = CI.getFileManager().getFile(Filename)) + if (auto File = CI.getFileManager().getOptionalFileRef(Filename)) CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( *File, /*IsSystem*/false); else CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; } + // If compiling implementation of a module, load its module map file now. + (void)CI.getPreprocessor().getCurrentModuleImplementation(); + // Add a module declaration scope so that modules from -fmodule-map-file // arguments may shadow modules found implicitly in search paths. CI.getPreprocessor() @@ -839,7 +948,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, std::unique_ptr<ASTConsumer> Consumer = CreateWrappedASTConsumer(CI, PresumedInputFile); if (!Consumer) - goto failure; + return false; // FIXME: should not overwrite ASTMutationListener when parsing model files? if (!isModelParsingAction()) @@ -850,7 +959,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader; source = createChainedIncludesSource(CI, FinalReader); if (!source) - goto failure; + return false; CI.setASTReader(static_cast<ASTReader *>(FinalReader.get())); CI.getASTContext().setExternalSource(source); } else if (CI.getLangOpts().Modules || @@ -879,7 +988,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener, DeleteDeserialListener); if (!CI.getASTContext().getExternalSource()) - goto failure; + return false; } // If modules are enabled, create the AST reader before creating // any builtins, so that all declarations know that they might be @@ -894,7 +1003,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, CI.setASTConsumer(std::move(Consumer)); if (!CI.hasASTConsumer()) - goto failure; + return false; } // Initialize built-in info as long as we aren't using an external AST @@ -913,9 +1022,15 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, } // If we were asked to load any module files, do so now. - for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) - if (!CI.loadModuleFile(ModuleFile)) - goto failure; + for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) { + serialization::ModuleFile *Loaded = nullptr; + if (!CI.loadModuleFile(ModuleFile, Loaded)) + return false; + + if (Loaded && Loaded->StandardCXXModule) + CI.getDiagnostics().Report( + diag::warn_eagerly_load_for_standard_cplusplus_modules); + } // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. @@ -927,18 +1042,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, CI.getASTContext().setExternalSource(Override); } - return true; + // Setup HLSL External Sema Source + if (CI.getLangOpts().HLSL && CI.hasASTContext()) { + IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema( + new HLSLExternalSemaSource()); + if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>( + CI.getASTContext().getExternalSource())) { + IntrusiveRefCntPtr<ExternalSemaSource> MultiSema( + new MultiplexExternalSemaSource(SemaSource, HLSLSema.get())); + CI.getASTContext().setExternalSource(MultiSema); + } else + CI.getASTContext().setExternalSource(HLSLSema); + } - // If we failed, reset state since the client will not end up calling the - // matching EndSourceFile(). -failure: - if (HasBegunSourceFile) - CI.getDiagnosticClient().EndSourceFile(); - CI.clearOutputFiles(/*EraseFiles=*/true); - CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); - setCurrentInput(FrontendInputFile()); - setCompilerInstance(nullptr); - return false; + FailureCleanup.release(); + return true; } llvm::Error FrontendAction::Execute() { @@ -998,7 +1116,7 @@ void FrontendAction::EndSourceFile() { } if (CI.getFrontendOpts().ShowStats) { - llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n"; + llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFileOrBufferName() << "':\n"; CI.getPreprocessor().PrintStats(); CI.getPreprocessor().getIdentifierTable().PrintStats(); CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); @@ -1010,6 +1128,9 @@ void FrontendAction::EndSourceFile() { // FrontendAction. CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles()); + // The resources are owned by AST when the current file is AST. + // So we reset the resources here to avoid users accessing it + // accidently. if (isCurrentFileAST()) { if (DisableFree) { CI.resetAndLeakPreprocessor(); @@ -1040,6 +1161,10 @@ void ASTFrontendAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); if (!CI.hasPreprocessor()) return; + // This is a fallback: If the client forgets to invoke this, we mark the + // current stack as the bottom. Though not optimal, this could help prevent + // stack overflow during deep recursion. + clang::noteBottomOfStack(); // FIXME: Move the truncation aspect of this into Sema, we delayed this till // here so the source manager would be initialized. @@ -1119,4 +1244,3 @@ bool WrapperFrontendAction::hasCodeCompletionSupport() const { WrapperFrontendAction::WrapperFrontendAction( std::unique_ptr<FrontendAction> WrappedAction) : WrappedAction(std::move(WrappedAction)) {} - |