10b57cec5SDimitry Andric //===--- FrontendAction.cpp -----------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "clang/Frontend/FrontendAction.h" 100b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h" 110b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 120b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h" 13480093f4SDimitry Andric #include "clang/Basic/Builtins.h" 14bdd1243dSDimitry Andric #include "clang/Basic/DiagnosticOptions.h" 15bdd1243dSDimitry Andric #include "clang/Basic/FileEntry.h" 16a7dea167SDimitry Andric #include "clang/Basic/LangStandard.h" 17bdd1243dSDimitry Andric #include "clang/Basic/Sarif.h" 188a4dda33SDimitry Andric #include "clang/Basic/Stack.h" 190b57cec5SDimitry Andric #include "clang/Frontend/ASTUnit.h" 200b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 210b57cec5SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h" 220b57cec5SDimitry Andric #include "clang/Frontend/FrontendPluginRegistry.h" 230b57cec5SDimitry Andric #include "clang/Frontend/LayoutOverrideSource.h" 240b57cec5SDimitry Andric #include "clang/Frontend/MultiplexConsumer.h" 25bdd1243dSDimitry Andric #include "clang/Frontend/SARIFDiagnosticPrinter.h" 260b57cec5SDimitry Andric #include "clang/Frontend/Utils.h" 270b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h" 280b57cec5SDimitry Andric #include "clang/Lex/LiteralSupport.h" 290b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 300b57cec5SDimitry Andric #include "clang/Lex/PreprocessorOptions.h" 310b57cec5SDimitry Andric #include "clang/Parse/ParseAST.h" 32753f127fSDimitry Andric #include "clang/Sema/HLSLExternalSemaSource.h" 33bdd1243dSDimitry Andric #include "clang/Sema/MultiplexExternalSemaSource.h" 340b57cec5SDimitry Andric #include "clang/Serialization/ASTDeserializationListener.h" 350b57cec5SDimitry Andric #include "clang/Serialization/ASTReader.h" 360b57cec5SDimitry Andric #include "clang/Serialization/GlobalModuleIndex.h" 37349cc55cSDimitry Andric #include "llvm/ADT/ScopeExit.h" 380b57cec5SDimitry Andric #include "llvm/Support/BuryPointer.h" 390b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 400b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 410b57cec5SDimitry Andric #include "llvm/Support/Path.h" 420b57cec5SDimitry Andric #include "llvm/Support/Timer.h" 430b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 44bdd1243dSDimitry Andric #include <memory> 450b57cec5SDimitry Andric #include <system_error> 460b57cec5SDimitry Andric using namespace clang; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry) 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric namespace { 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric class DelegatingDeserializationListener : public ASTDeserializationListener { 530b57cec5SDimitry Andric ASTDeserializationListener *Previous; 540b57cec5SDimitry Andric bool DeletePrevious; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric public: 570b57cec5SDimitry Andric explicit DelegatingDeserializationListener( 580b57cec5SDimitry Andric ASTDeserializationListener *Previous, bool DeletePrevious) 590b57cec5SDimitry Andric : Previous(Previous), DeletePrevious(DeletePrevious) {} 600b57cec5SDimitry Andric ~DelegatingDeserializationListener() override { 610b57cec5SDimitry Andric if (DeletePrevious) 620b57cec5SDimitry Andric delete Previous; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 655f757f3fSDimitry Andric DelegatingDeserializationListener(const DelegatingDeserializationListener &) = 665f757f3fSDimitry Andric delete; 675f757f3fSDimitry Andric DelegatingDeserializationListener & 685f757f3fSDimitry Andric operator=(const DelegatingDeserializationListener &) = delete; 695f757f3fSDimitry Andric 700b57cec5SDimitry Andric void ReaderInitialized(ASTReader *Reader) override { 710b57cec5SDimitry Andric if (Previous) 720b57cec5SDimitry Andric Previous->ReaderInitialized(Reader); 730b57cec5SDimitry Andric } 74*0fca6ea1SDimitry Andric void IdentifierRead(serialization::IdentifierID ID, 750b57cec5SDimitry Andric IdentifierInfo *II) override { 760b57cec5SDimitry Andric if (Previous) 770b57cec5SDimitry Andric Previous->IdentifierRead(ID, II); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric void TypeRead(serialization::TypeIdx Idx, QualType T) override { 800b57cec5SDimitry Andric if (Previous) 810b57cec5SDimitry Andric Previous->TypeRead(Idx, T); 820b57cec5SDimitry Andric } 83*0fca6ea1SDimitry Andric void DeclRead(GlobalDeclID ID, const Decl *D) override { 840b57cec5SDimitry Andric if (Previous) 850b57cec5SDimitry Andric Previous->DeclRead(ID, D); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric void SelectorRead(serialization::SelectorID ID, Selector Sel) override { 880b57cec5SDimitry Andric if (Previous) 890b57cec5SDimitry Andric Previous->SelectorRead(ID, Sel); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric void MacroDefinitionRead(serialization::PreprocessedEntityID PPID, 920b57cec5SDimitry Andric MacroDefinitionRecord *MD) override { 930b57cec5SDimitry Andric if (Previous) 940b57cec5SDimitry Andric Previous->MacroDefinitionRead(PPID, MD); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric }; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /// Dumps deserialized declarations. 990b57cec5SDimitry Andric class DeserializedDeclsDumper : public DelegatingDeserializationListener { 1000b57cec5SDimitry Andric public: 1010b57cec5SDimitry Andric explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous, 1020b57cec5SDimitry Andric bool DeletePrevious) 1030b57cec5SDimitry Andric : DelegatingDeserializationListener(Previous, DeletePrevious) {} 1040b57cec5SDimitry Andric 105*0fca6ea1SDimitry Andric void DeclRead(GlobalDeclID ID, const Decl *D) override { 1060b57cec5SDimitry Andric llvm::outs() << "PCH DECL: " << D->getDeclKindName(); 1070b57cec5SDimitry Andric if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { 1080b57cec5SDimitry Andric llvm::outs() << " - "; 1090b57cec5SDimitry Andric ND->printQualifiedName(llvm::outs()); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric llvm::outs() << "\n"; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric DelegatingDeserializationListener::DeclRead(ID, D); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric }; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric /// Checks deserialized declarations and emits error if a name 1180b57cec5SDimitry Andric /// matches one given in command-line using -error-on-deserialized-decl. 1190b57cec5SDimitry Andric class DeserializedDeclsChecker : public DelegatingDeserializationListener { 1200b57cec5SDimitry Andric ASTContext &Ctx; 1210b57cec5SDimitry Andric std::set<std::string> NamesToCheck; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric public: 1240b57cec5SDimitry Andric DeserializedDeclsChecker(ASTContext &Ctx, 1250b57cec5SDimitry Andric const std::set<std::string> &NamesToCheck, 1260b57cec5SDimitry Andric ASTDeserializationListener *Previous, 1270b57cec5SDimitry Andric bool DeletePrevious) 1280b57cec5SDimitry Andric : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx), 1290b57cec5SDimitry Andric NamesToCheck(NamesToCheck) {} 1300b57cec5SDimitry Andric 131*0fca6ea1SDimitry Andric void DeclRead(GlobalDeclID ID, const Decl *D) override { 1320b57cec5SDimitry Andric if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 1330b57cec5SDimitry Andric if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) { 1340b57cec5SDimitry Andric unsigned DiagID 1350b57cec5SDimitry Andric = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, 1360b57cec5SDimitry Andric "%0 was deserialized"); 1370b57cec5SDimitry Andric Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID) 138e8d8bef9SDimitry Andric << ND; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric DelegatingDeserializationListener::DeclRead(ID, D); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric }; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric } // end anonymous namespace 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric FrontendAction::FrontendAction() : Instance(nullptr) {} 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric FrontendAction::~FrontendAction() {} 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput, 1520b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST) { 1530b57cec5SDimitry Andric this->CurrentInput = CurrentInput; 1540b57cec5SDimitry Andric CurrentASTUnit = std::move(AST); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric Module *FrontendAction::getCurrentModule() const { 1580b57cec5SDimitry Andric CompilerInstance &CI = getCompilerInstance(); 1590b57cec5SDimitry Andric return CI.getPreprocessor().getHeaderSearchInfo().lookupModule( 160349cc55cSDimitry Andric CI.getLangOpts().CurrentModule, SourceLocation(), /*AllowSearch*/false); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 1640b57cec5SDimitry Andric FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, 1650b57cec5SDimitry Andric StringRef InFile) { 1660b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile); 1670b57cec5SDimitry Andric if (!Consumer) 1680b57cec5SDimitry Andric return nullptr; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // Validate -add-plugin args. 1710b57cec5SDimitry Andric bool FoundAllPlugins = true; 1720b57cec5SDimitry Andric for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) { 1730b57cec5SDimitry Andric bool Found = false; 1745ffd83dbSDimitry Andric for (const FrontendPluginRegistry::entry &Plugin : 1755ffd83dbSDimitry Andric FrontendPluginRegistry::entries()) { 1765ffd83dbSDimitry Andric if (Plugin.getName() == Arg) 1770b57cec5SDimitry Andric Found = true; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric if (!Found) { 1800b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg; 1810b57cec5SDimitry Andric FoundAllPlugins = false; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric if (!FoundAllPlugins) 1850b57cec5SDimitry Andric return nullptr; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // If there are no registered plugins we don't need to wrap the consumer 1880b57cec5SDimitry Andric if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end()) 1890b57cec5SDimitry Andric return Consumer; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric // If this is a code completion run, avoid invoking the plugin consumers 1920b57cec5SDimitry Andric if (CI.hasCodeCompletionConsumer()) 1930b57cec5SDimitry Andric return Consumer; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // Collect the list of plugins that go before the main action (in Consumers) 1960b57cec5SDimitry Andric // or after it (in AfterConsumers) 1970b57cec5SDimitry Andric std::vector<std::unique_ptr<ASTConsumer>> Consumers; 1980b57cec5SDimitry Andric std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers; 1995ffd83dbSDimitry Andric for (const FrontendPluginRegistry::entry &Plugin : 2005ffd83dbSDimitry Andric FrontendPluginRegistry::entries()) { 2015ffd83dbSDimitry Andric std::unique_ptr<PluginASTAction> P = Plugin.instantiate(); 2020b57cec5SDimitry Andric PluginASTAction::ActionType ActionType = P->getActionType(); 203349cc55cSDimitry Andric if (ActionType == PluginASTAction::CmdlineAfterMainAction || 204349cc55cSDimitry Andric ActionType == PluginASTAction::CmdlineBeforeMainAction) { 2050b57cec5SDimitry Andric // This is O(|plugins| * |add_plugins|), but since both numbers are 2060b57cec5SDimitry Andric // way below 50 in practice, that's ok. 207bdd1243dSDimitry Andric if (llvm::is_contained(CI.getFrontendOpts().AddPluginActions, 208bdd1243dSDimitry Andric Plugin.getName())) { 209349cc55cSDimitry Andric if (ActionType == PluginASTAction::CmdlineBeforeMainAction) 210349cc55cSDimitry Andric ActionType = PluginASTAction::AddBeforeMainAction; 211349cc55cSDimitry Andric else 2120b57cec5SDimitry Andric ActionType = PluginASTAction::AddAfterMainAction; 2130b57cec5SDimitry Andric } 214349cc55cSDimitry Andric } 2150b57cec5SDimitry Andric if ((ActionType == PluginASTAction::AddBeforeMainAction || 2160b57cec5SDimitry Andric ActionType == PluginASTAction::AddAfterMainAction) && 2175ffd83dbSDimitry Andric P->ParseArgs( 2185ffd83dbSDimitry Andric CI, 2195ffd83dbSDimitry Andric CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) { 2200b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> PluginConsumer = P->CreateASTConsumer(CI, InFile); 2210b57cec5SDimitry Andric if (ActionType == PluginASTAction::AddBeforeMainAction) { 2220b57cec5SDimitry Andric Consumers.push_back(std::move(PluginConsumer)); 2230b57cec5SDimitry Andric } else { 2240b57cec5SDimitry Andric AfterConsumers.push_back(std::move(PluginConsumer)); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric // Add to Consumers the main consumer, then all the plugins that go after it 2300b57cec5SDimitry Andric Consumers.push_back(std::move(Consumer)); 231349cc55cSDimitry Andric if (!AfterConsumers.empty()) { 232349cc55cSDimitry Andric // If we have plugins after the main consumer, which may be the codegen 233349cc55cSDimitry Andric // action, they likely will need the ASTContext, so don't clear it in the 234349cc55cSDimitry Andric // codegen action. 235349cc55cSDimitry Andric CI.getCodeGenOpts().ClearASTBeforeBackend = false; 236349cc55cSDimitry Andric for (auto &C : AfterConsumers) 2370b57cec5SDimitry Andric Consumers.push_back(std::move(C)); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 240a7dea167SDimitry Andric return std::make_unique<MultiplexConsumer>(std::move(Consumers)); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric /// For preprocessed files, if the first line is the linemarker and specifies 2440b57cec5SDimitry Andric /// the original source file name, use that name as the input file name. 2450b57cec5SDimitry Andric /// Returns the location of the first token after the line marker directive. 2460b57cec5SDimitry Andric /// 2470b57cec5SDimitry Andric /// \param CI The compiler instance. 2480b57cec5SDimitry Andric /// \param InputFile Populated with the filename from the line marker. 2490b57cec5SDimitry Andric /// \param IsModuleMap If \c true, add a line note corresponding to this line 2500b57cec5SDimitry Andric /// directive. (We need to do this because the directive will not be 2510b57cec5SDimitry Andric /// visited by the preprocessor.) 2520b57cec5SDimitry Andric static SourceLocation ReadOriginalFileName(CompilerInstance &CI, 2530b57cec5SDimitry Andric std::string &InputFile, 2540b57cec5SDimitry Andric bool IsModuleMap = false) { 2550b57cec5SDimitry Andric auto &SourceMgr = CI.getSourceManager(); 2560b57cec5SDimitry Andric auto MainFileID = SourceMgr.getMainFileID(); 2570b57cec5SDimitry Andric 258e8d8bef9SDimitry Andric auto MainFileBuf = SourceMgr.getBufferOrNone(MainFileID); 259e8d8bef9SDimitry Andric if (!MainFileBuf) 2600b57cec5SDimitry Andric return SourceLocation(); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric std::unique_ptr<Lexer> RawLexer( 263e8d8bef9SDimitry Andric new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts())); 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric // If the first line has the syntax of 2660b57cec5SDimitry Andric // 2670b57cec5SDimitry Andric // # NUM "FILENAME" 2680b57cec5SDimitry Andric // 2690b57cec5SDimitry Andric // we use FILENAME as the input file name. 2700b57cec5SDimitry Andric Token T; 2710b57cec5SDimitry Andric if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) 2720b57cec5SDimitry Andric return SourceLocation(); 2730b57cec5SDimitry Andric if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || 2740b57cec5SDimitry Andric T.getKind() != tok::numeric_constant) 2750b57cec5SDimitry Andric return SourceLocation(); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric unsigned LineNo; 2780b57cec5SDimitry Andric SourceLocation LineNoLoc = T.getLocation(); 2790b57cec5SDimitry Andric if (IsModuleMap) { 2800b57cec5SDimitry Andric llvm::SmallString<16> Buffer; 2810b57cec5SDimitry Andric if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts()) 2820b57cec5SDimitry Andric .getAsInteger(10, LineNo)) 2830b57cec5SDimitry Andric return SourceLocation(); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric RawLexer->LexFromRawLexer(T); 2870b57cec5SDimitry Andric if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) 2880b57cec5SDimitry Andric return SourceLocation(); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric StringLiteralParser Literal(T, CI.getPreprocessor()); 2910b57cec5SDimitry Andric if (Literal.hadError) 2920b57cec5SDimitry Andric return SourceLocation(); 2930b57cec5SDimitry Andric RawLexer->LexFromRawLexer(T); 2940b57cec5SDimitry Andric if (T.isNot(tok::eof) && !T.isAtStartOfLine()) 2950b57cec5SDimitry Andric return SourceLocation(); 2960b57cec5SDimitry Andric InputFile = Literal.GetString().str(); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric if (IsModuleMap) 2990b57cec5SDimitry Andric CI.getSourceManager().AddLineNote( 3000b57cec5SDimitry Andric LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false, 3010b57cec5SDimitry Andric false, SrcMgr::C_User_ModuleMap); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric return T.getLocation(); 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric static SmallVectorImpl<char> & 3070b57cec5SDimitry Andric operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { 3080b57cec5SDimitry Andric Includes.append(RHS.begin(), RHS.end()); 3090b57cec5SDimitry Andric return Includes; 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric static void addHeaderInclude(StringRef HeaderName, 3130b57cec5SDimitry Andric SmallVectorImpl<char> &Includes, 3140b57cec5SDimitry Andric const LangOptions &LangOpts, 3150b57cec5SDimitry Andric bool IsExternC) { 3160b57cec5SDimitry Andric if (IsExternC && LangOpts.CPlusPlus) 3170b57cec5SDimitry Andric Includes += "extern \"C\" {\n"; 3180b57cec5SDimitry Andric if (LangOpts.ObjC) 3190b57cec5SDimitry Andric Includes += "#import \""; 3200b57cec5SDimitry Andric else 3210b57cec5SDimitry Andric Includes += "#include \""; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric Includes += HeaderName; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric Includes += "\"\n"; 3260b57cec5SDimitry Andric if (IsExternC && LangOpts.CPlusPlus) 3270b57cec5SDimitry Andric Includes += "}\n"; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric /// Collect the set of header includes needed to construct the given 3310b57cec5SDimitry Andric /// module and update the TopHeaders file set of the module. 3320b57cec5SDimitry Andric /// 3330b57cec5SDimitry Andric /// \param Module The module we're collecting includes from. 3340b57cec5SDimitry Andric /// 3350b57cec5SDimitry Andric /// \param Includes Will be augmented with the set of \#includes or \#imports 3360b57cec5SDimitry Andric /// needed to load all of the named headers. 3370b57cec5SDimitry Andric static std::error_code collectModuleHeaderIncludes( 3380b57cec5SDimitry Andric const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag, 3390b57cec5SDimitry Andric ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) { 3400b57cec5SDimitry Andric // Don't collect any headers for unavailable modules. 3410b57cec5SDimitry Andric if (!Module->isAvailable()) 3420b57cec5SDimitry Andric return std::error_code(); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric // Resolve all lazy header directives to header files. 345bdd1243dSDimitry Andric ModMap.resolveHeaderDirectives(Module, /*File=*/std::nullopt); 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric // If any headers are missing, we can't build this module. In most cases, 3480b57cec5SDimitry Andric // diagnostics for this should have already been produced; we only get here 3490b57cec5SDimitry Andric // if explicit stat information was provided. 3500b57cec5SDimitry Andric // FIXME: If the name resolves to a file with different stat information, 3510b57cec5SDimitry Andric // produce a better diagnostic. 3520b57cec5SDimitry Andric if (!Module->MissingHeaders.empty()) { 3530b57cec5SDimitry Andric auto &MissingHeader = Module->MissingHeaders.front(); 3540b57cec5SDimitry Andric Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) 3550b57cec5SDimitry Andric << MissingHeader.IsUmbrella << MissingHeader.FileName; 3560b57cec5SDimitry Andric return std::error_code(); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric // Add includes for each of these headers. 3600b57cec5SDimitry Andric for (auto HK : {Module::HK_Normal, Module::HK_Private}) { 3610b57cec5SDimitry Andric for (Module::Header &H : Module->Headers[HK]) { 3620b57cec5SDimitry Andric Module->addTopHeader(H.Entry); 3630b57cec5SDimitry Andric // Use the path as specified in the module map file. We'll look for this 3640b57cec5SDimitry Andric // file relative to the module build directory (the directory containing 3650b57cec5SDimitry Andric // the module map file) so this will find the same file that we found 3660b57cec5SDimitry Andric // while parsing the module map. 367fe6060f1SDimitry Andric addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts, 368fe6060f1SDimitry Andric Module->IsExternC); 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric // Note that Module->PrivateHeaders will not be a TopHeader. 3720b57cec5SDimitry Andric 37306c3fb27SDimitry Andric if (std::optional<Module::Header> UmbrellaHeader = 37406c3fb27SDimitry Andric Module->getUmbrellaHeaderAsWritten()) { 37506c3fb27SDimitry Andric Module->addTopHeader(UmbrellaHeader->Entry); 3760b57cec5SDimitry Andric if (Module->Parent) 3770b57cec5SDimitry Andric // Include the umbrella header for submodules. 37806c3fb27SDimitry Andric addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory, 379fe6060f1SDimitry Andric Includes, LangOpts, Module->IsExternC); 38006c3fb27SDimitry Andric } else if (std::optional<Module::DirectoryName> UmbrellaDir = 38106c3fb27SDimitry Andric Module->getUmbrellaDirAsWritten()) { 3820b57cec5SDimitry Andric // Add all of the headers we find in this subdirectory. 3830b57cec5SDimitry Andric std::error_code EC; 3840b57cec5SDimitry Andric SmallString<128> DirNative; 38506c3fb27SDimitry Andric llvm::sys::path::native(UmbrellaDir->Entry.getName(), DirNative); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 38806c3fb27SDimitry Andric SmallVector<std::pair<std::string, FileEntryRef>, 8> Headers; 3890b57cec5SDimitry Andric for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; 3900b57cec5SDimitry Andric Dir != End && !EC; Dir.increment(EC)) { 3910b57cec5SDimitry Andric // Check whether this entry has an extension typically associated with 3920b57cec5SDimitry Andric // headers. 3930b57cec5SDimitry Andric if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path())) 3940b57cec5SDimitry Andric .Cases(".h", ".H", ".hh", ".hpp", true) 3950b57cec5SDimitry Andric .Default(false)) 3960b57cec5SDimitry Andric continue; 3970b57cec5SDimitry Andric 398bdd1243dSDimitry Andric auto Header = FileMgr.getOptionalFileRef(Dir->path()); 3990b57cec5SDimitry Andric // FIXME: This shouldn't happen unless there is a file system race. Is 4000b57cec5SDimitry Andric // that worth diagnosing? 4010b57cec5SDimitry Andric if (!Header) 4020b57cec5SDimitry Andric continue; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // If this header is marked 'unavailable' in this module, don't include 4050b57cec5SDimitry Andric // it. 406a7dea167SDimitry Andric if (ModMap.isHeaderUnavailableInModule(*Header, Module)) 4070b57cec5SDimitry Andric continue; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric // Compute the relative path from the directory to this file. 4100b57cec5SDimitry Andric SmallVector<StringRef, 16> Components; 4110b57cec5SDimitry Andric auto PathIt = llvm::sys::path::rbegin(Dir->path()); 4120b57cec5SDimitry Andric for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) 4130b57cec5SDimitry Andric Components.push_back(*PathIt); 414fe6060f1SDimitry Andric SmallString<128> RelativeHeader( 41506c3fb27SDimitry Andric UmbrellaDir->PathRelativeToRootModuleDirectory); 4160b57cec5SDimitry Andric for (auto It = Components.rbegin(), End = Components.rend(); It != End; 4170b57cec5SDimitry Andric ++It) 4180b57cec5SDimitry Andric llvm::sys::path::append(RelativeHeader, *It); 4190b57cec5SDimitry Andric 4205ffd83dbSDimitry Andric std::string RelName = RelativeHeader.c_str(); 4215ffd83dbSDimitry Andric Headers.push_back(std::make_pair(RelName, *Header)); 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric if (EC) 4250b57cec5SDimitry Andric return EC; 4265ffd83dbSDimitry Andric 4275ffd83dbSDimitry Andric // Sort header paths and make the header inclusion order deterministic 4285ffd83dbSDimitry Andric // across different OSs and filesystems. 429fcaf7f86SDimitry Andric llvm::sort(Headers, llvm::less_first()); 4305ffd83dbSDimitry Andric for (auto &H : Headers) { 4315ffd83dbSDimitry Andric // Include this header as part of the umbrella directory. 4325ffd83dbSDimitry Andric Module->addTopHeader(H.second); 4335ffd83dbSDimitry Andric addHeaderInclude(H.first, Includes, LangOpts, Module->IsExternC); 4345ffd83dbSDimitry Andric } 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric // Recurse into submodules. 43806c3fb27SDimitry Andric for (auto *Submodule : Module->submodules()) 4390b57cec5SDimitry Andric if (std::error_code Err = collectModuleHeaderIncludes( 44006c3fb27SDimitry Andric LangOpts, FileMgr, Diag, ModMap, Submodule, Includes)) 4410b57cec5SDimitry Andric return Err; 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric return std::error_code(); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem, 4470b57cec5SDimitry Andric bool IsPreprocessed, 4480b57cec5SDimitry Andric std::string &PresumedModuleMapFile, 4490b57cec5SDimitry Andric unsigned &Offset) { 4500b57cec5SDimitry Andric auto &SrcMgr = CI.getSourceManager(); 4510b57cec5SDimitry Andric HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric // Map the current input to a file. 4540b57cec5SDimitry Andric FileID ModuleMapID = SrcMgr.getMainFileID(); 45506c3fb27SDimitry Andric OptionalFileEntryRef ModuleMap = SrcMgr.getFileEntryRefForID(ModuleMapID); 45606c3fb27SDimitry Andric assert(ModuleMap && "MainFileID without FileEntry"); 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric // If the module map is preprocessed, handle the initial line marker; 4590b57cec5SDimitry Andric // line directives are not part of the module map syntax in general. 4600b57cec5SDimitry Andric Offset = 0; 4610b57cec5SDimitry Andric if (IsPreprocessed) { 4620b57cec5SDimitry Andric SourceLocation EndOfLineMarker = 4630b57cec5SDimitry Andric ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true); 4640b57cec5SDimitry Andric if (EndOfLineMarker.isValid()) 4650b57cec5SDimitry Andric Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric // Load the module map file. 46906c3fb27SDimitry Andric if (HS.loadModuleMapFile(*ModuleMap, IsSystem, ModuleMapID, &Offset, 4700b57cec5SDimitry Andric PresumedModuleMapFile)) 4710b57cec5SDimitry Andric return true; 4720b57cec5SDimitry Andric 473e8d8bef9SDimitry Andric if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset) 4740b57cec5SDimitry Andric Offset = 0; 4750b57cec5SDimitry Andric 47681ad6265SDimitry Andric // Infer framework module if possible. 47781ad6265SDimitry Andric if (HS.getModuleMap().canInferFrameworkModule(ModuleMap->getDir())) { 47806c3fb27SDimitry Andric SmallString<128> InferredFrameworkPath = ModuleMap->getDir().getName(); 47981ad6265SDimitry Andric llvm::sys::path::append(InferredFrameworkPath, 48081ad6265SDimitry Andric CI.getLangOpts().ModuleName + ".framework"); 48106c3fb27SDimitry Andric if (auto Dir = 48206c3fb27SDimitry Andric CI.getFileManager().getOptionalDirectoryRef(InferredFrameworkPath)) 48381ad6265SDimitry Andric (void)HS.getModuleMap().inferFrameworkModule(*Dir, IsSystem, nullptr); 48481ad6265SDimitry Andric } 48581ad6265SDimitry Andric 4860b57cec5SDimitry Andric return false; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric static Module *prepareToBuildModule(CompilerInstance &CI, 4900b57cec5SDimitry Andric StringRef ModuleMapFilename) { 4910b57cec5SDimitry Andric if (CI.getLangOpts().CurrentModule.empty()) { 4920b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_missing_module_name); 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric // FIXME: Eventually, we could consider asking whether there was just 4950b57cec5SDimitry Andric // a single module described in the module map, and use that as a 4960b57cec5SDimitry Andric // default. Then it would be fairly trivial to just "compile" a module 4970b57cec5SDimitry Andric // map with a single module (the common case). 4980b57cec5SDimitry Andric return nullptr; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric // Dig out the module definition. 5020b57cec5SDimitry Andric HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); 503349cc55cSDimitry Andric Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, SourceLocation(), 504fe6060f1SDimitry Andric /*AllowSearch=*/true); 5050b57cec5SDimitry Andric if (!M) { 5060b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_missing_module) 5070b57cec5SDimitry Andric << CI.getLangOpts().CurrentModule << ModuleMapFilename; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric return nullptr; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric // Check whether we can build this module at all. 5135f757f3fSDimitry Andric if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), *M, 5145f757f3fSDimitry Andric CI.getDiagnostics())) 5150b57cec5SDimitry Andric return nullptr; 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric // Inform the preprocessor that includes from within the input buffer should 5180b57cec5SDimitry Andric // be resolved relative to the build directory of the module map file. 51906c3fb27SDimitry Andric CI.getPreprocessor().setMainFileDir(*M->Directory); 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric // If the module was inferred from a different module map (via an expanded 5220b57cec5SDimitry Andric // umbrella module definition), track that fact. 5230b57cec5SDimitry Andric // FIXME: It would be preferable to fill this in as part of processing 5240b57cec5SDimitry Andric // the module map, rather than adding it after the fact. 5250b57cec5SDimitry Andric StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; 5260b57cec5SDimitry Andric if (!OriginalModuleMapName.empty()) { 527a7dea167SDimitry Andric auto OriginalModuleMap = 5285f757f3fSDimitry Andric CI.getFileManager().getOptionalFileRef(OriginalModuleMapName, 5290b57cec5SDimitry Andric /*openFile*/ true); 5300b57cec5SDimitry Andric if (!OriginalModuleMap) { 5310b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_module_map_not_found) 5320b57cec5SDimitry Andric << OriginalModuleMapName; 5330b57cec5SDimitry Andric return nullptr; 5340b57cec5SDimitry Andric } 5355f757f3fSDimitry Andric if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID( 5360b57cec5SDimitry Andric CI.getSourceManager().getMainFileID())) { 5370b57cec5SDimitry Andric M->IsInferred = true; 538*0fca6ea1SDimitry Andric auto FileCharacter = 539*0fca6ea1SDimitry Andric M->IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 540*0fca6ea1SDimitry Andric FileID OriginalModuleMapFID = CI.getSourceManager().getOrCreateFileID( 541*0fca6ea1SDimitry Andric *OriginalModuleMap, FileCharacter); 542*0fca6ea1SDimitry Andric CI.getPreprocessor() 543*0fca6ea1SDimitry Andric .getHeaderSearchInfo() 544*0fca6ea1SDimitry Andric .getModuleMap() 545*0fca6ea1SDimitry Andric .setInferredModuleAllowedBy(M, OriginalModuleMapFID); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric // If we're being run from the command-line, the module build stack will not 5500b57cec5SDimitry Andric // have been filled in yet, so complete it now in order to allow us to detect 5510b57cec5SDimitry Andric // module cycles. 5520b57cec5SDimitry Andric SourceManager &SourceMgr = CI.getSourceManager(); 5530b57cec5SDimitry Andric if (SourceMgr.getModuleBuildStack().empty()) 5540b57cec5SDimitry Andric SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, 5550b57cec5SDimitry Andric FullSourceLoc(SourceLocation(), SourceMgr)); 5560b57cec5SDimitry Andric return M; 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric /// Compute the input buffer that should be used to build the specified module. 5600b57cec5SDimitry Andric static std::unique_ptr<llvm::MemoryBuffer> 5610b57cec5SDimitry Andric getInputBufferForModule(CompilerInstance &CI, Module *M) { 5620b57cec5SDimitry Andric FileManager &FileMgr = CI.getFileManager(); 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric // Collect the set of #includes we need to build the module. 5650b57cec5SDimitry Andric SmallString<256> HeaderContents; 5660b57cec5SDimitry Andric std::error_code Err = std::error_code(); 56706c3fb27SDimitry Andric if (std::optional<Module::Header> UmbrellaHeader = 56806c3fb27SDimitry Andric M->getUmbrellaHeaderAsWritten()) 56906c3fb27SDimitry Andric addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory, 570fe6060f1SDimitry Andric HeaderContents, CI.getLangOpts(), M->IsExternC); 5710b57cec5SDimitry Andric Err = collectModuleHeaderIncludes( 5720b57cec5SDimitry Andric CI.getLangOpts(), FileMgr, CI.getDiagnostics(), 5730b57cec5SDimitry Andric CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, 5740b57cec5SDimitry Andric HeaderContents); 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric if (Err) { 5770b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) 5780b57cec5SDimitry Andric << M->getFullModuleName() << Err.message(); 5790b57cec5SDimitry Andric return nullptr; 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric return llvm::MemoryBuffer::getMemBufferCopy( 5830b57cec5SDimitry Andric HeaderContents, Module::getModuleInputBufferName()); 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric bool FrontendAction::BeginSourceFile(CompilerInstance &CI, 5870b57cec5SDimitry Andric const FrontendInputFile &RealInput) { 5880b57cec5SDimitry Andric FrontendInputFile Input(RealInput); 5890b57cec5SDimitry Andric assert(!Instance && "Already processing a source file!"); 5900b57cec5SDimitry Andric assert(!Input.isEmpty() && "Unexpected empty filename!"); 5910b57cec5SDimitry Andric setCurrentInput(Input); 5920b57cec5SDimitry Andric setCompilerInstance(&CI); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric bool HasBegunSourceFile = false; 5950b57cec5SDimitry Andric bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled && 5960b57cec5SDimitry Andric usesPreprocessorOnly(); 597349cc55cSDimitry Andric 598349cc55cSDimitry Andric // If we fail, reset state since the client will not end up calling the 599349cc55cSDimitry Andric // matching EndSourceFile(). All paths that return true should release this. 600349cc55cSDimitry Andric auto FailureCleanup = llvm::make_scope_exit([&]() { 601349cc55cSDimitry Andric if (HasBegunSourceFile) 602349cc55cSDimitry Andric CI.getDiagnosticClient().EndSourceFile(); 603753f127fSDimitry Andric CI.setASTConsumer(nullptr); 604349cc55cSDimitry Andric CI.clearOutputFiles(/*EraseFiles=*/true); 605349cc55cSDimitry Andric CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); 606349cc55cSDimitry Andric setCurrentInput(FrontendInputFile()); 607349cc55cSDimitry Andric setCompilerInstance(nullptr); 608349cc55cSDimitry Andric }); 609349cc55cSDimitry Andric 6100b57cec5SDimitry Andric if (!BeginInvocation(CI)) 611349cc55cSDimitry Andric return false; 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric // If we're replaying the build of an AST file, import it and set up 6140b57cec5SDimitry Andric // the initial state from its build. 6150b57cec5SDimitry Andric if (ReplayASTFile) { 6160b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric // The AST unit populates its own diagnostics engine rather than ours. 6190b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags( 6200b57cec5SDimitry Andric new DiagnosticsEngine(Diags->getDiagnosticIDs(), 6210b57cec5SDimitry Andric &Diags->getDiagnosticOptions())); 6220b57cec5SDimitry Andric ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false); 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric // FIXME: What if the input is a memory buffer? 6250b57cec5SDimitry Andric StringRef InputFile = Input.getFile(); 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( 6285ffd83dbSDimitry Andric std::string(InputFile), CI.getPCHContainerReader(), 6295ffd83dbSDimitry Andric ASTUnit::LoadPreprocessorOnly, ASTDiags, CI.getFileSystemOpts(), 6305f757f3fSDimitry Andric /*HeaderSearchOptions=*/nullptr); 6310b57cec5SDimitry Andric if (!AST) 632349cc55cSDimitry Andric return false; 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // Options relating to how we treat the input (but not what we do with it) 6350b57cec5SDimitry Andric // are inherited from the AST unit. 6360b57cec5SDimitry Andric CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts(); 6370b57cec5SDimitry Andric CI.getPreprocessorOpts() = AST->getPreprocessorOpts(); 6380b57cec5SDimitry Andric CI.getLangOpts() = AST->getLangOpts(); 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric // Set the shared objects, these are reset when we finish processing the 6410b57cec5SDimitry Andric // file, otherwise the CompilerInstance will happily destroy them. 6420b57cec5SDimitry Andric CI.setFileManager(&AST->getFileManager()); 6430b57cec5SDimitry Andric CI.createSourceManager(CI.getFileManager()); 6440b57cec5SDimitry Andric CI.getSourceManager().initializeForReplay(AST->getSourceManager()); 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric // Preload all the module files loaded transitively by the AST unit. Also 6470b57cec5SDimitry Andric // load all module map files that were parsed as part of building the AST 6480b57cec5SDimitry Andric // unit. 6490b57cec5SDimitry Andric if (auto ASTReader = AST->getASTReader()) { 6500b57cec5SDimitry Andric auto &MM = ASTReader->getModuleManager(); 6510b57cec5SDimitry Andric auto &PrimaryModule = MM.getPrimaryModule(); 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric for (serialization::ModuleFile &MF : MM) 6540b57cec5SDimitry Andric if (&MF != &PrimaryModule) 6550b57cec5SDimitry Andric CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName); 6560b57cec5SDimitry Andric 657bdd1243dSDimitry Andric ASTReader->visitTopLevelModuleMaps(PrimaryModule, [&](FileEntryRef FE) { 6585ffd83dbSDimitry Andric CI.getFrontendOpts().ModuleMapFiles.push_back( 659bdd1243dSDimitry Andric std::string(FE.getName())); 6600b57cec5SDimitry Andric }); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric // Set up the input file for replay purposes. 6640b57cec5SDimitry Andric auto Kind = AST->getInputKind(); 6650b57cec5SDimitry Andric if (Kind.getFormat() == InputKind::ModuleMap) { 6660b57cec5SDimitry Andric Module *ASTModule = 6670b57cec5SDimitry Andric AST->getPreprocessor().getHeaderSearchInfo().lookupModule( 668349cc55cSDimitry Andric AST->getLangOpts().CurrentModule, SourceLocation(), 669349cc55cSDimitry Andric /*AllowSearch*/ false); 6700b57cec5SDimitry Andric assert(ASTModule && "module file does not define its own module"); 6710b57cec5SDimitry Andric Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind); 6720b57cec5SDimitry Andric } else { 6730b57cec5SDimitry Andric auto &OldSM = AST->getSourceManager(); 6740b57cec5SDimitry Andric FileID ID = OldSM.getMainFileID(); 6755f757f3fSDimitry Andric if (auto File = OldSM.getFileEntryRefForID(ID)) 6760b57cec5SDimitry Andric Input = FrontendInputFile(File->getName(), Kind); 6770b57cec5SDimitry Andric else 678e8d8bef9SDimitry Andric Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind); 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric setCurrentInput(Input, std::move(AST)); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric // AST files follow a very different path, since they share objects via the 6840b57cec5SDimitry Andric // AST unit. 6850b57cec5SDimitry Andric if (Input.getKind().getFormat() == InputKind::Precompiled) { 6860b57cec5SDimitry Andric assert(!usesPreprocessorOnly() && "this case was handled above"); 6870b57cec5SDimitry Andric assert(hasASTFileSupport() && 6880b57cec5SDimitry Andric "This action does not have AST file support!"); 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric // FIXME: What if the input is a memory buffer? 6930b57cec5SDimitry Andric StringRef InputFile = Input.getFile(); 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( 6965ffd83dbSDimitry Andric std::string(InputFile), CI.getPCHContainerReader(), 6975ffd83dbSDimitry Andric ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts(), 698*0fca6ea1SDimitry Andric CI.getHeaderSearchOptsPtr(), CI.getLangOptsPtr()); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric if (!AST) 701349cc55cSDimitry Andric return false; 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // Inform the diagnostic client we are processing a source file. 7040b57cec5SDimitry Andric CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); 7050b57cec5SDimitry Andric HasBegunSourceFile = true; 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric // Set the shared objects, these are reset when we finish processing the 7080b57cec5SDimitry Andric // file, otherwise the CompilerInstance will happily destroy them. 7090b57cec5SDimitry Andric CI.setFileManager(&AST->getFileManager()); 7100b57cec5SDimitry Andric CI.setSourceManager(&AST->getSourceManager()); 7110b57cec5SDimitry Andric CI.setPreprocessor(AST->getPreprocessorPtr()); 7120b57cec5SDimitry Andric Preprocessor &PP = CI.getPreprocessor(); 7130b57cec5SDimitry Andric PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), 7140b57cec5SDimitry Andric PP.getLangOpts()); 7150b57cec5SDimitry Andric CI.setASTContext(&AST->getASTContext()); 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric setCurrentInput(Input, std::move(AST)); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric // Initialize the action. 7200b57cec5SDimitry Andric if (!BeginSourceFileAction(CI)) 721349cc55cSDimitry Andric return false; 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric // Create the AST consumer. 7240b57cec5SDimitry Andric CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); 7250b57cec5SDimitry Andric if (!CI.hasASTConsumer()) 726349cc55cSDimitry Andric return false; 7270b57cec5SDimitry Andric 728349cc55cSDimitry Andric FailureCleanup.release(); 7290b57cec5SDimitry Andric return true; 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric // Set up the file and source managers, if needed. 7330b57cec5SDimitry Andric if (!CI.hasFileManager()) { 7340b57cec5SDimitry Andric if (!CI.createFileManager()) { 735349cc55cSDimitry Andric return false; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric } 738bdd1243dSDimitry Andric if (!CI.hasSourceManager()) { 7390b57cec5SDimitry Andric CI.createSourceManager(CI.getFileManager()); 740bdd1243dSDimitry Andric if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) { 741bdd1243dSDimitry Andric static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient()) 742bdd1243dSDimitry Andric ->setSarifWriter( 743bdd1243dSDimitry Andric std::make_unique<SarifDocumentWriter>(CI.getSourceManager())); 744bdd1243dSDimitry Andric } 745bdd1243dSDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric // Set up embedding for any specified files. Do this before we load any 7480b57cec5SDimitry Andric // source files, including the primary module map for the compilation. 7490b57cec5SDimitry Andric for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { 7505f757f3fSDimitry Andric if (auto FE = CI.getFileManager().getOptionalFileRef(F, /*openFile*/true)) 751a7dea167SDimitry Andric CI.getSourceManager().setFileIsTransient(*FE); 7520b57cec5SDimitry Andric else 7530b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F; 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric if (CI.getFrontendOpts().ModulesEmbedAllFiles) 7560b57cec5SDimitry Andric CI.getSourceManager().setAllFilesAreTransient(true); 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric // IR files bypass the rest of initialization. 759a7dea167SDimitry Andric if (Input.getKind().getLanguage() == Language::LLVM_IR) { 760*0fca6ea1SDimitry Andric if (!hasIRSupport()) { 761*0fca6ea1SDimitry Andric CI.getDiagnostics().Report(diag::err_ast_action_on_llvm_ir) 762*0fca6ea1SDimitry Andric << Input.getFile(); 763*0fca6ea1SDimitry Andric return false; 764*0fca6ea1SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric // Inform the diagnostic client we are processing a source file. 7670b57cec5SDimitry Andric CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); 7680b57cec5SDimitry Andric HasBegunSourceFile = true; 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric // Initialize the action. 7710b57cec5SDimitry Andric if (!BeginSourceFileAction(CI)) 772349cc55cSDimitry Andric return false; 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric // Initialize the main file entry. 7750b57cec5SDimitry Andric if (!CI.InitializeSourceManager(CurrentInput)) 776349cc55cSDimitry Andric return false; 7770b57cec5SDimitry Andric 778349cc55cSDimitry Andric FailureCleanup.release(); 7790b57cec5SDimitry Andric return true; 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric // If the implicit PCH include is actually a directory, rather than 7830b57cec5SDimitry Andric // a single file, search for a suitable PCH file in that directory. 7840b57cec5SDimitry Andric if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 7850b57cec5SDimitry Andric FileManager &FileMgr = CI.getFileManager(); 7860b57cec5SDimitry Andric PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 7870b57cec5SDimitry Andric StringRef PCHInclude = PPOpts.ImplicitPCHInclude; 7880b57cec5SDimitry Andric std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath(); 78981ad6265SDimitry Andric if (auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude)) { 7900b57cec5SDimitry Andric std::error_code EC; 7910b57cec5SDimitry Andric SmallString<128> DirNative; 79281ad6265SDimitry Andric llvm::sys::path::native(PCHDir->getName(), DirNative); 7930b57cec5SDimitry Andric bool Found = false; 7940b57cec5SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 7950b57cec5SDimitry Andric for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), 7960b57cec5SDimitry Andric DirEnd; 7970b57cec5SDimitry Andric Dir != DirEnd && !EC; Dir.increment(EC)) { 7980b57cec5SDimitry Andric // Check whether this is an acceptable AST file. 7990b57cec5SDimitry Andric if (ASTReader::isAcceptableASTFile( 800bdd1243dSDimitry Andric Dir->path(), FileMgr, CI.getModuleCache(), 801bdd1243dSDimitry Andric CI.getPCHContainerReader(), CI.getLangOpts(), 802bdd1243dSDimitry Andric CI.getTargetOpts(), CI.getPreprocessorOpts(), 80361cfbce3SDimitry Andric SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) { 8045ffd83dbSDimitry Andric PPOpts.ImplicitPCHInclude = std::string(Dir->path()); 8050b57cec5SDimitry Andric Found = true; 8060b57cec5SDimitry Andric break; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric if (!Found) { 8110b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; 812349cc55cSDimitry Andric return false; 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric // Set up the preprocessor if needed. When parsing model files the 8180b57cec5SDimitry Andric // preprocessor of the original source is reused. 8190b57cec5SDimitry Andric if (!isModelParsingAction()) 8200b57cec5SDimitry Andric CI.createPreprocessor(getTranslationUnitKind()); 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric // Inform the diagnostic client we are processing a source file. 8230b57cec5SDimitry Andric CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 8240b57cec5SDimitry Andric &CI.getPreprocessor()); 8250b57cec5SDimitry Andric HasBegunSourceFile = true; 8260b57cec5SDimitry Andric 82781ad6265SDimitry Andric // Handle C++20 header units. 82881ad6265SDimitry Andric // Here, the user has the option to specify that the header name should be 82981ad6265SDimitry Andric // looked up in the pre-processor search paths (and the main filename as 83081ad6265SDimitry Andric // passed by the driver might therefore be incomplete until that look-up). 83181ad6265SDimitry Andric if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() && 83281ad6265SDimitry Andric !Input.getKind().isPreprocessed()) { 83381ad6265SDimitry Andric StringRef FileName = Input.getFile(); 83481ad6265SDimitry Andric InputKind Kind = Input.getKind(); 83581ad6265SDimitry Andric if (Kind.getHeaderUnitKind() != InputKind::HeaderUnit_Abs) { 83681ad6265SDimitry Andric assert(CI.hasPreprocessor() && 83781ad6265SDimitry Andric "trying to build a header unit without a Pre-processor?"); 83881ad6265SDimitry Andric HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); 83981ad6265SDimitry Andric // Relative searches begin from CWD. 84006c3fb27SDimitry Andric auto Dir = CI.getFileManager().getOptionalDirectoryRef("."); 8415f757f3fSDimitry Andric SmallVector<std::pair<OptionalFileEntryRef, DirectoryEntryRef>, 1> CWD; 8425f757f3fSDimitry Andric CWD.push_back({std::nullopt, *Dir}); 843bdd1243dSDimitry Andric OptionalFileEntryRef FE = 84481ad6265SDimitry Andric HS.LookupFile(FileName, SourceLocation(), 84581ad6265SDimitry Andric /*Angled*/ Input.getKind().getHeaderUnitKind() == 84681ad6265SDimitry Andric InputKind::HeaderUnit_System, 84781ad6265SDimitry Andric nullptr, nullptr, CWD, nullptr, nullptr, nullptr, 84881ad6265SDimitry Andric nullptr, nullptr, nullptr); 84981ad6265SDimitry Andric if (!FE) { 85081ad6265SDimitry Andric CI.getDiagnostics().Report(diag::err_module_header_file_not_found) 85181ad6265SDimitry Andric << FileName; 85281ad6265SDimitry Andric return false; 85381ad6265SDimitry Andric } 85481ad6265SDimitry Andric // We now have the filename... 8555f757f3fSDimitry Andric FileName = FE->getName(); 85681ad6265SDimitry Andric // ... still a header unit, but now use the path as written. 85781ad6265SDimitry Andric Kind = Input.getKind().withHeaderUnit(InputKind::HeaderUnit_Abs); 85881ad6265SDimitry Andric Input = FrontendInputFile(FileName, Kind, Input.isSystem()); 85981ad6265SDimitry Andric } 86081ad6265SDimitry Andric // Unless the user has overridden the name, the header unit module name is 86181ad6265SDimitry Andric // the pathname for the file. 86281ad6265SDimitry Andric if (CI.getLangOpts().ModuleName.empty()) 86381ad6265SDimitry Andric CI.getLangOpts().ModuleName = std::string(FileName); 86481ad6265SDimitry Andric CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName; 86581ad6265SDimitry Andric } 86681ad6265SDimitry Andric 8670b57cec5SDimitry Andric if (!CI.InitializeSourceManager(Input)) 868349cc55cSDimitry Andric return false; 8690b57cec5SDimitry Andric 87081ad6265SDimitry Andric if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() && 87181ad6265SDimitry Andric Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) { 87281ad6265SDimitry Andric // We have an input filename like foo.iih, but we want to find the right 87381ad6265SDimitry Andric // module name (and original file, to build the map entry). 87481ad6265SDimitry Andric // Check if the first line specifies the original source file name with a 87581ad6265SDimitry Andric // linemarker. 87681ad6265SDimitry Andric std::string PresumedInputFile = std::string(getCurrentFileOrBufferName()); 87781ad6265SDimitry Andric ReadOriginalFileName(CI, PresumedInputFile); 87881ad6265SDimitry Andric // Unless the user overrides this, the module name is the name by which the 87981ad6265SDimitry Andric // original file was known. 88081ad6265SDimitry Andric if (CI.getLangOpts().ModuleName.empty()) 88181ad6265SDimitry Andric CI.getLangOpts().ModuleName = std::string(PresumedInputFile); 88281ad6265SDimitry Andric CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName; 88381ad6265SDimitry Andric } 88481ad6265SDimitry Andric 8850b57cec5SDimitry Andric // For module map files, we first parse the module map and synthesize a 8860b57cec5SDimitry Andric // "<module-includes>" buffer before more conventional processing. 8870b57cec5SDimitry Andric if (Input.getKind().getFormat() == InputKind::ModuleMap) { 8880b57cec5SDimitry Andric CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric std::string PresumedModuleMapFile; 8910b57cec5SDimitry Andric unsigned OffsetToContents; 8920b57cec5SDimitry Andric if (loadModuleMapForModuleBuild(CI, Input.isSystem(), 8930b57cec5SDimitry Andric Input.isPreprocessed(), 8940b57cec5SDimitry Andric PresumedModuleMapFile, OffsetToContents)) 895349cc55cSDimitry Andric return false; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric auto *CurrentModule = prepareToBuildModule(CI, Input.getFile()); 8980b57cec5SDimitry Andric if (!CurrentModule) 899349cc55cSDimitry Andric return false; 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile; 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric if (OffsetToContents) 9040b57cec5SDimitry Andric // If the module contents are in the same file, skip to them. 9050b57cec5SDimitry Andric CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true); 9060b57cec5SDimitry Andric else { 9070b57cec5SDimitry Andric // Otherwise, convert the module description to a suitable input buffer. 9080b57cec5SDimitry Andric auto Buffer = getInputBufferForModule(CI, CurrentModule); 9090b57cec5SDimitry Andric if (!Buffer) 910349cc55cSDimitry Andric return false; 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric // Reinitialize the main file entry to refer to the new input. 9130b57cec5SDimitry Andric auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User; 9140b57cec5SDimitry Andric auto &SourceMgr = CI.getSourceManager(); 9150b57cec5SDimitry Andric auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind); 9165ffd83dbSDimitry Andric assert(BufferID.isValid() && "couldn't create module buffer ID"); 9170b57cec5SDimitry Andric SourceMgr.setMainFileID(BufferID); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric // Initialize the action. 9220b57cec5SDimitry Andric if (!BeginSourceFileAction(CI)) 923349cc55cSDimitry Andric return false; 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric // If we were asked to load any module map files, do so now. 9260b57cec5SDimitry Andric for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { 92706c3fb27SDimitry Andric if (auto File = CI.getFileManager().getOptionalFileRef(Filename)) 9280b57cec5SDimitry Andric CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( 929a7dea167SDimitry Andric *File, /*IsSystem*/false); 9300b57cec5SDimitry Andric else 9310b57cec5SDimitry Andric CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 934bdd1243dSDimitry Andric // If compiling implementation of a module, load its module map file now. 935bdd1243dSDimitry Andric (void)CI.getPreprocessor().getCurrentModuleImplementation(); 936bdd1243dSDimitry Andric 9370b57cec5SDimitry Andric // Add a module declaration scope so that modules from -fmodule-map-file 9380b57cec5SDimitry Andric // arguments may shadow modules found implicitly in search paths. 9390b57cec5SDimitry Andric CI.getPreprocessor() 9400b57cec5SDimitry Andric .getHeaderSearchInfo() 9410b57cec5SDimitry Andric .getModuleMap() 9420b57cec5SDimitry Andric .finishModuleDeclarationScope(); 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric // Create the AST context and consumer unless this is a preprocessor only 9450b57cec5SDimitry Andric // action. 9460b57cec5SDimitry Andric if (!usesPreprocessorOnly()) { 9470b57cec5SDimitry Andric // Parsing a model file should reuse the existing ASTContext. 9480b57cec5SDimitry Andric if (!isModelParsingAction()) 9490b57cec5SDimitry Andric CI.createASTContext(); 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric // For preprocessed files, check if the first line specifies the original 9520b57cec5SDimitry Andric // source file name with a linemarker. 9535ffd83dbSDimitry Andric std::string PresumedInputFile = std::string(getCurrentFileOrBufferName()); 9540b57cec5SDimitry Andric if (Input.isPreprocessed()) 9550b57cec5SDimitry Andric ReadOriginalFileName(CI, PresumedInputFile); 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> Consumer = 9580b57cec5SDimitry Andric CreateWrappedASTConsumer(CI, PresumedInputFile); 9590b57cec5SDimitry Andric if (!Consumer) 960349cc55cSDimitry Andric return false; 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric // FIXME: should not overwrite ASTMutationListener when parsing model files? 9630b57cec5SDimitry Andric if (!isModelParsingAction()) 9640b57cec5SDimitry Andric CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { 9670b57cec5SDimitry Andric // Convert headers to PCH and chain them. 9680b57cec5SDimitry Andric IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader; 9690b57cec5SDimitry Andric source = createChainedIncludesSource(CI, FinalReader); 9700b57cec5SDimitry Andric if (!source) 971349cc55cSDimitry Andric return false; 9725ffd83dbSDimitry Andric CI.setASTReader(static_cast<ASTReader *>(FinalReader.get())); 9730b57cec5SDimitry Andric CI.getASTContext().setExternalSource(source); 9740b57cec5SDimitry Andric } else if (CI.getLangOpts().Modules || 9750b57cec5SDimitry Andric !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 9760b57cec5SDimitry Andric // Use PCM or PCH. 9770b57cec5SDimitry Andric assert(hasPCHSupport() && "This action does not have PCH support!"); 9780b57cec5SDimitry Andric ASTDeserializationListener *DeserialListener = 9790b57cec5SDimitry Andric Consumer->GetASTDeserializationListener(); 9800b57cec5SDimitry Andric bool DeleteDeserialListener = false; 9810b57cec5SDimitry Andric if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) { 9820b57cec5SDimitry Andric DeserialListener = new DeserializedDeclsDumper(DeserialListener, 9830b57cec5SDimitry Andric DeleteDeserialListener); 9840b57cec5SDimitry Andric DeleteDeserialListener = true; 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) { 9870b57cec5SDimitry Andric DeserialListener = new DeserializedDeclsChecker( 9880b57cec5SDimitry Andric CI.getASTContext(), 9890b57cec5SDimitry Andric CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, 9900b57cec5SDimitry Andric DeserialListener, DeleteDeserialListener); 9910b57cec5SDimitry Andric DeleteDeserialListener = true; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 9940b57cec5SDimitry Andric CI.createPCHExternalASTSource( 9950b57cec5SDimitry Andric CI.getPreprocessorOpts().ImplicitPCHInclude, 996e8d8bef9SDimitry Andric CI.getPreprocessorOpts().DisablePCHOrModuleValidation, 997e8d8bef9SDimitry Andric CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, 998e8d8bef9SDimitry Andric DeserialListener, DeleteDeserialListener); 9990b57cec5SDimitry Andric if (!CI.getASTContext().getExternalSource()) 1000349cc55cSDimitry Andric return false; 10010b57cec5SDimitry Andric } 10025ffd83dbSDimitry Andric // If modules are enabled, create the AST reader before creating 10030b57cec5SDimitry Andric // any builtins, so that all declarations know that they might be 10040b57cec5SDimitry Andric // extended by an external source. 10050b57cec5SDimitry Andric if (CI.getLangOpts().Modules || !CI.hasASTContext() || 10060b57cec5SDimitry Andric !CI.getASTContext().getExternalSource()) { 1007480093f4SDimitry Andric CI.createASTReader(); 1008480093f4SDimitry Andric CI.getASTReader()->setDeserializationListener(DeserialListener, 10090b57cec5SDimitry Andric DeleteDeserialListener); 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric CI.setASTConsumer(std::move(Consumer)); 10140b57cec5SDimitry Andric if (!CI.hasASTConsumer()) 1015349cc55cSDimitry Andric return false; 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric // Initialize built-in info as long as we aren't using an external AST 10190b57cec5SDimitry Andric // source. 10200b57cec5SDimitry Andric if (CI.getLangOpts().Modules || !CI.hasASTContext() || 10210b57cec5SDimitry Andric !CI.getASTContext().getExternalSource()) { 10220b57cec5SDimitry Andric Preprocessor &PP = CI.getPreprocessor(); 10230b57cec5SDimitry Andric PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), 10240b57cec5SDimitry Andric PP.getLangOpts()); 10250b57cec5SDimitry Andric } else { 10260b57cec5SDimitry Andric // FIXME: If this is a problem, recover from it by creating a multiplex 10270b57cec5SDimitry Andric // source. 1028480093f4SDimitry Andric assert((!CI.getLangOpts().Modules || CI.getASTReader()) && 10290b57cec5SDimitry Andric "modules enabled but created an external source that " 10300b57cec5SDimitry Andric "doesn't support modules"); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric // If we were asked to load any module files, do so now. 10345f757f3fSDimitry Andric for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) { 10355f757f3fSDimitry Andric serialization::ModuleFile *Loaded = nullptr; 10365f757f3fSDimitry Andric if (!CI.loadModuleFile(ModuleFile, Loaded)) 1037349cc55cSDimitry Andric return false; 10380b57cec5SDimitry Andric 10395f757f3fSDimitry Andric if (Loaded && Loaded->StandardCXXModule) 10405f757f3fSDimitry Andric CI.getDiagnostics().Report( 10415f757f3fSDimitry Andric diag::warn_eagerly_load_for_standard_cplusplus_modules); 10425f757f3fSDimitry Andric } 10435f757f3fSDimitry Andric 10440b57cec5SDimitry Andric // If there is a layout overrides file, attach an external AST source that 10450b57cec5SDimitry Andric // provides the layouts from that file. 10460b57cec5SDimitry Andric if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && 10470b57cec5SDimitry Andric CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { 10480b57cec5SDimitry Andric IntrusiveRefCntPtr<ExternalASTSource> 10490b57cec5SDimitry Andric Override(new LayoutOverrideSource( 10500b57cec5SDimitry Andric CI.getFrontendOpts().OverrideRecordLayoutsFile)); 10510b57cec5SDimitry Andric CI.getASTContext().setExternalSource(Override); 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 1054753f127fSDimitry Andric // Setup HLSL External Sema Source 1055753f127fSDimitry Andric if (CI.getLangOpts().HLSL && CI.hasASTContext()) { 1056bdd1243dSDimitry Andric IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema( 1057753f127fSDimitry Andric new HLSLExternalSemaSource()); 1058bdd1243dSDimitry Andric if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>( 1059bdd1243dSDimitry Andric CI.getASTContext().getExternalSource())) { 1060bdd1243dSDimitry Andric IntrusiveRefCntPtr<ExternalSemaSource> MultiSema( 1061bdd1243dSDimitry Andric new MultiplexExternalSemaSource(SemaSource, HLSLSema.get())); 1062bdd1243dSDimitry Andric CI.getASTContext().setExternalSource(MultiSema); 1063bdd1243dSDimitry Andric } else 1064753f127fSDimitry Andric CI.getASTContext().setExternalSource(HLSLSema); 1065753f127fSDimitry Andric } 1066753f127fSDimitry Andric 1067349cc55cSDimitry Andric FailureCleanup.release(); 10680b57cec5SDimitry Andric return true; 10690b57cec5SDimitry Andric } 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric llvm::Error FrontendAction::Execute() { 10720b57cec5SDimitry Andric CompilerInstance &CI = getCompilerInstance(); 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric if (CI.hasFrontendTimer()) { 10750b57cec5SDimitry Andric llvm::TimeRegion Timer(CI.getFrontendTimer()); 10760b57cec5SDimitry Andric ExecuteAction(); 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric else ExecuteAction(); 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric // If we are supposed to rebuild the global module index, do so now unless 10810b57cec5SDimitry Andric // there were any module-build failures. 10820b57cec5SDimitry Andric if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() && 10830b57cec5SDimitry Andric CI.hasPreprocessor()) { 10840b57cec5SDimitry Andric StringRef Cache = 10850b57cec5SDimitry Andric CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); 10860b57cec5SDimitry Andric if (!Cache.empty()) { 10870b57cec5SDimitry Andric if (llvm::Error Err = GlobalModuleIndex::writeIndex( 10880b57cec5SDimitry Andric CI.getFileManager(), CI.getPCHContainerReader(), Cache)) { 10890b57cec5SDimitry Andric // FIXME this drops the error on the floor, but 10900b57cec5SDimitry Andric // Index/pch-from-libclang.c seems to rely on dropping at least some of 10910b57cec5SDimitry Andric // the error conditions! 10920b57cec5SDimitry Andric consumeError(std::move(Err)); 10930b57cec5SDimitry Andric } 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric return llvm::Error::success(); 10980b57cec5SDimitry Andric } 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric void FrontendAction::EndSourceFile() { 11010b57cec5SDimitry Andric CompilerInstance &CI = getCompilerInstance(); 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric // Inform the diagnostic client we are done with this source file. 11040b57cec5SDimitry Andric CI.getDiagnosticClient().EndSourceFile(); 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric // Inform the preprocessor we are done. 11070b57cec5SDimitry Andric if (CI.hasPreprocessor()) 11080b57cec5SDimitry Andric CI.getPreprocessor().EndSourceFile(); 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric // Finalize the action. 11110b57cec5SDimitry Andric EndSourceFileAction(); 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric // Sema references the ast consumer, so reset sema first. 11140b57cec5SDimitry Andric // 11150b57cec5SDimitry Andric // FIXME: There is more per-file stuff we could just drop here? 11160b57cec5SDimitry Andric bool DisableFree = CI.getFrontendOpts().DisableFree; 11170b57cec5SDimitry Andric if (DisableFree) { 11180b57cec5SDimitry Andric CI.resetAndLeakSema(); 11190b57cec5SDimitry Andric CI.resetAndLeakASTContext(); 11200b57cec5SDimitry Andric llvm::BuryPointer(CI.takeASTConsumer().get()); 11210b57cec5SDimitry Andric } else { 11220b57cec5SDimitry Andric CI.setSema(nullptr); 11230b57cec5SDimitry Andric CI.setASTContext(nullptr); 11240b57cec5SDimitry Andric CI.setASTConsumer(nullptr); 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric if (CI.getFrontendOpts().ShowStats) { 112881ad6265SDimitry Andric llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFileOrBufferName() << "':\n"; 11290b57cec5SDimitry Andric CI.getPreprocessor().PrintStats(); 11300b57cec5SDimitry Andric CI.getPreprocessor().getIdentifierTable().PrintStats(); 11310b57cec5SDimitry Andric CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); 11320b57cec5SDimitry Andric CI.getSourceManager().PrintStats(); 11330b57cec5SDimitry Andric llvm::errs() << "\n"; 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric // Cleanup the output streams, and erase the output files if instructed by the 11370b57cec5SDimitry Andric // FrontendAction. 11380b57cec5SDimitry Andric CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles()); 11390b57cec5SDimitry Andric 114006c3fb27SDimitry Andric // The resources are owned by AST when the current file is AST. 114106c3fb27SDimitry Andric // So we reset the resources here to avoid users accessing it 114206c3fb27SDimitry Andric // accidently. 11430b57cec5SDimitry Andric if (isCurrentFileAST()) { 11440b57cec5SDimitry Andric if (DisableFree) { 11450b57cec5SDimitry Andric CI.resetAndLeakPreprocessor(); 11460b57cec5SDimitry Andric CI.resetAndLeakSourceManager(); 11470b57cec5SDimitry Andric CI.resetAndLeakFileManager(); 11480b57cec5SDimitry Andric llvm::BuryPointer(std::move(CurrentASTUnit)); 11490b57cec5SDimitry Andric } else { 11500b57cec5SDimitry Andric CI.setPreprocessor(nullptr); 11510b57cec5SDimitry Andric CI.setSourceManager(nullptr); 11520b57cec5SDimitry Andric CI.setFileManager(nullptr); 11530b57cec5SDimitry Andric } 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric setCompilerInstance(nullptr); 11570b57cec5SDimitry Andric setCurrentInput(FrontendInputFile()); 11580b57cec5SDimitry Andric CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); 11590b57cec5SDimitry Andric } 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric bool FrontendAction::shouldEraseOutputFiles() { 11620b57cec5SDimitry Andric return getCompilerInstance().getDiagnostics().hasErrorOccurred(); 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11660b57cec5SDimitry Andric // Utility Actions 11670b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric void ASTFrontendAction::ExecuteAction() { 11700b57cec5SDimitry Andric CompilerInstance &CI = getCompilerInstance(); 11710b57cec5SDimitry Andric if (!CI.hasPreprocessor()) 11720b57cec5SDimitry Andric return; 11738a4dda33SDimitry Andric // This is a fallback: If the client forgets to invoke this, we mark the 11748a4dda33SDimitry Andric // current stack as the bottom. Though not optimal, this could help prevent 11758a4dda33SDimitry Andric // stack overflow during deep recursion. 11768a4dda33SDimitry Andric clang::noteBottomOfStack(); 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric // FIXME: Move the truncation aspect of this into Sema, we delayed this till 11790b57cec5SDimitry Andric // here so the source manager would be initialized. 11800b57cec5SDimitry Andric if (hasCodeCompletionSupport() && 11810b57cec5SDimitry Andric !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 11820b57cec5SDimitry Andric CI.createCodeCompletionConsumer(); 11830b57cec5SDimitry Andric 11840b57cec5SDimitry Andric // Use a code completion consumer? 11850b57cec5SDimitry Andric CodeCompleteConsumer *CompletionConsumer = nullptr; 11860b57cec5SDimitry Andric if (CI.hasCodeCompletionConsumer()) 11870b57cec5SDimitry Andric CompletionConsumer = &CI.getCodeCompletionConsumer(); 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric if (!CI.hasSema()) 11900b57cec5SDimitry Andric CI.createSema(getTranslationUnitKind(), CompletionConsumer); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats, 11930b57cec5SDimitry Andric CI.getFrontendOpts().SkipFunctionBodies); 11940b57cec5SDimitry Andric } 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric void PluginASTAction::anchor() { } 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 11990b57cec5SDimitry Andric PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, 12000b57cec5SDimitry Andric StringRef InFile) { 12010b57cec5SDimitry Andric llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); 12020b57cec5SDimitry Andric } 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) { 12050b57cec5SDimitry Andric return WrappedAction->PrepareToExecuteAction(CI); 12060b57cec5SDimitry Andric } 12070b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 12080b57cec5SDimitry Andric WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, 12090b57cec5SDimitry Andric StringRef InFile) { 12100b57cec5SDimitry Andric return WrappedAction->CreateASTConsumer(CI, InFile); 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { 12130b57cec5SDimitry Andric return WrappedAction->BeginInvocation(CI); 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) { 12160b57cec5SDimitry Andric WrappedAction->setCurrentInput(getCurrentInput()); 12170b57cec5SDimitry Andric WrappedAction->setCompilerInstance(&CI); 12180b57cec5SDimitry Andric auto Ret = WrappedAction->BeginSourceFileAction(CI); 12190b57cec5SDimitry Andric // BeginSourceFileAction may change CurrentInput, e.g. during module builds. 12200b57cec5SDimitry Andric setCurrentInput(WrappedAction->getCurrentInput()); 12210b57cec5SDimitry Andric return Ret; 12220b57cec5SDimitry Andric } 12230b57cec5SDimitry Andric void WrapperFrontendAction::ExecuteAction() { 12240b57cec5SDimitry Andric WrappedAction->ExecuteAction(); 12250b57cec5SDimitry Andric } 1226fe6060f1SDimitry Andric void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); } 12270b57cec5SDimitry Andric void WrapperFrontendAction::EndSourceFileAction() { 12280b57cec5SDimitry Andric WrappedAction->EndSourceFileAction(); 12290b57cec5SDimitry Andric } 12305ffd83dbSDimitry Andric bool WrapperFrontendAction::shouldEraseOutputFiles() { 12315ffd83dbSDimitry Andric return WrappedAction->shouldEraseOutputFiles(); 12325ffd83dbSDimitry Andric } 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric bool WrapperFrontendAction::usesPreprocessorOnly() const { 12350b57cec5SDimitry Andric return WrappedAction->usesPreprocessorOnly(); 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() { 12380b57cec5SDimitry Andric return WrappedAction->getTranslationUnitKind(); 12390b57cec5SDimitry Andric } 12400b57cec5SDimitry Andric bool WrapperFrontendAction::hasPCHSupport() const { 12410b57cec5SDimitry Andric return WrappedAction->hasPCHSupport(); 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric bool WrapperFrontendAction::hasASTFileSupport() const { 12440b57cec5SDimitry Andric return WrappedAction->hasASTFileSupport(); 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric bool WrapperFrontendAction::hasIRSupport() const { 12470b57cec5SDimitry Andric return WrappedAction->hasIRSupport(); 12480b57cec5SDimitry Andric } 12490b57cec5SDimitry Andric bool WrapperFrontendAction::hasCodeCompletionSupport() const { 12500b57cec5SDimitry Andric return WrappedAction->hasCodeCompletionSupport(); 12510b57cec5SDimitry Andric } 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric WrapperFrontendAction::WrapperFrontendAction( 12540b57cec5SDimitry Andric std::unique_ptr<FrontendAction> WrappedAction) 12550b57cec5SDimitry Andric : WrappedAction(std::move(WrappedAction)) {} 1256