1496 lines · cpp
1//===--- FrontendAction.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Frontend/FrontendAction.h"10#include "clang/AST/ASTConsumer.h"11#include "clang/AST/ASTContext.h"12#include "clang/AST/Decl.h"13#include "clang/AST/DeclGroup.h"14#include "clang/Basic/Builtins.h"15#include "clang/Basic/DiagnosticFrontend.h"16#include "clang/Basic/DiagnosticOptions.h"17#include "clang/Basic/FileEntry.h"18#include "clang/Basic/LangOptions.h"19#include "clang/Basic/LangStandard.h"20#include "clang/Basic/Sarif.h"21#include "clang/Basic/SourceLocation.h"22#include "clang/Basic/SourceManager.h"23#include "clang/Basic/Stack.h"24#include "clang/Basic/TokenKinds.h"25#include "clang/Frontend/ASTUnit.h"26#include "clang/Frontend/CompilerInstance.h"27#include "clang/Frontend/FrontendPluginRegistry.h"28#include "clang/Frontend/LayoutOverrideSource.h"29#include "clang/Frontend/MultiplexConsumer.h"30#include "clang/Frontend/SARIFDiagnosticPrinter.h"31#include "clang/Frontend/Utils.h"32#include "clang/Lex/HeaderSearch.h"33#include "clang/Lex/LiteralSupport.h"34#include "clang/Lex/Preprocessor.h"35#include "clang/Lex/PreprocessorOptions.h"36#include "clang/Parse/ParseAST.h"37#include "clang/Sema/HLSLExternalSemaSource.h"38#include "clang/Sema/MultiplexExternalSemaSource.h"39#include "clang/Serialization/ASTDeserializationListener.h"40#include "clang/Serialization/ASTReader.h"41#include "clang/Serialization/GlobalModuleIndex.h"42#include "llvm/ADT/ScopeExit.h"43#include "llvm/ADT/SmallPtrSet.h"44#include "llvm/ADT/StringRef.h"45#include "llvm/Support/BuryPointer.h"46#include "llvm/Support/ErrorHandling.h"47#include "llvm/Support/FileSystem.h"48#include "llvm/Support/Path.h"49#include "llvm/Support/Timer.h"50#include "llvm/Support/raw_ostream.h"51#include <memory>52#include <system_error>53using namespace clang;54 55LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)56 57namespace {58 59/// DeserializedDeclsLineRangePrinter dumps ranges of deserialized declarations60/// to aid debugging and bug minimization. It implements ASTConsumer and61/// ASTDeserializationListener, so that an object of62/// DeserializedDeclsLineRangePrinter registers as its own listener. The63/// ASTDeserializationListener interface provides the DeclRead callback that we64/// use to collect the deserialized Decls. Note that printing or otherwise65/// processing them as this point is dangerous, since that could trigger66/// additional deserialization and crash compilation. Therefore, we process the67/// collected Decls in HandleTranslationUnit method of ASTConsumer. This is a68/// safe point, since we know that by this point all the Decls needed by the69/// compiler frontend have been deserialized. In case our processing causes70/// further deserialization, DeclRead from the listener might be called again.71/// However, at that point we don't accept any more Decls for processing.72class DeserializedDeclsSourceRangePrinter : public ASTConsumer,73 ASTDeserializationListener {74public:75 explicit DeserializedDeclsSourceRangePrinter(76 SourceManager &SM, std::unique_ptr<llvm::raw_fd_ostream> OS)77 : ASTDeserializationListener(), SM(SM), OS(std::move(OS)) {}78 79 ASTDeserializationListener *GetASTDeserializationListener() override {80 return this;81 }82 83 void DeclRead(GlobalDeclID ID, const Decl *D) override {84 if (!IsCollectingDecls)85 return;86 if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) ||87 isa<NamespaceDecl>(D) || isa<ExportDecl>(D)) {88 // These decls cover a lot of nested declarations that might not be used,89 // reducing the granularity and making the output less useful.90 return;91 }92 if (isa<ParmVarDecl>(D)) {93 // Parameters are covered by their functions.94 return;95 }96 auto *DC = D->getLexicalDeclContext();97 if (!DC || !shouldIncludeDeclsIn(DC))98 return;99 100 PendingDecls.push_back(D);101 for (; (isa<ExportDecl>(DC) || isa<NamespaceDecl>(DC)) &&102 ProcessedDeclContexts.insert(DC).second;103 DC = DC->getLexicalParent()) {104 // Add any interesting decl contexts that we have not seen before.105 // Note that we filter them out from DeclRead as that would include all106 // redeclarations of namespaces, potentially those that do not have any107 // imported declarations.108 PendingDecls.push_back(cast<Decl>(DC));109 }110 }111 112 struct Position {113 unsigned Line;114 unsigned Column;115 116 bool operator<(const Position &other) const {117 return std::tie(Line, Column) < std::tie(other.Line, other.Column);118 }119 120 static Position GetBeginSpelling(const SourceManager &SM,121 const CharSourceRange &R) {122 SourceLocation Begin = R.getBegin();123 return {SM.getSpellingLineNumber(Begin),124 SM.getSpellingColumnNumber(Begin)};125 }126 127 static Position GetEndSpelling(const SourceManager &SM,128 const CharSourceRange &Range,129 const LangOptions &LangOpts) {130 // For token ranges, compute end location for end character of the range.131 CharSourceRange R = Lexer::getAsCharRange(Range, SM, LangOpts);132 SourceLocation End = R.getEnd();133 // Relex the token past the end location of the last token in the source134 // range. If it's a semicolon, advance the location by one token.135 Token PossiblySemi;136 Lexer::getRawToken(End, PossiblySemi, SM, LangOpts, true);137 if (PossiblySemi.is(tok::semi))138 End = End.getLocWithOffset(1);139 // Column number of the returned end position is exclusive.140 return {SM.getSpellingLineNumber(End), SM.getSpellingColumnNumber(End)};141 }142 };143 144 struct RequiredRanges {145 StringRef Filename;146 std::vector<std::pair<Position, Position>> FromTo;147 };148 void HandleTranslationUnit(ASTContext &Context) override {149 assert(IsCollectingDecls && "HandleTranslationUnit called twice?");150 IsCollectingDecls = false;151 152 // Merge ranges in each of the files.153 struct FileData {154 std::vector<std::pair<Position, Position>> FromTo;155 OptionalFileEntryRef Ref;156 };157 llvm::DenseMap<const FileEntry *, FileData> FileToRanges;158 159 for (const Decl *D : PendingDecls) {160 for (CharSourceRange R : getRangesToMark(D)) {161 if (!R.isValid())162 continue;163 164 auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin()));165 if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) {166 // Such cases are rare and difficult to handle.167 continue;168 }169 170 auto &Data = FileToRanges[F];171 if (!Data.Ref)172 Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin()));173 Data.FromTo.push_back(174 {Position::GetBeginSpelling(SM, R),175 Position::GetEndSpelling(SM, R, D->getLangOpts())});176 }177 }178 179 // To simplify output, merge consecutive and intersecting ranges.180 std::vector<RequiredRanges> Result;181 for (auto &[F, Data] : FileToRanges) {182 auto &FromTo = Data.FromTo;183 assert(!FromTo.empty());184 185 if (!Data.Ref)186 continue;187 188 llvm::sort(FromTo);189 190 std::vector<std::pair<Position, Position>> MergedRanges;191 MergedRanges.push_back(FromTo.front());192 for (auto It = FromTo.begin() + 1; It < FromTo.end(); ++It) {193 if (MergedRanges.back().second < It->first) {194 MergedRanges.push_back(*It);195 continue;196 }197 if (MergedRanges.back().second < It->second)198 MergedRanges.back().second = It->second;199 }200 Result.push_back({Data.Ref->getName(), std::move(MergedRanges)});201 }202 printJson(Result);203 }204 205private:206 std::vector<const Decl *> PendingDecls;207 llvm::SmallPtrSet<const DeclContext *, 0> ProcessedDeclContexts;208 bool IsCollectingDecls = true;209 const SourceManager &SM;210 std::unique_ptr<llvm::raw_ostream> OS;211 212 static bool shouldIncludeDeclsIn(const DeclContext *DC) {213 assert(DC && "DC is null");214 // We choose to work at namespace level to reduce complexity and the number215 // of cases we care about.216 // We still need to carefully handle composite declarations like217 // `ExportDecl`.218 for (; DC; DC = DC->getLexicalParent()) {219 if (DC->isFileContext())220 return true;221 if (isa<ExportDecl>(DC))222 continue; // Depends on the parent.223 return false;224 }225 llvm_unreachable("DeclContext chain must end with a translation unit");226 }227 228 llvm::SmallVector<CharSourceRange, 2> getRangesToMark(const Decl *D) {229 if (auto *ED = dyn_cast<ExportDecl>(D)) {230 if (!ED->hasBraces())231 return {SM.getExpansionRange(ED->getExportLoc())};232 233 return {SM.getExpansionRange(SourceRange(234 ED->getExportLoc(),235 lexForLBrace(ED->getExportLoc(), D->getLangOpts()))),236 SM.getExpansionRange(ED->getRBraceLoc())};237 }238 239 auto *NS = dyn_cast<NamespaceDecl>(D);240 if (!NS)241 return {SM.getExpansionRange(D->getSourceRange())};242 243 SourceLocation LBraceLoc;244 if (NS->isAnonymousNamespace()) {245 LBraceLoc = NS->getLocation();246 } else {247 // Start with the location of the identifier.248 SourceLocation TokenBeforeLBrace = NS->getLocation();249 if (NS->hasAttrs()) {250 for (auto *A : NS->getAttrs()) {251 // But attributes may go after it.252 if (SM.isBeforeInTranslationUnit(TokenBeforeLBrace,253 A->getRange().getEnd())) {254 // Give up, the attributes are often coming from macros and we255 // cannot skip them reliably.256 return {};257 }258 }259 }260 LBraceLoc = lexForLBrace(TokenBeforeLBrace, D->getLangOpts());261 }262 return {SM.getExpansionRange(SourceRange(NS->getBeginLoc(), LBraceLoc)),263 SM.getExpansionRange(NS->getRBraceLoc())};264 }265 266 void printJson(llvm::ArrayRef<RequiredRanges> Result) {267 *OS << "{\n";268 *OS << R"( "required_ranges": [)" << "\n";269 for (size_t I = 0; I < Result.size(); ++I) {270 auto &F = Result[I].Filename;271 auto &MergedRanges = Result[I].FromTo;272 *OS << R"( {)" << "\n";273 *OS << R"( "file": ")" << F << "\"," << "\n";274 *OS << R"( "range": [)" << "\n";275 for (size_t J = 0; J < MergedRanges.size(); ++J) {276 auto &From = MergedRanges[J].first;277 auto &To = MergedRanges[J].second;278 *OS << R"( {)" << "\n";279 *OS << R"( "from": {)" << "\n";280 *OS << R"( "line": )" << From.Line << ",\n";281 *OS << R"( "column": )" << From.Column << "\n"282 << R"( },)" << "\n";283 *OS << R"( "to": {)" << "\n";284 *OS << R"( "line": )" << To.Line << ",\n";285 *OS << R"( "column": )" << To.Column << "\n"286 << R"( })" << "\n";287 *OS << R"( })";288 if (J < MergedRanges.size() - 1) {289 *OS << ",";290 }291 *OS << "\n";292 }293 *OS << " ]" << "\n" << " }";294 if (I < Result.size() - 1)295 *OS << ",";296 *OS << "\n";297 }298 *OS << " ]\n";299 *OS << "}\n";300 301 OS->flush();302 }303 304 SourceLocation lexForLBrace(SourceLocation TokenBeforeLBrace,305 const LangOptions &LangOpts) {306 // Now skip one token, the next should be the lbrace.307 Token Tok;308 if (Lexer::getRawToken(TokenBeforeLBrace, Tok, SM, LangOpts, true) ||309 Lexer::getRawToken(Tok.getEndLoc(), Tok, SM, LangOpts, true) ||310 Tok.getKind() != tok::l_brace) {311 // On error or if we did not find the token we expected, avoid marking312 // everything inside the namespace as used.313 return SourceLocation();314 }315 return Tok.getLocation();316 }317};318 319/// Dumps deserialized declarations.320class DeserializedDeclsDumper : public DelegatingDeserializationListener {321public:322 explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,323 bool DeletePrevious)324 : DelegatingDeserializationListener(Previous, DeletePrevious) {}325 326 void DeclRead(GlobalDeclID ID, const Decl *D) override {327 llvm::outs() << "PCH DECL: " << D->getDeclKindName();328 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {329 llvm::outs() << " - ";330 ND->printQualifiedName(llvm::outs());331 }332 llvm::outs() << "\n";333 334 DelegatingDeserializationListener::DeclRead(ID, D);335 }336};337 338/// Checks deserialized declarations and emits error if a name339/// matches one given in command-line using -error-on-deserialized-decl.340class DeserializedDeclsChecker : public DelegatingDeserializationListener {341 ASTContext &Ctx;342 std::set<std::string> NamesToCheck;343 344public:345 DeserializedDeclsChecker(ASTContext &Ctx,346 const std::set<std::string> &NamesToCheck,347 ASTDeserializationListener *Previous,348 bool DeletePrevious)349 : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx),350 NamesToCheck(NamesToCheck) {}351 352 void DeclRead(GlobalDeclID ID, const Decl *D) override {353 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))354 if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {355 unsigned DiagID356 = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,357 "%0 was deserialized");358 Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)359 << ND;360 }361 362 DelegatingDeserializationListener::DeclRead(ID, D);363 }364};365 366} // end anonymous namespace367 368FrontendAction::FrontendAction() : Instance(nullptr) {}369 370FrontendAction::~FrontendAction() {}371 372void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,373 std::unique_ptr<ASTUnit> AST) {374 this->CurrentInput = CurrentInput;375 CurrentASTUnit = std::move(AST);376}377 378Module *FrontendAction::getCurrentModule() const {379 CompilerInstance &CI = getCompilerInstance();380 return CI.getPreprocessor().getHeaderSearchInfo().lookupModule(381 CI.getLangOpts().CurrentModule, SourceLocation(), /*AllowSearch*/false);382}383 384std::unique_ptr<ASTConsumer>385FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,386 StringRef InFile) {387 std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile);388 if (!Consumer)389 return nullptr;390 391 std::vector<std::unique_ptr<ASTConsumer>> Consumers;392 llvm::StringRef DumpDeserializedDeclarationRangesPath =393 CI.getFrontendOpts().DumpMinimizationHintsPath;394 if (!DumpDeserializedDeclarationRangesPath.empty()) {395 std::error_code ErrorCode;396 auto FileStream = std::make_unique<llvm::raw_fd_ostream>(397 DumpDeserializedDeclarationRangesPath, ErrorCode,398 llvm::sys::fs::OF_TextWithCRLF);399 if (!ErrorCode) {400 Consumers.push_back(std::make_unique<DeserializedDeclsSourceRangePrinter>(401 CI.getSourceManager(), std::move(FileStream)));402 } else {403 llvm::errs() << "Failed to create output file for "404 "-dump-minimization-hints flag, file path: "405 << DumpDeserializedDeclarationRangesPath406 << ", error: " << ErrorCode.message() << "\n";407 }408 }409 410 // Validate -add-plugin args.411 bool FoundAllPlugins = true;412 for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) {413 bool Found = false;414 for (const FrontendPluginRegistry::entry &Plugin :415 FrontendPluginRegistry::entries()) {416 if (Plugin.getName() == Arg)417 Found = true;418 }419 if (!Found) {420 CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg;421 FoundAllPlugins = false;422 }423 }424 if (!FoundAllPlugins)425 return nullptr;426 427 // If this is a code completion run, avoid invoking the plugin consumers428 if (CI.hasCodeCompletionConsumer())429 return Consumer;430 431 // Collect the list of plugins that go before the main action (in Consumers)432 // or after it (in AfterConsumers)433 std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers;434 for (const FrontendPluginRegistry::entry &Plugin :435 FrontendPluginRegistry::entries()) {436 std::unique_ptr<PluginASTAction> P = Plugin.instantiate();437 PluginASTAction::ActionType ActionType = P->getActionType();438 if (ActionType == PluginASTAction::CmdlineAfterMainAction ||439 ActionType == PluginASTAction::CmdlineBeforeMainAction) {440 // This is O(|plugins| * |add_plugins|), but since both numbers are441 // way below 50 in practice, that's ok.442 if (llvm::is_contained(CI.getFrontendOpts().AddPluginActions,443 Plugin.getName())) {444 if (ActionType == PluginASTAction::CmdlineBeforeMainAction)445 ActionType = PluginASTAction::AddBeforeMainAction;446 else447 ActionType = PluginASTAction::AddAfterMainAction;448 }449 }450 if ((ActionType == PluginASTAction::AddBeforeMainAction ||451 ActionType == PluginASTAction::AddAfterMainAction) &&452 P->ParseArgs(453 CI,454 CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) {455 std::unique_ptr<ASTConsumer> PluginConsumer = P->CreateASTConsumer(CI, InFile);456 if (ActionType == PluginASTAction::AddBeforeMainAction) {457 Consumers.push_back(std::move(PluginConsumer));458 } else {459 AfterConsumers.push_back(std::move(PluginConsumer));460 }461 }462 }463 464 // Add to Consumers the main consumer, then all the plugins that go after it465 Consumers.push_back(std::move(Consumer));466 if (!AfterConsumers.empty()) {467 // If we have plugins after the main consumer, which may be the codegen468 // action, they likely will need the ASTContext, so don't clear it in the469 // codegen action.470 CI.getCodeGenOpts().ClearASTBeforeBackend = false;471 for (auto &C : AfterConsumers)472 Consumers.push_back(std::move(C));473 }474 475 assert(Consumers.size() >= 1 && "should have added the main consumer");476 if (Consumers.size() == 1)477 return std::move(Consumers.front());478 return std::make_unique<MultiplexConsumer>(std::move(Consumers));479}480 481/// For preprocessed files, if the first line is the linemarker and specifies482/// the original source file name, use that name as the input file name.483/// Returns the location of the first token after the line marker directive.484///485/// \param CI The compiler instance.486/// \param InputFile Populated with the filename from the line marker.487/// \param IsModuleMap If \c true, add a line note corresponding to this line488/// directive. (We need to do this because the directive will not be489/// visited by the preprocessor.)490static SourceLocation ReadOriginalFileName(CompilerInstance &CI,491 std::string &InputFile,492 bool IsModuleMap = false) {493 auto &SourceMgr = CI.getSourceManager();494 auto MainFileID = SourceMgr.getMainFileID();495 496 auto MainFileBuf = SourceMgr.getBufferOrNone(MainFileID);497 if (!MainFileBuf)498 return SourceLocation();499 500 std::unique_ptr<Lexer> RawLexer(501 new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts()));502 503 // If the first line has the syntax of504 //505 // # NUM "FILENAME"506 //507 // we use FILENAME as the input file name.508 Token T;509 if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash)510 return SourceLocation();511 if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() ||512 T.getKind() != tok::numeric_constant)513 return SourceLocation();514 515 unsigned LineNo;516 SourceLocation LineNoLoc = T.getLocation();517 if (IsModuleMap) {518 llvm::SmallString<16> Buffer;519 if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts())520 .getAsInteger(10, LineNo))521 return SourceLocation();522 }523 524 RawLexer->LexFromRawLexer(T);525 if (T.isAtStartOfLine() || T.getKind() != tok::string_literal)526 return SourceLocation();527 528 StringLiteralParser Literal(T, CI.getPreprocessor());529 if (Literal.hadError)530 return SourceLocation();531 RawLexer->LexFromRawLexer(T);532 if (T.isNot(tok::eof) && !T.isAtStartOfLine())533 return SourceLocation();534 InputFile = Literal.GetString().str();535 536 if (IsModuleMap)537 CI.getSourceManager().AddLineNote(538 LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false,539 false, SrcMgr::C_User_ModuleMap);540 541 return T.getLocation();542}543 544static SmallVectorImpl<char> &545operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {546 Includes.append(RHS.begin(), RHS.end());547 return Includes;548}549 550static void addHeaderInclude(StringRef HeaderName,551 SmallVectorImpl<char> &Includes,552 const LangOptions &LangOpts,553 bool IsExternC) {554 if (IsExternC && LangOpts.CPlusPlus)555 Includes += "extern \"C\" {\n";556 if (LangOpts.ObjC)557 Includes += "#import \"";558 else559 Includes += "#include \"";560 561 Includes += HeaderName;562 563 Includes += "\"\n";564 if (IsExternC && LangOpts.CPlusPlus)565 Includes += "}\n";566}567 568/// Collect the set of header includes needed to construct the given569/// module and update the TopHeaders file set of the module.570///571/// \param Module The module we're collecting includes from.572///573/// \param Includes Will be augmented with the set of \#includes or \#imports574/// needed to load all of the named headers.575static std::error_code collectModuleHeaderIncludes(576 const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag,577 ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) {578 // Don't collect any headers for unavailable modules.579 if (!Module->isAvailable())580 return std::error_code();581 582 // Resolve all lazy header directives to header files.583 ModMap.resolveHeaderDirectives(Module, /*File=*/std::nullopt);584 585 // If any headers are missing, we can't build this module. In most cases,586 // diagnostics for this should have already been produced; we only get here587 // if explicit stat information was provided.588 // FIXME: If the name resolves to a file with different stat information,589 // produce a better diagnostic.590 if (!Module->MissingHeaders.empty()) {591 auto &MissingHeader = Module->MissingHeaders.front();592 Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)593 << MissingHeader.IsUmbrella << MissingHeader.FileName;594 return std::error_code();595 }596 597 // Add includes for each of these headers.598 for (auto HK : {Module::HK_Normal, Module::HK_Private}) {599 for (const Module::Header &H : Module->getHeaders(HK)) {600 Module->addTopHeader(H.Entry);601 // Use the path as specified in the module map file. We'll look for this602 // file relative to the module build directory (the directory containing603 // the module map file) so this will find the same file that we found604 // while parsing the module map.605 addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,606 Module->IsExternC);607 }608 }609 // Note that Module->PrivateHeaders will not be a TopHeader.610 611 if (std::optional<Module::Header> UmbrellaHeader =612 Module->getUmbrellaHeaderAsWritten()) {613 Module->addTopHeader(UmbrellaHeader->Entry);614 if (Module->Parent)615 // Include the umbrella header for submodules.616 addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,617 Includes, LangOpts, Module->IsExternC);618 } else if (std::optional<Module::DirectoryName> UmbrellaDir =619 Module->getUmbrellaDirAsWritten()) {620 // Add all of the headers we find in this subdirectory.621 std::error_code EC;622 SmallString<128> DirNative;623 llvm::sys::path::native(UmbrellaDir->Entry.getName(), DirNative);624 625 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();626 SmallVector<std::pair<std::string, std::string>, 8> HeaderPaths;627 for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;628 Dir != End && !EC; Dir.increment(EC)) {629 // Check whether this entry has an extension typically associated with630 // headers.631 if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))632 .Cases({".h", ".H", ".hh", ".hpp"}, true)633 .Default(false))634 continue;635 636 // Compute the relative path from the directory to this file.637 SmallVector<StringRef, 16> Components;638 auto PathIt = llvm::sys::path::rbegin(Dir->path());639 for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)640 Components.push_back(*PathIt);641 SmallString<128> RelativeHeader(642 UmbrellaDir->PathRelativeToRootModuleDirectory);643 for (auto It = Components.rbegin(), End = Components.rend(); It != End;644 ++It)645 llvm::sys::path::append(RelativeHeader, *It);646 647 HeaderPaths.push_back(648 std::make_pair(Dir->path().str(), RelativeHeader.c_str()));649 }650 651 if (EC)652 return EC;653 654 // Sort header paths and make the header inclusion order deterministic655 // across different OSs and filesystems. As the header search table656 // serialization order depends on the file reference UID, we need to create657 // file references in deterministic order too.658 llvm::sort(HeaderPaths, llvm::less_first());659 for (auto &[Path, RelPath] : HeaderPaths) {660 auto Header = FileMgr.getOptionalFileRef(Path);661 // FIXME: This shouldn't happen unless there is a file system race. Is662 // that worth diagnosing?663 if (!Header)664 continue;665 666 // If this header is marked 'unavailable' in this module, don't include667 // it.668 if (ModMap.isHeaderUnavailableInModule(*Header, Module))669 continue;670 671 // Include this header as part of the umbrella directory.672 Module->addTopHeader(*Header);673 addHeaderInclude(RelPath, Includes, LangOpts, Module->IsExternC);674 }675 }676 677 // Recurse into submodules.678 for (auto *Submodule : Module->submodules())679 if (std::error_code Err = collectModuleHeaderIncludes(680 LangOpts, FileMgr, Diag, ModMap, Submodule, Includes))681 return Err;682 683 return std::error_code();684}685 686static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,687 bool IsPreprocessed,688 std::string &PresumedModuleMapFile,689 unsigned &Offset) {690 auto &SrcMgr = CI.getSourceManager();691 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();692 693 // Map the current input to a file.694 FileID ModuleMapID = SrcMgr.getMainFileID();695 OptionalFileEntryRef ModuleMap = SrcMgr.getFileEntryRefForID(ModuleMapID);696 assert(ModuleMap && "MainFileID without FileEntry");697 698 // If the module map is preprocessed, handle the initial line marker;699 // line directives are not part of the module map syntax in general.700 Offset = 0;701 if (IsPreprocessed) {702 SourceLocation EndOfLineMarker =703 ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true);704 if (EndOfLineMarker.isValid())705 Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;706 }707 708 // Load the module map file.709 if (HS.parseAndLoadModuleMapFile(*ModuleMap, IsSystem, ModuleMapID, &Offset,710 PresumedModuleMapFile))711 return true;712 713 if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset)714 Offset = 0;715 716 // Infer framework module if possible.717 if (HS.getModuleMap().canInferFrameworkModule(ModuleMap->getDir())) {718 SmallString<128> InferredFrameworkPath = ModuleMap->getDir().getName();719 llvm::sys::path::append(InferredFrameworkPath,720 CI.getLangOpts().ModuleName + ".framework");721 if (auto Dir =722 CI.getFileManager().getOptionalDirectoryRef(InferredFrameworkPath))723 (void)HS.getModuleMap().inferFrameworkModule(*Dir, IsSystem, nullptr);724 }725 726 return false;727}728 729static Module *prepareToBuildModule(CompilerInstance &CI,730 StringRef ModuleMapFilename) {731 if (CI.getLangOpts().CurrentModule.empty()) {732 CI.getDiagnostics().Report(diag::err_missing_module_name);733 734 // FIXME: Eventually, we could consider asking whether there was just735 // a single module described in the module map, and use that as a736 // default. Then it would be fairly trivial to just "compile" a module737 // map with a single module (the common case).738 return nullptr;739 }740 741 // Dig out the module definition.742 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();743 Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, SourceLocation(),744 /*AllowSearch=*/true);745 if (!M) {746 CI.getDiagnostics().Report(diag::err_missing_module)747 << CI.getLangOpts().CurrentModule << ModuleMapFilename;748 749 return nullptr;750 }751 752 // Check whether we can build this module at all.753 if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), *M,754 CI.getDiagnostics()))755 return nullptr;756 757 // Inform the preprocessor that includes from within the input buffer should758 // be resolved relative to the build directory of the module map file.759 CI.getPreprocessor().setMainFileDir(*M->Directory);760 761 // If the module was inferred from a different module map (via an expanded762 // umbrella module definition), track that fact.763 // FIXME: It would be preferable to fill this in as part of processing764 // the module map, rather than adding it after the fact.765 StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap;766 if (!OriginalModuleMapName.empty()) {767 auto OriginalModuleMap =768 CI.getFileManager().getOptionalFileRef(OriginalModuleMapName,769 /*openFile*/ true);770 if (!OriginalModuleMap) {771 CI.getDiagnostics().Report(diag::err_module_map_not_found)772 << OriginalModuleMapName;773 return nullptr;774 }775 if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID(776 CI.getSourceManager().getMainFileID())) {777 auto FileCharacter =778 M->IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;779 FileID OriginalModuleMapFID = CI.getSourceManager().getOrCreateFileID(780 *OriginalModuleMap, FileCharacter);781 CI.getPreprocessor()782 .getHeaderSearchInfo()783 .getModuleMap()784 .setInferredModuleAllowedBy(M, OriginalModuleMapFID);785 }786 }787 788 // If we're being run from the command-line, the module build stack will not789 // have been filled in yet, so complete it now in order to allow us to detect790 // module cycles.791 SourceManager &SourceMgr = CI.getSourceManager();792 if (SourceMgr.getModuleBuildStack().empty())793 SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,794 FullSourceLoc(SourceLocation(), SourceMgr));795 return M;796}797 798/// Compute the input buffer that should be used to build the specified module.799static std::unique_ptr<llvm::MemoryBuffer>800getInputBufferForModule(CompilerInstance &CI, Module *M) {801 FileManager &FileMgr = CI.getFileManager();802 803 // Collect the set of #includes we need to build the module.804 SmallString<256> HeaderContents;805 std::error_code Err = std::error_code();806 if (std::optional<Module::Header> UmbrellaHeader =807 M->getUmbrellaHeaderAsWritten())808 addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,809 HeaderContents, CI.getLangOpts(), M->IsExternC);810 Err = collectModuleHeaderIncludes(811 CI.getLangOpts(), FileMgr, CI.getDiagnostics(),812 CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,813 HeaderContents);814 815 if (Err) {816 CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)817 << M->getFullModuleName() << Err.message();818 return nullptr;819 }820 821 return llvm::MemoryBuffer::getMemBufferCopy(822 HeaderContents, Module::getModuleInputBufferName());823}824 825bool FrontendAction::BeginSourceFile(CompilerInstance &CI,826 const FrontendInputFile &RealInput) {827 FrontendInputFile Input(RealInput);828 assert(!Instance && "Already processing a source file!");829 assert(!Input.isEmpty() && "Unexpected empty filename!");830 setCurrentInput(Input);831 setCompilerInstance(&CI);832 833 bool HasBegunSourceFile = false;834 bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&835 usesPreprocessorOnly();836 837 // If we fail, reset state since the client will not end up calling the838 // matching EndSourceFile(). All paths that return true should release this.839 auto FailureCleanup = llvm::make_scope_exit([&]() {840 if (HasBegunSourceFile)841 CI.getDiagnosticClient().EndSourceFile();842 CI.setASTConsumer(nullptr);843 CI.clearOutputFiles(/*EraseFiles=*/true);844 CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);845 setCurrentInput(FrontendInputFile());846 setCompilerInstance(nullptr);847 });848 849 if (!BeginInvocation(CI))850 return false;851 852 // If we're replaying the build of an AST file, import it and set up853 // the initial state from its build.854 if (ReplayASTFile) {855 IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();856 857 // The AST unit populates its own diagnostics engine rather than ours.858 auto ASTDiags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(859 Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions());860 ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);861 862 // FIXME: What if the input is a memory buffer?863 StringRef InputFile = Input.getFile();864 865 std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(866 InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly,867 CI.getVirtualFileSystemPtr(), nullptr, ASTDiags, CI.getFileSystemOpts(),868 CI.getHeaderSearchOpts());869 if (!AST)870 return false;871 872 // Options relating to how we treat the input (but not what we do with it)873 // are inherited from the AST unit.874 CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts();875 CI.getPreprocessorOpts() = AST->getPreprocessorOpts();876 CI.getLangOpts() = AST->getLangOpts();877 878 // Set the shared objects, these are reset when we finish processing the879 // file, otherwise the CompilerInstance will happily destroy them.880 CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr());881 CI.setFileManager(AST->getFileManagerPtr());882 CI.createSourceManager();883 CI.getSourceManager().initializeForReplay(AST->getSourceManager());884 885 // Preload all the module files loaded transitively by the AST unit. Also886 // load all module map files that were parsed as part of building the AST887 // unit.888 if (auto ASTReader = AST->getASTReader()) {889 auto &MM = ASTReader->getModuleManager();890 auto &PrimaryModule = MM.getPrimaryModule();891 892 for (serialization::ModuleFile &MF : MM)893 if (&MF != &PrimaryModule)894 CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);895 896 ASTReader->visitTopLevelModuleMaps(PrimaryModule, [&](FileEntryRef FE) {897 CI.getFrontendOpts().ModuleMapFiles.push_back(898 std::string(FE.getName()));899 });900 }901 902 // Set up the input file for replay purposes.903 auto Kind = AST->getInputKind();904 if (Kind.getFormat() == InputKind::ModuleMap) {905 Module *ASTModule =906 AST->getPreprocessor().getHeaderSearchInfo().lookupModule(907 AST->getLangOpts().CurrentModule, SourceLocation(),908 /*AllowSearch*/ false);909 assert(ASTModule && "module file does not define its own module");910 Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);911 } else {912 auto &OldSM = AST->getSourceManager();913 FileID ID = OldSM.getMainFileID();914 if (auto File = OldSM.getFileEntryRefForID(ID))915 Input = FrontendInputFile(File->getName(), Kind);916 else917 Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind);918 }919 setCurrentInput(Input, std::move(AST));920 }921 922 // AST files follow a very different path, since they share objects via the923 // AST unit.924 if (Input.getKind().getFormat() == InputKind::Precompiled) {925 assert(!usesPreprocessorOnly() && "this case was handled above");926 assert(hasASTFileSupport() &&927 "This action does not have AST file support!");928 929 IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();930 931 // FIXME: What if the input is a memory buffer?932 StringRef InputFile = Input.getFile();933 934 std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(935 InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything,936 CI.getVirtualFileSystemPtr(), nullptr, Diags, CI.getFileSystemOpts(),937 CI.getHeaderSearchOpts(), &CI.getLangOpts());938 939 if (!AST)940 return false;941 942 // Inform the diagnostic client we are processing a source file.943 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);944 HasBegunSourceFile = true;945 946 // Set the shared objects, these are reset when we finish processing the947 // file, otherwise the CompilerInstance will happily destroy them.948 CI.setVirtualFileSystem(AST->getVirtualFileSystemPtr());949 CI.setFileManager(AST->getFileManagerPtr());950 CI.setSourceManager(AST->getSourceManagerPtr());951 CI.setPreprocessor(AST->getPreprocessorPtr());952 Preprocessor &PP = CI.getPreprocessor();953 PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),954 PP.getLangOpts());955 CI.setASTContext(AST->getASTContextPtr());956 957 setCurrentInput(Input, std::move(AST));958 959 // Initialize the action.960 if (!BeginSourceFileAction(CI))961 return false;962 963 // Create the AST consumer.964 CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile));965 if (!CI.hasASTConsumer())966 return false;967 968 FailureCleanup.release();969 return true;970 }971 972 // Set up the file system, file and source managers, if needed.973 if (!CI.hasVirtualFileSystem())974 CI.createVirtualFileSystem();975 if (!CI.hasFileManager())976 CI.createFileManager();977 if (!CI.hasSourceManager()) {978 CI.createSourceManager();979 if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) {980 static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient())981 ->setSarifWriter(982 std::make_unique<SarifDocumentWriter>(CI.getSourceManager()));983 }984 }985 986 // Set up embedding for any specified files. Do this before we load any987 // source files, including the primary module map for the compilation.988 for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {989 if (auto FE = CI.getFileManager().getOptionalFileRef(F, /*openFile*/true))990 CI.getSourceManager().setFileIsTransient(*FE);991 else992 CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;993 }994 if (CI.getFrontendOpts().ModulesEmbedAllFiles)995 CI.getSourceManager().setAllFilesAreTransient(true);996 997 // IR files bypass the rest of initialization.998 if (Input.getKind().getLanguage() == Language::LLVM_IR) {999 if (!hasIRSupport()) {1000 CI.getDiagnostics().Report(diag::err_ast_action_on_llvm_ir)1001 << Input.getFile();1002 return false;1003 }1004 1005 // Inform the diagnostic client we are processing a source file.1006 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);1007 HasBegunSourceFile = true;1008 1009 // Initialize the action.1010 if (!BeginSourceFileAction(CI))1011 return false;1012 1013 // Initialize the main file entry.1014 if (!CI.InitializeSourceManager(CurrentInput))1015 return false;1016 1017 FailureCleanup.release();1018 return true;1019 }1020 1021 // If the implicit PCH include is actually a directory, rather than1022 // a single file, search for a suitable PCH file in that directory.1023 if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {1024 FileManager &FileMgr = CI.getFileManager();1025 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();1026 StringRef PCHInclude = PPOpts.ImplicitPCHInclude;1027 std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();1028 if (auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude)) {1029 std::error_code EC;1030 SmallString<128> DirNative;1031 llvm::sys::path::native(PCHDir->getName(), DirNative);1032 bool Found = false;1033 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();1034 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),1035 DirEnd;1036 Dir != DirEnd && !EC; Dir.increment(EC)) {1037 // Check whether this is an acceptable AST file.1038 if (ASTReader::isAcceptableASTFile(1039 Dir->path(), FileMgr, CI.getModuleCache(),1040 CI.getPCHContainerReader(), CI.getLangOpts(),1041 CI.getCodeGenOpts(), CI.getTargetOpts(),1042 CI.getPreprocessorOpts(), SpecificModuleCachePath,1043 /*RequireStrictOptionMatches=*/true)) {1044 PPOpts.ImplicitPCHInclude = std::string(Dir->path());1045 Found = true;1046 break;1047 }1048 }1049 1050 if (!Found) {1051 CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;1052 return false;1053 }1054 }1055 }1056 1057 // Set up the preprocessor if needed. When parsing model files the1058 // preprocessor of the original source is reused.1059 if (!isModelParsingAction())1060 CI.createPreprocessor(getTranslationUnitKind());1061 1062 // Inform the diagnostic client we are processing a source file.1063 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),1064 &CI.getPreprocessor());1065 HasBegunSourceFile = true;1066 1067 // Handle C++20 header units.1068 // Here, the user has the option to specify that the header name should be1069 // looked up in the pre-processor search paths (and the main filename as1070 // passed by the driver might therefore be incomplete until that look-up).1071 if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&1072 !Input.getKind().isPreprocessed()) {1073 StringRef FileName = Input.getFile();1074 InputKind Kind = Input.getKind();1075 if (Kind.getHeaderUnitKind() != InputKind::HeaderUnit_Abs) {1076 assert(CI.hasPreprocessor() &&1077 "trying to build a header unit without a Pre-processor?");1078 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();1079 // Relative searches begin from CWD.1080 auto Dir = CI.getFileManager().getOptionalDirectoryRef(".");1081 SmallVector<std::pair<OptionalFileEntryRef, DirectoryEntryRef>, 1> CWD;1082 CWD.push_back({std::nullopt, *Dir});1083 OptionalFileEntryRef FE =1084 HS.LookupFile(FileName, SourceLocation(),1085 /*Angled*/ Input.getKind().getHeaderUnitKind() ==1086 InputKind::HeaderUnit_System,1087 nullptr, nullptr, CWD, nullptr, nullptr, nullptr,1088 nullptr, nullptr, nullptr);1089 if (!FE) {1090 CI.getDiagnostics().Report(diag::err_module_header_file_not_found)1091 << FileName;1092 return false;1093 }1094 // We now have the filename...1095 FileName = FE->getName();1096 // ... still a header unit, but now use the path as written.1097 Kind = Input.getKind().withHeaderUnit(InputKind::HeaderUnit_Abs);1098 Input = FrontendInputFile(FileName, Kind, Input.isSystem());1099 }1100 // Unless the user has overridden the name, the header unit module name is1101 // the pathname for the file.1102 if (CI.getLangOpts().ModuleName.empty())1103 CI.getLangOpts().ModuleName = std::string(FileName);1104 CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;1105 }1106 1107 if (!CI.InitializeSourceManager(Input))1108 return false;1109 1110 if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&1111 Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {1112 // We have an input filename like foo.iih, but we want to find the right1113 // module name (and original file, to build the map entry).1114 // Check if the first line specifies the original source file name with a1115 // linemarker.1116 std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());1117 ReadOriginalFileName(CI, PresumedInputFile);1118 // Unless the user overrides this, the module name is the name by which the1119 // original file was known.1120 if (CI.getLangOpts().ModuleName.empty())1121 CI.getLangOpts().ModuleName = std::string(PresumedInputFile);1122 CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;1123 }1124 1125 // For module map files, we first parse the module map and synthesize a1126 // "<module-includes>" buffer before more conventional processing.1127 if (Input.getKind().getFormat() == InputKind::ModuleMap) {1128 CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);1129 1130 std::string PresumedModuleMapFile;1131 unsigned OffsetToContents;1132 if (loadModuleMapForModuleBuild(CI, Input.isSystem(),1133 Input.isPreprocessed(),1134 PresumedModuleMapFile, OffsetToContents))1135 return false;1136 1137 auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());1138 if (!CurrentModule)1139 return false;1140 1141 CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile;1142 1143 if (OffsetToContents)1144 // If the module contents are in the same file, skip to them.1145 CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);1146 else {1147 // Otherwise, convert the module description to a suitable input buffer.1148 auto Buffer = getInputBufferForModule(CI, CurrentModule);1149 if (!Buffer)1150 return false;1151 1152 // Reinitialize the main file entry to refer to the new input.1153 auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User;1154 auto &SourceMgr = CI.getSourceManager();1155 auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind);1156 assert(BufferID.isValid() && "couldn't create module buffer ID");1157 SourceMgr.setMainFileID(BufferID);1158 }1159 }1160 1161 // Initialize the action.1162 if (!BeginSourceFileAction(CI))1163 return false;1164 1165 // If we were asked to load any module map files, do so now.1166 for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {1167 if (auto File = CI.getFileManager().getOptionalFileRef(Filename))1168 CI.getPreprocessor().getHeaderSearchInfo().parseAndLoadModuleMapFile(1169 *File, /*IsSystem*/ false);1170 else1171 CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;1172 }1173 1174 // If compiling implementation of a module, load its module map file now.1175 (void)CI.getPreprocessor().getCurrentModuleImplementation();1176 1177 // Add a module declaration scope so that modules from -fmodule-map-file1178 // arguments may shadow modules found implicitly in search paths.1179 CI.getPreprocessor()1180 .getHeaderSearchInfo()1181 .getModuleMap()1182 .finishModuleDeclarationScope();1183 1184 // Create the AST context and consumer unless this is a preprocessor only1185 // action.1186 if (!usesPreprocessorOnly()) {1187 // Parsing a model file should reuse the existing ASTContext.1188 if (!isModelParsingAction())1189 CI.createASTContext();1190 1191 // For preprocessed files, check if the first line specifies the original1192 // source file name with a linemarker.1193 std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());1194 if (Input.isPreprocessed())1195 ReadOriginalFileName(CI, PresumedInputFile);1196 1197 std::unique_ptr<ASTConsumer> Consumer =1198 CreateWrappedASTConsumer(CI, PresumedInputFile);1199 if (!Consumer)1200 return false;1201 1202 // FIXME: should not overwrite ASTMutationListener when parsing model files?1203 if (!isModelParsingAction())1204 CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());1205 1206 if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {1207 // Convert headers to PCH and chain them.1208 IntrusiveRefCntPtr<ExternalSemaSource> source;1209 IntrusiveRefCntPtr<ASTReader> FinalReader;1210 source = createChainedIncludesSource(CI, FinalReader);1211 if (!source)1212 return false;1213 CI.setASTReader(FinalReader);1214 CI.getASTContext().setExternalSource(source);1215 } else if (CI.getLangOpts().Modules ||1216 !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {1217 // Use PCM or PCH.1218 assert(hasPCHSupport() && "This action does not have PCH support!");1219 ASTDeserializationListener *DeserialListener =1220 Consumer->GetASTDeserializationListener();1221 bool DeleteDeserialListener = false;1222 if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) {1223 DeserialListener = new DeserializedDeclsDumper(DeserialListener,1224 DeleteDeserialListener);1225 DeleteDeserialListener = true;1226 }1227 if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) {1228 DeserialListener = new DeserializedDeclsChecker(1229 CI.getASTContext(),1230 CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,1231 DeserialListener, DeleteDeserialListener);1232 DeleteDeserialListener = true;1233 }1234 if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {1235 CI.createPCHExternalASTSource(1236 CI.getPreprocessorOpts().ImplicitPCHInclude,1237 CI.getPreprocessorOpts().DisablePCHOrModuleValidation,1238 CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,1239 DeserialListener, DeleteDeserialListener);1240 if (!CI.getASTContext().getExternalSource())1241 return false;1242 }1243 // If modules are enabled, create the AST reader before creating1244 // any builtins, so that all declarations know that they might be1245 // extended by an external source.1246 if (CI.getLangOpts().Modules || !CI.hasASTContext() ||1247 !CI.getASTContext().getExternalSource()) {1248 CI.createASTReader();1249 CI.getASTReader()->setDeserializationListener(DeserialListener,1250 DeleteDeserialListener);1251 }1252 }1253 1254 CI.setASTConsumer(std::move(Consumer));1255 if (!CI.hasASTConsumer())1256 return false;1257 }1258 1259 // Initialize built-in info as long as we aren't using an external AST1260 // source.1261 if (CI.getLangOpts().Modules || !CI.hasASTContext() ||1262 !CI.getASTContext().getExternalSource()) {1263 Preprocessor &PP = CI.getPreprocessor();1264 PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),1265 PP.getLangOpts());1266 } else {1267 // FIXME: If this is a problem, recover from it by creating a multiplex1268 // source.1269 assert((!CI.getLangOpts().Modules || CI.getASTReader()) &&1270 "modules enabled but created an external source that "1271 "doesn't support modules");1272 }1273 1274 // If we were asked to load any module files, do so now.1275 for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) {1276 serialization::ModuleFile *Loaded = nullptr;1277 if (!CI.loadModuleFile(ModuleFile, Loaded))1278 return false;1279 1280 if (Loaded && Loaded->StandardCXXModule)1281 CI.getDiagnostics().Report(1282 diag::warn_eagerly_load_for_standard_cplusplus_modules);1283 }1284 1285 // If there is a layout overrides file, attach an external AST source that1286 // provides the layouts from that file.1287 if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&1288 CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {1289 auto Override = llvm::makeIntrusiveRefCnt<LayoutOverrideSource>(1290 CI.getFrontendOpts().OverrideRecordLayoutsFile);1291 CI.getASTContext().setExternalSource(Override);1292 }1293 1294 // Setup HLSL External Sema Source1295 if (CI.getLangOpts().HLSL && CI.hasASTContext()) {1296 auto HLSLSema = llvm::makeIntrusiveRefCnt<HLSLExternalSemaSource>();1297 if (auto SemaSource = dyn_cast_if_present<ExternalSemaSource>(1298 CI.getASTContext().getExternalSourcePtr())) {1299 auto MultiSema = llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(1300 std::move(SemaSource), std::move(HLSLSema));1301 CI.getASTContext().setExternalSource(std::move(MultiSema));1302 } else1303 CI.getASTContext().setExternalSource(std::move(HLSLSema));1304 }1305 1306 FailureCleanup.release();1307 return true;1308}1309 1310llvm::Error FrontendAction::Execute() {1311 CompilerInstance &CI = getCompilerInstance();1312 ExecuteAction();1313 1314 // If we are supposed to rebuild the global module index, do so now unless1315 // there were any module-build failures.1316 if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&1317 CI.hasPreprocessor()) {1318 StringRef Cache =1319 CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath();1320 if (!Cache.empty()) {1321 if (llvm::Error Err = GlobalModuleIndex::writeIndex(1322 CI.getFileManager(), CI.getPCHContainerReader(), Cache)) {1323 // FIXME this drops the error on the floor, but1324 // Index/pch-from-libclang.c seems to rely on dropping at least some of1325 // the error conditions!1326 consumeError(std::move(Err));1327 }1328 }1329 }1330 1331 return llvm::Error::success();1332}1333 1334void FrontendAction::EndSourceFile() {1335 CompilerInstance &CI = getCompilerInstance();1336 1337 // Inform the preprocessor we are done.1338 if (CI.hasPreprocessor())1339 CI.getPreprocessor().EndSourceFile();1340 1341 // Inform the diagnostic client we are done with this source file.1342 // Do this after notifying the preprocessor, so that end-of-file preprocessor1343 // callbacks can report diagnostics.1344 CI.getDiagnosticClient().EndSourceFile();1345 1346 // Finalize the action.1347 EndSourceFileAction();1348 1349 // Sema references the ast consumer, so reset sema first.1350 //1351 // FIXME: There is more per-file stuff we could just drop here?1352 bool DisableFree = CI.getFrontendOpts().DisableFree;1353 if (DisableFree) {1354 CI.resetAndLeakSema();1355 CI.resetAndLeakASTContext();1356 llvm::BuryPointer(CI.takeASTConsumer().get());1357 } else {1358 CI.setSema(nullptr);1359 CI.setASTContext(nullptr);1360 CI.setASTConsumer(nullptr);1361 }1362 1363 if (CI.getFrontendOpts().ShowStats) {1364 llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFileOrBufferName() << "':\n";1365 if (CI.hasPreprocessor()) {1366 CI.getPreprocessor().PrintStats();1367 CI.getPreprocessor().getIdentifierTable().PrintStats();1368 CI.getPreprocessor().getHeaderSearchInfo().PrintStats();1369 }1370 if (CI.hasSourceManager()) {1371 CI.getSourceManager().PrintStats();1372 }1373 llvm::errs() << "\n";1374 }1375 1376 // Cleanup the output streams, and erase the output files if instructed by the1377 // FrontendAction.1378 CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());1379 1380 // The resources are owned by AST when the current file is AST.1381 // So we reset the resources here to avoid users accessing it1382 // accidently.1383 if (isCurrentFileAST()) {1384 if (DisableFree) {1385 CI.resetAndLeakPreprocessor();1386 CI.resetAndLeakSourceManager();1387 CI.resetAndLeakFileManager();1388 llvm::BuryPointer(std::move(CurrentASTUnit));1389 } else {1390 CI.setPreprocessor(nullptr);1391 CI.setSourceManager(nullptr);1392 CI.setFileManager(nullptr);1393 }1394 }1395 1396 setCompilerInstance(nullptr);1397 setCurrentInput(FrontendInputFile());1398 CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);1399}1400 1401bool FrontendAction::shouldEraseOutputFiles() {1402 return getCompilerInstance().getDiagnostics().hasErrorOccurred();1403}1404 1405//===----------------------------------------------------------------------===//1406// Utility Actions1407//===----------------------------------------------------------------------===//1408 1409void ASTFrontendAction::ExecuteAction() {1410 CompilerInstance &CI = getCompilerInstance();1411 if (!CI.hasPreprocessor())1412 return;1413 // This is a fallback: If the client forgets to invoke this, we mark the1414 // current stack as the bottom. Though not optimal, this could help prevent1415 // stack overflow during deep recursion.1416 clang::noteBottomOfStack();1417 1418 // FIXME: Move the truncation aspect of this into Sema, we delayed this till1419 // here so the source manager would be initialized.1420 if (hasCodeCompletionSupport() &&1421 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())1422 CI.createCodeCompletionConsumer();1423 1424 // Use a code completion consumer?1425 CodeCompleteConsumer *CompletionConsumer = nullptr;1426 if (CI.hasCodeCompletionConsumer())1427 CompletionConsumer = &CI.getCodeCompletionConsumer();1428 1429 if (!CI.hasSema())1430 CI.createSema(getTranslationUnitKind(), CompletionConsumer);1431 1432 ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,1433 CI.getFrontendOpts().SkipFunctionBodies);1434}1435 1436void PluginASTAction::anchor() { }1437 1438std::unique_ptr<ASTConsumer>1439PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,1440 StringRef InFile) {1441 llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");1442}1443 1444bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) {1445 return WrappedAction->PrepareToExecuteAction(CI);1446}1447std::unique_ptr<ASTConsumer>1448WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,1449 StringRef InFile) {1450 return WrappedAction->CreateASTConsumer(CI, InFile);1451}1452bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {1453 return WrappedAction->BeginInvocation(CI);1454}1455bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) {1456 WrappedAction->setCurrentInput(getCurrentInput());1457 WrappedAction->setCompilerInstance(&CI);1458 auto Ret = WrappedAction->BeginSourceFileAction(CI);1459 // BeginSourceFileAction may change CurrentInput, e.g. during module builds.1460 setCurrentInput(WrappedAction->getCurrentInput());1461 return Ret;1462}1463void WrapperFrontendAction::ExecuteAction() {1464 WrappedAction->ExecuteAction();1465}1466void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); }1467void WrapperFrontendAction::EndSourceFileAction() {1468 WrappedAction->EndSourceFileAction();1469}1470bool WrapperFrontendAction::shouldEraseOutputFiles() {1471 return WrappedAction->shouldEraseOutputFiles();1472}1473 1474bool WrapperFrontendAction::usesPreprocessorOnly() const {1475 return WrappedAction->usesPreprocessorOnly();1476}1477TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {1478 return WrappedAction->getTranslationUnitKind();1479}1480bool WrapperFrontendAction::hasPCHSupport() const {1481 return WrappedAction->hasPCHSupport();1482}1483bool WrapperFrontendAction::hasASTFileSupport() const {1484 return WrappedAction->hasASTFileSupport();1485}1486bool WrapperFrontendAction::hasIRSupport() const {1487 return WrappedAction->hasIRSupport();1488}1489bool WrapperFrontendAction::hasCodeCompletionSupport() const {1490 return WrappedAction->hasCodeCompletionSupport();1491}1492 1493WrapperFrontendAction::WrapperFrontendAction(1494 std::unique_ptr<FrontendAction> WrappedAction)1495 : WrappedAction(std::move(WrappedAction)) {}1496