brintos

brintos / llvm-project-archived public Read only

0
0
Text · 57.8 KiB · 1b56718 Raw
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