Path: blob/main/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp
35232 views
//===--- FrontendAction.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Frontend/FrontendAction.h"9#include "clang/AST/ASTConsumer.h"10#include "clang/AST/ASTContext.h"11#include "clang/AST/DeclGroup.h"12#include "clang/Basic/Builtins.h"13#include "clang/Basic/DiagnosticOptions.h"14#include "clang/Basic/FileEntry.h"15#include "clang/Basic/LangStandard.h"16#include "clang/Basic/Sarif.h"17#include "clang/Basic/Stack.h"18#include "clang/Frontend/ASTUnit.h"19#include "clang/Frontend/CompilerInstance.h"20#include "clang/Frontend/FrontendDiagnostic.h"21#include "clang/Frontend/FrontendPluginRegistry.h"22#include "clang/Frontend/LayoutOverrideSource.h"23#include "clang/Frontend/MultiplexConsumer.h"24#include "clang/Frontend/SARIFDiagnosticPrinter.h"25#include "clang/Frontend/Utils.h"26#include "clang/Lex/HeaderSearch.h"27#include "clang/Lex/LiteralSupport.h"28#include "clang/Lex/Preprocessor.h"29#include "clang/Lex/PreprocessorOptions.h"30#include "clang/Parse/ParseAST.h"31#include "clang/Sema/HLSLExternalSemaSource.h"32#include "clang/Sema/MultiplexExternalSemaSource.h"33#include "clang/Serialization/ASTDeserializationListener.h"34#include "clang/Serialization/ASTReader.h"35#include "clang/Serialization/GlobalModuleIndex.h"36#include "llvm/ADT/ScopeExit.h"37#include "llvm/Support/BuryPointer.h"38#include "llvm/Support/ErrorHandling.h"39#include "llvm/Support/FileSystem.h"40#include "llvm/Support/Path.h"41#include "llvm/Support/Timer.h"42#include "llvm/Support/raw_ostream.h"43#include <memory>44#include <system_error>45using namespace clang;4647LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)4849namespace {5051class DelegatingDeserializationListener : public ASTDeserializationListener {52ASTDeserializationListener *Previous;53bool DeletePrevious;5455public:56explicit DelegatingDeserializationListener(57ASTDeserializationListener *Previous, bool DeletePrevious)58: Previous(Previous), DeletePrevious(DeletePrevious) {}59~DelegatingDeserializationListener() override {60if (DeletePrevious)61delete Previous;62}6364DelegatingDeserializationListener(const DelegatingDeserializationListener &) =65delete;66DelegatingDeserializationListener &67operator=(const DelegatingDeserializationListener &) = delete;6869void ReaderInitialized(ASTReader *Reader) override {70if (Previous)71Previous->ReaderInitialized(Reader);72}73void IdentifierRead(serialization::IdentifierID ID,74IdentifierInfo *II) override {75if (Previous)76Previous->IdentifierRead(ID, II);77}78void TypeRead(serialization::TypeIdx Idx, QualType T) override {79if (Previous)80Previous->TypeRead(Idx, T);81}82void DeclRead(GlobalDeclID ID, const Decl *D) override {83if (Previous)84Previous->DeclRead(ID, D);85}86void SelectorRead(serialization::SelectorID ID, Selector Sel) override {87if (Previous)88Previous->SelectorRead(ID, Sel);89}90void MacroDefinitionRead(serialization::PreprocessedEntityID PPID,91MacroDefinitionRecord *MD) override {92if (Previous)93Previous->MacroDefinitionRead(PPID, MD);94}95};9697/// Dumps deserialized declarations.98class DeserializedDeclsDumper : public DelegatingDeserializationListener {99public:100explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,101bool DeletePrevious)102: DelegatingDeserializationListener(Previous, DeletePrevious) {}103104void DeclRead(GlobalDeclID ID, const Decl *D) override {105llvm::outs() << "PCH DECL: " << D->getDeclKindName();106if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {107llvm::outs() << " - ";108ND->printQualifiedName(llvm::outs());109}110llvm::outs() << "\n";111112DelegatingDeserializationListener::DeclRead(ID, D);113}114};115116/// Checks deserialized declarations and emits error if a name117/// matches one given in command-line using -error-on-deserialized-decl.118class DeserializedDeclsChecker : public DelegatingDeserializationListener {119ASTContext &Ctx;120std::set<std::string> NamesToCheck;121122public:123DeserializedDeclsChecker(ASTContext &Ctx,124const std::set<std::string> &NamesToCheck,125ASTDeserializationListener *Previous,126bool DeletePrevious)127: DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx),128NamesToCheck(NamesToCheck) {}129130void DeclRead(GlobalDeclID ID, const Decl *D) override {131if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))132if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {133unsigned DiagID134= Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,135"%0 was deserialized");136Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)137<< ND;138}139140DelegatingDeserializationListener::DeclRead(ID, D);141}142};143144} // end anonymous namespace145146FrontendAction::FrontendAction() : Instance(nullptr) {}147148FrontendAction::~FrontendAction() {}149150void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,151std::unique_ptr<ASTUnit> AST) {152this->CurrentInput = CurrentInput;153CurrentASTUnit = std::move(AST);154}155156Module *FrontendAction::getCurrentModule() const {157CompilerInstance &CI = getCompilerInstance();158return CI.getPreprocessor().getHeaderSearchInfo().lookupModule(159CI.getLangOpts().CurrentModule, SourceLocation(), /*AllowSearch*/false);160}161162std::unique_ptr<ASTConsumer>163FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,164StringRef InFile) {165std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile);166if (!Consumer)167return nullptr;168169// Validate -add-plugin args.170bool FoundAllPlugins = true;171for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) {172bool Found = false;173for (const FrontendPluginRegistry::entry &Plugin :174FrontendPluginRegistry::entries()) {175if (Plugin.getName() == Arg)176Found = true;177}178if (!Found) {179CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg;180FoundAllPlugins = false;181}182}183if (!FoundAllPlugins)184return nullptr;185186// If there are no registered plugins we don't need to wrap the consumer187if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end())188return Consumer;189190// If this is a code completion run, avoid invoking the plugin consumers191if (CI.hasCodeCompletionConsumer())192return Consumer;193194// Collect the list of plugins that go before the main action (in Consumers)195// or after it (in AfterConsumers)196std::vector<std::unique_ptr<ASTConsumer>> Consumers;197std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers;198for (const FrontendPluginRegistry::entry &Plugin :199FrontendPluginRegistry::entries()) {200std::unique_ptr<PluginASTAction> P = Plugin.instantiate();201PluginASTAction::ActionType ActionType = P->getActionType();202if (ActionType == PluginASTAction::CmdlineAfterMainAction ||203ActionType == PluginASTAction::CmdlineBeforeMainAction) {204// This is O(|plugins| * |add_plugins|), but since both numbers are205// way below 50 in practice, that's ok.206if (llvm::is_contained(CI.getFrontendOpts().AddPluginActions,207Plugin.getName())) {208if (ActionType == PluginASTAction::CmdlineBeforeMainAction)209ActionType = PluginASTAction::AddBeforeMainAction;210else211ActionType = PluginASTAction::AddAfterMainAction;212}213}214if ((ActionType == PluginASTAction::AddBeforeMainAction ||215ActionType == PluginASTAction::AddAfterMainAction) &&216P->ParseArgs(217CI,218CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) {219std::unique_ptr<ASTConsumer> PluginConsumer = P->CreateASTConsumer(CI, InFile);220if (ActionType == PluginASTAction::AddBeforeMainAction) {221Consumers.push_back(std::move(PluginConsumer));222} else {223AfterConsumers.push_back(std::move(PluginConsumer));224}225}226}227228// Add to Consumers the main consumer, then all the plugins that go after it229Consumers.push_back(std::move(Consumer));230if (!AfterConsumers.empty()) {231// If we have plugins after the main consumer, which may be the codegen232// action, they likely will need the ASTContext, so don't clear it in the233// codegen action.234CI.getCodeGenOpts().ClearASTBeforeBackend = false;235for (auto &C : AfterConsumers)236Consumers.push_back(std::move(C));237}238239return std::make_unique<MultiplexConsumer>(std::move(Consumers));240}241242/// For preprocessed files, if the first line is the linemarker and specifies243/// the original source file name, use that name as the input file name.244/// Returns the location of the first token after the line marker directive.245///246/// \param CI The compiler instance.247/// \param InputFile Populated with the filename from the line marker.248/// \param IsModuleMap If \c true, add a line note corresponding to this line249/// directive. (We need to do this because the directive will not be250/// visited by the preprocessor.)251static SourceLocation ReadOriginalFileName(CompilerInstance &CI,252std::string &InputFile,253bool IsModuleMap = false) {254auto &SourceMgr = CI.getSourceManager();255auto MainFileID = SourceMgr.getMainFileID();256257auto MainFileBuf = SourceMgr.getBufferOrNone(MainFileID);258if (!MainFileBuf)259return SourceLocation();260261std::unique_ptr<Lexer> RawLexer(262new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts()));263264// If the first line has the syntax of265//266// # NUM "FILENAME"267//268// we use FILENAME as the input file name.269Token T;270if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash)271return SourceLocation();272if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() ||273T.getKind() != tok::numeric_constant)274return SourceLocation();275276unsigned LineNo;277SourceLocation LineNoLoc = T.getLocation();278if (IsModuleMap) {279llvm::SmallString<16> Buffer;280if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts())281.getAsInteger(10, LineNo))282return SourceLocation();283}284285RawLexer->LexFromRawLexer(T);286if (T.isAtStartOfLine() || T.getKind() != tok::string_literal)287return SourceLocation();288289StringLiteralParser Literal(T, CI.getPreprocessor());290if (Literal.hadError)291return SourceLocation();292RawLexer->LexFromRawLexer(T);293if (T.isNot(tok::eof) && !T.isAtStartOfLine())294return SourceLocation();295InputFile = Literal.GetString().str();296297if (IsModuleMap)298CI.getSourceManager().AddLineNote(299LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false,300false, SrcMgr::C_User_ModuleMap);301302return T.getLocation();303}304305static SmallVectorImpl<char> &306operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {307Includes.append(RHS.begin(), RHS.end());308return Includes;309}310311static void addHeaderInclude(StringRef HeaderName,312SmallVectorImpl<char> &Includes,313const LangOptions &LangOpts,314bool IsExternC) {315if (IsExternC && LangOpts.CPlusPlus)316Includes += "extern \"C\" {\n";317if (LangOpts.ObjC)318Includes += "#import \"";319else320Includes += "#include \"";321322Includes += HeaderName;323324Includes += "\"\n";325if (IsExternC && LangOpts.CPlusPlus)326Includes += "}\n";327}328329/// Collect the set of header includes needed to construct the given330/// module and update the TopHeaders file set of the module.331///332/// \param Module The module we're collecting includes from.333///334/// \param Includes Will be augmented with the set of \#includes or \#imports335/// needed to load all of the named headers.336static std::error_code collectModuleHeaderIncludes(337const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag,338ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) {339// Don't collect any headers for unavailable modules.340if (!Module->isAvailable())341return std::error_code();342343// Resolve all lazy header directives to header files.344ModMap.resolveHeaderDirectives(Module, /*File=*/std::nullopt);345346// If any headers are missing, we can't build this module. In most cases,347// diagnostics for this should have already been produced; we only get here348// if explicit stat information was provided.349// FIXME: If the name resolves to a file with different stat information,350// produce a better diagnostic.351if (!Module->MissingHeaders.empty()) {352auto &MissingHeader = Module->MissingHeaders.front();353Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)354<< MissingHeader.IsUmbrella << MissingHeader.FileName;355return std::error_code();356}357358// Add includes for each of these headers.359for (auto HK : {Module::HK_Normal, Module::HK_Private}) {360for (Module::Header &H : Module->Headers[HK]) {361Module->addTopHeader(H.Entry);362// Use the path as specified in the module map file. We'll look for this363// file relative to the module build directory (the directory containing364// the module map file) so this will find the same file that we found365// while parsing the module map.366addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,367Module->IsExternC);368}369}370// Note that Module->PrivateHeaders will not be a TopHeader.371372if (std::optional<Module::Header> UmbrellaHeader =373Module->getUmbrellaHeaderAsWritten()) {374Module->addTopHeader(UmbrellaHeader->Entry);375if (Module->Parent)376// Include the umbrella header for submodules.377addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,378Includes, LangOpts, Module->IsExternC);379} else if (std::optional<Module::DirectoryName> UmbrellaDir =380Module->getUmbrellaDirAsWritten()) {381// Add all of the headers we find in this subdirectory.382std::error_code EC;383SmallString<128> DirNative;384llvm::sys::path::native(UmbrellaDir->Entry.getName(), DirNative);385386llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();387SmallVector<std::pair<std::string, FileEntryRef>, 8> Headers;388for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;389Dir != End && !EC; Dir.increment(EC)) {390// Check whether this entry has an extension typically associated with391// headers.392if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))393.Cases(".h", ".H", ".hh", ".hpp", true)394.Default(false))395continue;396397auto Header = FileMgr.getOptionalFileRef(Dir->path());398// FIXME: This shouldn't happen unless there is a file system race. Is399// that worth diagnosing?400if (!Header)401continue;402403// If this header is marked 'unavailable' in this module, don't include404// it.405if (ModMap.isHeaderUnavailableInModule(*Header, Module))406continue;407408// Compute the relative path from the directory to this file.409SmallVector<StringRef, 16> Components;410auto PathIt = llvm::sys::path::rbegin(Dir->path());411for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)412Components.push_back(*PathIt);413SmallString<128> RelativeHeader(414UmbrellaDir->PathRelativeToRootModuleDirectory);415for (auto It = Components.rbegin(), End = Components.rend(); It != End;416++It)417llvm::sys::path::append(RelativeHeader, *It);418419std::string RelName = RelativeHeader.c_str();420Headers.push_back(std::make_pair(RelName, *Header));421}422423if (EC)424return EC;425426// Sort header paths and make the header inclusion order deterministic427// across different OSs and filesystems.428llvm::sort(Headers, llvm::less_first());429for (auto &H : Headers) {430// Include this header as part of the umbrella directory.431Module->addTopHeader(H.second);432addHeaderInclude(H.first, Includes, LangOpts, Module->IsExternC);433}434}435436// Recurse into submodules.437for (auto *Submodule : Module->submodules())438if (std::error_code Err = collectModuleHeaderIncludes(439LangOpts, FileMgr, Diag, ModMap, Submodule, Includes))440return Err;441442return std::error_code();443}444445static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,446bool IsPreprocessed,447std::string &PresumedModuleMapFile,448unsigned &Offset) {449auto &SrcMgr = CI.getSourceManager();450HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();451452// Map the current input to a file.453FileID ModuleMapID = SrcMgr.getMainFileID();454OptionalFileEntryRef ModuleMap = SrcMgr.getFileEntryRefForID(ModuleMapID);455assert(ModuleMap && "MainFileID without FileEntry");456457// If the module map is preprocessed, handle the initial line marker;458// line directives are not part of the module map syntax in general.459Offset = 0;460if (IsPreprocessed) {461SourceLocation EndOfLineMarker =462ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true);463if (EndOfLineMarker.isValid())464Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;465}466467// Load the module map file.468if (HS.loadModuleMapFile(*ModuleMap, IsSystem, ModuleMapID, &Offset,469PresumedModuleMapFile))470return true;471472if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset)473Offset = 0;474475// Infer framework module if possible.476if (HS.getModuleMap().canInferFrameworkModule(ModuleMap->getDir())) {477SmallString<128> InferredFrameworkPath = ModuleMap->getDir().getName();478llvm::sys::path::append(InferredFrameworkPath,479CI.getLangOpts().ModuleName + ".framework");480if (auto Dir =481CI.getFileManager().getOptionalDirectoryRef(InferredFrameworkPath))482(void)HS.getModuleMap().inferFrameworkModule(*Dir, IsSystem, nullptr);483}484485return false;486}487488static Module *prepareToBuildModule(CompilerInstance &CI,489StringRef ModuleMapFilename) {490if (CI.getLangOpts().CurrentModule.empty()) {491CI.getDiagnostics().Report(diag::err_missing_module_name);492493// FIXME: Eventually, we could consider asking whether there was just494// a single module described in the module map, and use that as a495// default. Then it would be fairly trivial to just "compile" a module496// map with a single module (the common case).497return nullptr;498}499500// Dig out the module definition.501HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();502Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, SourceLocation(),503/*AllowSearch=*/true);504if (!M) {505CI.getDiagnostics().Report(diag::err_missing_module)506<< CI.getLangOpts().CurrentModule << ModuleMapFilename;507508return nullptr;509}510511// Check whether we can build this module at all.512if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), *M,513CI.getDiagnostics()))514return nullptr;515516// Inform the preprocessor that includes from within the input buffer should517// be resolved relative to the build directory of the module map file.518CI.getPreprocessor().setMainFileDir(*M->Directory);519520// If the module was inferred from a different module map (via an expanded521// umbrella module definition), track that fact.522// FIXME: It would be preferable to fill this in as part of processing523// the module map, rather than adding it after the fact.524StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap;525if (!OriginalModuleMapName.empty()) {526auto OriginalModuleMap =527CI.getFileManager().getOptionalFileRef(OriginalModuleMapName,528/*openFile*/ true);529if (!OriginalModuleMap) {530CI.getDiagnostics().Report(diag::err_module_map_not_found)531<< OriginalModuleMapName;532return nullptr;533}534if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID(535CI.getSourceManager().getMainFileID())) {536M->IsInferred = true;537auto FileCharacter =538M->IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;539FileID OriginalModuleMapFID = CI.getSourceManager().getOrCreateFileID(540*OriginalModuleMap, FileCharacter);541CI.getPreprocessor()542.getHeaderSearchInfo()543.getModuleMap()544.setInferredModuleAllowedBy(M, OriginalModuleMapFID);545}546}547548// If we're being run from the command-line, the module build stack will not549// have been filled in yet, so complete it now in order to allow us to detect550// module cycles.551SourceManager &SourceMgr = CI.getSourceManager();552if (SourceMgr.getModuleBuildStack().empty())553SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,554FullSourceLoc(SourceLocation(), SourceMgr));555return M;556}557558/// Compute the input buffer that should be used to build the specified module.559static std::unique_ptr<llvm::MemoryBuffer>560getInputBufferForModule(CompilerInstance &CI, Module *M) {561FileManager &FileMgr = CI.getFileManager();562563// Collect the set of #includes we need to build the module.564SmallString<256> HeaderContents;565std::error_code Err = std::error_code();566if (std::optional<Module::Header> UmbrellaHeader =567M->getUmbrellaHeaderAsWritten())568addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,569HeaderContents, CI.getLangOpts(), M->IsExternC);570Err = collectModuleHeaderIncludes(571CI.getLangOpts(), FileMgr, CI.getDiagnostics(),572CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,573HeaderContents);574575if (Err) {576CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)577<< M->getFullModuleName() << Err.message();578return nullptr;579}580581return llvm::MemoryBuffer::getMemBufferCopy(582HeaderContents, Module::getModuleInputBufferName());583}584585bool FrontendAction::BeginSourceFile(CompilerInstance &CI,586const FrontendInputFile &RealInput) {587FrontendInputFile Input(RealInput);588assert(!Instance && "Already processing a source file!");589assert(!Input.isEmpty() && "Unexpected empty filename!");590setCurrentInput(Input);591setCompilerInstance(&CI);592593bool HasBegunSourceFile = false;594bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&595usesPreprocessorOnly();596597// If we fail, reset state since the client will not end up calling the598// matching EndSourceFile(). All paths that return true should release this.599auto FailureCleanup = llvm::make_scope_exit([&]() {600if (HasBegunSourceFile)601CI.getDiagnosticClient().EndSourceFile();602CI.setASTConsumer(nullptr);603CI.clearOutputFiles(/*EraseFiles=*/true);604CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);605setCurrentInput(FrontendInputFile());606setCompilerInstance(nullptr);607});608609if (!BeginInvocation(CI))610return false;611612// If we're replaying the build of an AST file, import it and set up613// the initial state from its build.614if (ReplayASTFile) {615IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());616617// The AST unit populates its own diagnostics engine rather than ours.618IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags(619new DiagnosticsEngine(Diags->getDiagnosticIDs(),620&Diags->getDiagnosticOptions()));621ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);622623// FIXME: What if the input is a memory buffer?624StringRef InputFile = Input.getFile();625626std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(627std::string(InputFile), CI.getPCHContainerReader(),628ASTUnit::LoadPreprocessorOnly, ASTDiags, CI.getFileSystemOpts(),629/*HeaderSearchOptions=*/nullptr);630if (!AST)631return false;632633// Options relating to how we treat the input (but not what we do with it)634// are inherited from the AST unit.635CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts();636CI.getPreprocessorOpts() = AST->getPreprocessorOpts();637CI.getLangOpts() = AST->getLangOpts();638639// Set the shared objects, these are reset when we finish processing the640// file, otherwise the CompilerInstance will happily destroy them.641CI.setFileManager(&AST->getFileManager());642CI.createSourceManager(CI.getFileManager());643CI.getSourceManager().initializeForReplay(AST->getSourceManager());644645// Preload all the module files loaded transitively by the AST unit. Also646// load all module map files that were parsed as part of building the AST647// unit.648if (auto ASTReader = AST->getASTReader()) {649auto &MM = ASTReader->getModuleManager();650auto &PrimaryModule = MM.getPrimaryModule();651652for (serialization::ModuleFile &MF : MM)653if (&MF != &PrimaryModule)654CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);655656ASTReader->visitTopLevelModuleMaps(PrimaryModule, [&](FileEntryRef FE) {657CI.getFrontendOpts().ModuleMapFiles.push_back(658std::string(FE.getName()));659});660}661662// Set up the input file for replay purposes.663auto Kind = AST->getInputKind();664if (Kind.getFormat() == InputKind::ModuleMap) {665Module *ASTModule =666AST->getPreprocessor().getHeaderSearchInfo().lookupModule(667AST->getLangOpts().CurrentModule, SourceLocation(),668/*AllowSearch*/ false);669assert(ASTModule && "module file does not define its own module");670Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);671} else {672auto &OldSM = AST->getSourceManager();673FileID ID = OldSM.getMainFileID();674if (auto File = OldSM.getFileEntryRefForID(ID))675Input = FrontendInputFile(File->getName(), Kind);676else677Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind);678}679setCurrentInput(Input, std::move(AST));680}681682// AST files follow a very different path, since they share objects via the683// AST unit.684if (Input.getKind().getFormat() == InputKind::Precompiled) {685assert(!usesPreprocessorOnly() && "this case was handled above");686assert(hasASTFileSupport() &&687"This action does not have AST file support!");688689IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());690691// FIXME: What if the input is a memory buffer?692StringRef InputFile = Input.getFile();693694std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(695std::string(InputFile), CI.getPCHContainerReader(),696ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts(),697CI.getHeaderSearchOptsPtr(), CI.getLangOptsPtr());698699if (!AST)700return false;701702// Inform the diagnostic client we are processing a source file.703CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);704HasBegunSourceFile = true;705706// Set the shared objects, these are reset when we finish processing the707// file, otherwise the CompilerInstance will happily destroy them.708CI.setFileManager(&AST->getFileManager());709CI.setSourceManager(&AST->getSourceManager());710CI.setPreprocessor(AST->getPreprocessorPtr());711Preprocessor &PP = CI.getPreprocessor();712PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),713PP.getLangOpts());714CI.setASTContext(&AST->getASTContext());715716setCurrentInput(Input, std::move(AST));717718// Initialize the action.719if (!BeginSourceFileAction(CI))720return false;721722// Create the AST consumer.723CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile));724if (!CI.hasASTConsumer())725return false;726727FailureCleanup.release();728return true;729}730731// Set up the file and source managers, if needed.732if (!CI.hasFileManager()) {733if (!CI.createFileManager()) {734return false;735}736}737if (!CI.hasSourceManager()) {738CI.createSourceManager(CI.getFileManager());739if (CI.getDiagnosticOpts().getFormat() == DiagnosticOptions::SARIF) {740static_cast<SARIFDiagnosticPrinter *>(&CI.getDiagnosticClient())741->setSarifWriter(742std::make_unique<SarifDocumentWriter>(CI.getSourceManager()));743}744}745746// Set up embedding for any specified files. Do this before we load any747// source files, including the primary module map for the compilation.748for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {749if (auto FE = CI.getFileManager().getOptionalFileRef(F, /*openFile*/true))750CI.getSourceManager().setFileIsTransient(*FE);751else752CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;753}754if (CI.getFrontendOpts().ModulesEmbedAllFiles)755CI.getSourceManager().setAllFilesAreTransient(true);756757// IR files bypass the rest of initialization.758if (Input.getKind().getLanguage() == Language::LLVM_IR) {759if (!hasIRSupport()) {760CI.getDiagnostics().Report(diag::err_ast_action_on_llvm_ir)761<< Input.getFile();762return false;763}764765// Inform the diagnostic client we are processing a source file.766CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);767HasBegunSourceFile = true;768769// Initialize the action.770if (!BeginSourceFileAction(CI))771return false;772773// Initialize the main file entry.774if (!CI.InitializeSourceManager(CurrentInput))775return false;776777FailureCleanup.release();778return true;779}780781// If the implicit PCH include is actually a directory, rather than782// a single file, search for a suitable PCH file in that directory.783if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {784FileManager &FileMgr = CI.getFileManager();785PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();786StringRef PCHInclude = PPOpts.ImplicitPCHInclude;787std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();788if (auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude)) {789std::error_code EC;790SmallString<128> DirNative;791llvm::sys::path::native(PCHDir->getName(), DirNative);792bool Found = false;793llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();794for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),795DirEnd;796Dir != DirEnd && !EC; Dir.increment(EC)) {797// Check whether this is an acceptable AST file.798if (ASTReader::isAcceptableASTFile(799Dir->path(), FileMgr, CI.getModuleCache(),800CI.getPCHContainerReader(), CI.getLangOpts(),801CI.getTargetOpts(), CI.getPreprocessorOpts(),802SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) {803PPOpts.ImplicitPCHInclude = std::string(Dir->path());804Found = true;805break;806}807}808809if (!Found) {810CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;811return false;812}813}814}815816// Set up the preprocessor if needed. When parsing model files the817// preprocessor of the original source is reused.818if (!isModelParsingAction())819CI.createPreprocessor(getTranslationUnitKind());820821// Inform the diagnostic client we are processing a source file.822CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),823&CI.getPreprocessor());824HasBegunSourceFile = true;825826// Handle C++20 header units.827// Here, the user has the option to specify that the header name should be828// looked up in the pre-processor search paths (and the main filename as829// passed by the driver might therefore be incomplete until that look-up).830if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&831!Input.getKind().isPreprocessed()) {832StringRef FileName = Input.getFile();833InputKind Kind = Input.getKind();834if (Kind.getHeaderUnitKind() != InputKind::HeaderUnit_Abs) {835assert(CI.hasPreprocessor() &&836"trying to build a header unit without a Pre-processor?");837HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();838// Relative searches begin from CWD.839auto Dir = CI.getFileManager().getOptionalDirectoryRef(".");840SmallVector<std::pair<OptionalFileEntryRef, DirectoryEntryRef>, 1> CWD;841CWD.push_back({std::nullopt, *Dir});842OptionalFileEntryRef FE =843HS.LookupFile(FileName, SourceLocation(),844/*Angled*/ Input.getKind().getHeaderUnitKind() ==845InputKind::HeaderUnit_System,846nullptr, nullptr, CWD, nullptr, nullptr, nullptr,847nullptr, nullptr, nullptr);848if (!FE) {849CI.getDiagnostics().Report(diag::err_module_header_file_not_found)850<< FileName;851return false;852}853// We now have the filename...854FileName = FE->getName();855// ... still a header unit, but now use the path as written.856Kind = Input.getKind().withHeaderUnit(InputKind::HeaderUnit_Abs);857Input = FrontendInputFile(FileName, Kind, Input.isSystem());858}859// Unless the user has overridden the name, the header unit module name is860// the pathname for the file.861if (CI.getLangOpts().ModuleName.empty())862CI.getLangOpts().ModuleName = std::string(FileName);863CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;864}865866if (!CI.InitializeSourceManager(Input))867return false;868869if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&870Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {871// We have an input filename like foo.iih, but we want to find the right872// module name (and original file, to build the map entry).873// Check if the first line specifies the original source file name with a874// linemarker.875std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());876ReadOriginalFileName(CI, PresumedInputFile);877// Unless the user overrides this, the module name is the name by which the878// original file was known.879if (CI.getLangOpts().ModuleName.empty())880CI.getLangOpts().ModuleName = std::string(PresumedInputFile);881CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;882}883884// For module map files, we first parse the module map and synthesize a885// "<module-includes>" buffer before more conventional processing.886if (Input.getKind().getFormat() == InputKind::ModuleMap) {887CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);888889std::string PresumedModuleMapFile;890unsigned OffsetToContents;891if (loadModuleMapForModuleBuild(CI, Input.isSystem(),892Input.isPreprocessed(),893PresumedModuleMapFile, OffsetToContents))894return false;895896auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());897if (!CurrentModule)898return false;899900CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile;901902if (OffsetToContents)903// If the module contents are in the same file, skip to them.904CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);905else {906// Otherwise, convert the module description to a suitable input buffer.907auto Buffer = getInputBufferForModule(CI, CurrentModule);908if (!Buffer)909return false;910911// Reinitialize the main file entry to refer to the new input.912auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User;913auto &SourceMgr = CI.getSourceManager();914auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind);915assert(BufferID.isValid() && "couldn't create module buffer ID");916SourceMgr.setMainFileID(BufferID);917}918}919920// Initialize the action.921if (!BeginSourceFileAction(CI))922return false;923924// If we were asked to load any module map files, do so now.925for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {926if (auto File = CI.getFileManager().getOptionalFileRef(Filename))927CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile(928*File, /*IsSystem*/false);929else930CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;931}932933// If compiling implementation of a module, load its module map file now.934(void)CI.getPreprocessor().getCurrentModuleImplementation();935936// Add a module declaration scope so that modules from -fmodule-map-file937// arguments may shadow modules found implicitly in search paths.938CI.getPreprocessor()939.getHeaderSearchInfo()940.getModuleMap()941.finishModuleDeclarationScope();942943// Create the AST context and consumer unless this is a preprocessor only944// action.945if (!usesPreprocessorOnly()) {946// Parsing a model file should reuse the existing ASTContext.947if (!isModelParsingAction())948CI.createASTContext();949950// For preprocessed files, check if the first line specifies the original951// source file name with a linemarker.952std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());953if (Input.isPreprocessed())954ReadOriginalFileName(CI, PresumedInputFile);955956std::unique_ptr<ASTConsumer> Consumer =957CreateWrappedASTConsumer(CI, PresumedInputFile);958if (!Consumer)959return false;960961// FIXME: should not overwrite ASTMutationListener when parsing model files?962if (!isModelParsingAction())963CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());964965if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {966// Convert headers to PCH and chain them.967IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;968source = createChainedIncludesSource(CI, FinalReader);969if (!source)970return false;971CI.setASTReader(static_cast<ASTReader *>(FinalReader.get()));972CI.getASTContext().setExternalSource(source);973} else if (CI.getLangOpts().Modules ||974!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {975// Use PCM or PCH.976assert(hasPCHSupport() && "This action does not have PCH support!");977ASTDeserializationListener *DeserialListener =978Consumer->GetASTDeserializationListener();979bool DeleteDeserialListener = false;980if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) {981DeserialListener = new DeserializedDeclsDumper(DeserialListener,982DeleteDeserialListener);983DeleteDeserialListener = true;984}985if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) {986DeserialListener = new DeserializedDeclsChecker(987CI.getASTContext(),988CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,989DeserialListener, DeleteDeserialListener);990DeleteDeserialListener = true;991}992if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {993CI.createPCHExternalASTSource(994CI.getPreprocessorOpts().ImplicitPCHInclude,995CI.getPreprocessorOpts().DisablePCHOrModuleValidation,996CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,997DeserialListener, DeleteDeserialListener);998if (!CI.getASTContext().getExternalSource())999return false;1000}1001// If modules are enabled, create the AST reader before creating1002// any builtins, so that all declarations know that they might be1003// extended by an external source.1004if (CI.getLangOpts().Modules || !CI.hasASTContext() ||1005!CI.getASTContext().getExternalSource()) {1006CI.createASTReader();1007CI.getASTReader()->setDeserializationListener(DeserialListener,1008DeleteDeserialListener);1009}1010}10111012CI.setASTConsumer(std::move(Consumer));1013if (!CI.hasASTConsumer())1014return false;1015}10161017// Initialize built-in info as long as we aren't using an external AST1018// source.1019if (CI.getLangOpts().Modules || !CI.hasASTContext() ||1020!CI.getASTContext().getExternalSource()) {1021Preprocessor &PP = CI.getPreprocessor();1022PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),1023PP.getLangOpts());1024} else {1025// FIXME: If this is a problem, recover from it by creating a multiplex1026// source.1027assert((!CI.getLangOpts().Modules || CI.getASTReader()) &&1028"modules enabled but created an external source that "1029"doesn't support modules");1030}10311032// If we were asked to load any module files, do so now.1033for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) {1034serialization::ModuleFile *Loaded = nullptr;1035if (!CI.loadModuleFile(ModuleFile, Loaded))1036return false;10371038if (Loaded && Loaded->StandardCXXModule)1039CI.getDiagnostics().Report(1040diag::warn_eagerly_load_for_standard_cplusplus_modules);1041}10421043// If there is a layout overrides file, attach an external AST source that1044// provides the layouts from that file.1045if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&1046CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {1047IntrusiveRefCntPtr<ExternalASTSource>1048Override(new LayoutOverrideSource(1049CI.getFrontendOpts().OverrideRecordLayoutsFile));1050CI.getASTContext().setExternalSource(Override);1051}10521053// Setup HLSL External Sema Source1054if (CI.getLangOpts().HLSL && CI.hasASTContext()) {1055IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema(1056new HLSLExternalSemaSource());1057if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>(1058CI.getASTContext().getExternalSource())) {1059IntrusiveRefCntPtr<ExternalSemaSource> MultiSema(1060new MultiplexExternalSemaSource(SemaSource, HLSLSema.get()));1061CI.getASTContext().setExternalSource(MultiSema);1062} else1063CI.getASTContext().setExternalSource(HLSLSema);1064}10651066FailureCleanup.release();1067return true;1068}10691070llvm::Error FrontendAction::Execute() {1071CompilerInstance &CI = getCompilerInstance();10721073if (CI.hasFrontendTimer()) {1074llvm::TimeRegion Timer(CI.getFrontendTimer());1075ExecuteAction();1076}1077else ExecuteAction();10781079// If we are supposed to rebuild the global module index, do so now unless1080// there were any module-build failures.1081if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&1082CI.hasPreprocessor()) {1083StringRef Cache =1084CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath();1085if (!Cache.empty()) {1086if (llvm::Error Err = GlobalModuleIndex::writeIndex(1087CI.getFileManager(), CI.getPCHContainerReader(), Cache)) {1088// FIXME this drops the error on the floor, but1089// Index/pch-from-libclang.c seems to rely on dropping at least some of1090// the error conditions!1091consumeError(std::move(Err));1092}1093}1094}10951096return llvm::Error::success();1097}10981099void FrontendAction::EndSourceFile() {1100CompilerInstance &CI = getCompilerInstance();11011102// Inform the diagnostic client we are done with this source file.1103CI.getDiagnosticClient().EndSourceFile();11041105// Inform the preprocessor we are done.1106if (CI.hasPreprocessor())1107CI.getPreprocessor().EndSourceFile();11081109// Finalize the action.1110EndSourceFileAction();11111112// Sema references the ast consumer, so reset sema first.1113//1114// FIXME: There is more per-file stuff we could just drop here?1115bool DisableFree = CI.getFrontendOpts().DisableFree;1116if (DisableFree) {1117CI.resetAndLeakSema();1118CI.resetAndLeakASTContext();1119llvm::BuryPointer(CI.takeASTConsumer().get());1120} else {1121CI.setSema(nullptr);1122CI.setASTContext(nullptr);1123CI.setASTConsumer(nullptr);1124}11251126if (CI.getFrontendOpts().ShowStats) {1127llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFileOrBufferName() << "':\n";1128CI.getPreprocessor().PrintStats();1129CI.getPreprocessor().getIdentifierTable().PrintStats();1130CI.getPreprocessor().getHeaderSearchInfo().PrintStats();1131CI.getSourceManager().PrintStats();1132llvm::errs() << "\n";1133}11341135// Cleanup the output streams, and erase the output files if instructed by the1136// FrontendAction.1137CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());11381139// The resources are owned by AST when the current file is AST.1140// So we reset the resources here to avoid users accessing it1141// accidently.1142if (isCurrentFileAST()) {1143if (DisableFree) {1144CI.resetAndLeakPreprocessor();1145CI.resetAndLeakSourceManager();1146CI.resetAndLeakFileManager();1147llvm::BuryPointer(std::move(CurrentASTUnit));1148} else {1149CI.setPreprocessor(nullptr);1150CI.setSourceManager(nullptr);1151CI.setFileManager(nullptr);1152}1153}11541155setCompilerInstance(nullptr);1156setCurrentInput(FrontendInputFile());1157CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);1158}11591160bool FrontendAction::shouldEraseOutputFiles() {1161return getCompilerInstance().getDiagnostics().hasErrorOccurred();1162}11631164//===----------------------------------------------------------------------===//1165// Utility Actions1166//===----------------------------------------------------------------------===//11671168void ASTFrontendAction::ExecuteAction() {1169CompilerInstance &CI = getCompilerInstance();1170if (!CI.hasPreprocessor())1171return;1172// This is a fallback: If the client forgets to invoke this, we mark the1173// current stack as the bottom. Though not optimal, this could help prevent1174// stack overflow during deep recursion.1175clang::noteBottomOfStack();11761177// FIXME: Move the truncation aspect of this into Sema, we delayed this till1178// here so the source manager would be initialized.1179if (hasCodeCompletionSupport() &&1180!CI.getFrontendOpts().CodeCompletionAt.FileName.empty())1181CI.createCodeCompletionConsumer();11821183// Use a code completion consumer?1184CodeCompleteConsumer *CompletionConsumer = nullptr;1185if (CI.hasCodeCompletionConsumer())1186CompletionConsumer = &CI.getCodeCompletionConsumer();11871188if (!CI.hasSema())1189CI.createSema(getTranslationUnitKind(), CompletionConsumer);11901191ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,1192CI.getFrontendOpts().SkipFunctionBodies);1193}11941195void PluginASTAction::anchor() { }11961197std::unique_ptr<ASTConsumer>1198PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,1199StringRef InFile) {1200llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");1201}12021203bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) {1204return WrappedAction->PrepareToExecuteAction(CI);1205}1206std::unique_ptr<ASTConsumer>1207WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,1208StringRef InFile) {1209return WrappedAction->CreateASTConsumer(CI, InFile);1210}1211bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {1212return WrappedAction->BeginInvocation(CI);1213}1214bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) {1215WrappedAction->setCurrentInput(getCurrentInput());1216WrappedAction->setCompilerInstance(&CI);1217auto Ret = WrappedAction->BeginSourceFileAction(CI);1218// BeginSourceFileAction may change CurrentInput, e.g. during module builds.1219setCurrentInput(WrappedAction->getCurrentInput());1220return Ret;1221}1222void WrapperFrontendAction::ExecuteAction() {1223WrappedAction->ExecuteAction();1224}1225void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); }1226void WrapperFrontendAction::EndSourceFileAction() {1227WrappedAction->EndSourceFileAction();1228}1229bool WrapperFrontendAction::shouldEraseOutputFiles() {1230return WrappedAction->shouldEraseOutputFiles();1231}12321233bool WrapperFrontendAction::usesPreprocessorOnly() const {1234return WrappedAction->usesPreprocessorOnly();1235}1236TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {1237return WrappedAction->getTranslationUnitKind();1238}1239bool WrapperFrontendAction::hasPCHSupport() const {1240return WrappedAction->hasPCHSupport();1241}1242bool WrapperFrontendAction::hasASTFileSupport() const {1243return WrappedAction->hasASTFileSupport();1244}1245bool WrapperFrontendAction::hasIRSupport() const {1246return WrappedAction->hasIRSupport();1247}1248bool WrapperFrontendAction::hasCodeCompletionSupport() const {1249return WrappedAction->hasCodeCompletionSupport();1250}12511252WrapperFrontendAction::WrapperFrontendAction(1253std::unique_ptr<FrontendAction> WrappedAction)1254: WrappedAction(std::move(WrappedAction)) {}125512561257