17330f729Sjoerg //===--- FrontendAction.cpp -----------------------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "clang/Frontend/FrontendAction.h"
107330f729Sjoerg #include "clang/AST/ASTConsumer.h"
117330f729Sjoerg #include "clang/AST/ASTContext.h"
127330f729Sjoerg #include "clang/AST/DeclGroup.h"
13*e038c9c4Sjoerg #include "clang/Basic/Builtins.h"
147330f729Sjoerg #include "clang/Basic/LangStandard.h"
157330f729Sjoerg #include "clang/Frontend/ASTUnit.h"
167330f729Sjoerg #include "clang/Frontend/CompilerInstance.h"
177330f729Sjoerg #include "clang/Frontend/FrontendDiagnostic.h"
187330f729Sjoerg #include "clang/Frontend/FrontendPluginRegistry.h"
197330f729Sjoerg #include "clang/Frontend/LayoutOverrideSource.h"
207330f729Sjoerg #include "clang/Frontend/MultiplexConsumer.h"
217330f729Sjoerg #include "clang/Frontend/Utils.h"
227330f729Sjoerg #include "clang/Lex/HeaderSearch.h"
237330f729Sjoerg #include "clang/Lex/LiteralSupport.h"
247330f729Sjoerg #include "clang/Lex/Preprocessor.h"
257330f729Sjoerg #include "clang/Lex/PreprocessorOptions.h"
267330f729Sjoerg #include "clang/Parse/ParseAST.h"
277330f729Sjoerg #include "clang/Serialization/ASTDeserializationListener.h"
287330f729Sjoerg #include "clang/Serialization/ASTReader.h"
297330f729Sjoerg #include "clang/Serialization/GlobalModuleIndex.h"
307330f729Sjoerg #include "llvm/Support/BuryPointer.h"
317330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
327330f729Sjoerg #include "llvm/Support/FileSystem.h"
337330f729Sjoerg #include "llvm/Support/Path.h"
347330f729Sjoerg #include "llvm/Support/Timer.h"
357330f729Sjoerg #include "llvm/Support/raw_ostream.h"
367330f729Sjoerg #include <system_error>
377330f729Sjoerg using namespace clang;
387330f729Sjoerg
397330f729Sjoerg LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)
407330f729Sjoerg
417330f729Sjoerg namespace {
427330f729Sjoerg
437330f729Sjoerg class DelegatingDeserializationListener : public ASTDeserializationListener {
447330f729Sjoerg ASTDeserializationListener *Previous;
457330f729Sjoerg bool DeletePrevious;
467330f729Sjoerg
477330f729Sjoerg public:
DelegatingDeserializationListener(ASTDeserializationListener * Previous,bool DeletePrevious)487330f729Sjoerg explicit DelegatingDeserializationListener(
497330f729Sjoerg ASTDeserializationListener *Previous, bool DeletePrevious)
507330f729Sjoerg : Previous(Previous), DeletePrevious(DeletePrevious) {}
~DelegatingDeserializationListener()517330f729Sjoerg ~DelegatingDeserializationListener() override {
527330f729Sjoerg if (DeletePrevious)
537330f729Sjoerg delete Previous;
547330f729Sjoerg }
557330f729Sjoerg
ReaderInitialized(ASTReader * Reader)567330f729Sjoerg void ReaderInitialized(ASTReader *Reader) override {
577330f729Sjoerg if (Previous)
587330f729Sjoerg Previous->ReaderInitialized(Reader);
597330f729Sjoerg }
IdentifierRead(serialization::IdentID ID,IdentifierInfo * II)607330f729Sjoerg void IdentifierRead(serialization::IdentID ID,
617330f729Sjoerg IdentifierInfo *II) override {
627330f729Sjoerg if (Previous)
637330f729Sjoerg Previous->IdentifierRead(ID, II);
647330f729Sjoerg }
TypeRead(serialization::TypeIdx Idx,QualType T)657330f729Sjoerg void TypeRead(serialization::TypeIdx Idx, QualType T) override {
667330f729Sjoerg if (Previous)
677330f729Sjoerg Previous->TypeRead(Idx, T);
687330f729Sjoerg }
DeclRead(serialization::DeclID ID,const Decl * D)697330f729Sjoerg void DeclRead(serialization::DeclID ID, const Decl *D) override {
707330f729Sjoerg if (Previous)
717330f729Sjoerg Previous->DeclRead(ID, D);
727330f729Sjoerg }
SelectorRead(serialization::SelectorID ID,Selector Sel)737330f729Sjoerg void SelectorRead(serialization::SelectorID ID, Selector Sel) override {
747330f729Sjoerg if (Previous)
757330f729Sjoerg Previous->SelectorRead(ID, Sel);
767330f729Sjoerg }
MacroDefinitionRead(serialization::PreprocessedEntityID PPID,MacroDefinitionRecord * MD)777330f729Sjoerg void MacroDefinitionRead(serialization::PreprocessedEntityID PPID,
787330f729Sjoerg MacroDefinitionRecord *MD) override {
797330f729Sjoerg if (Previous)
807330f729Sjoerg Previous->MacroDefinitionRead(PPID, MD);
817330f729Sjoerg }
827330f729Sjoerg };
837330f729Sjoerg
847330f729Sjoerg /// Dumps deserialized declarations.
857330f729Sjoerg class DeserializedDeclsDumper : public DelegatingDeserializationListener {
867330f729Sjoerg public:
DeserializedDeclsDumper(ASTDeserializationListener * Previous,bool DeletePrevious)877330f729Sjoerg explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,
887330f729Sjoerg bool DeletePrevious)
897330f729Sjoerg : DelegatingDeserializationListener(Previous, DeletePrevious) {}
907330f729Sjoerg
DeclRead(serialization::DeclID ID,const Decl * D)917330f729Sjoerg void DeclRead(serialization::DeclID ID, const Decl *D) override {
927330f729Sjoerg llvm::outs() << "PCH DECL: " << D->getDeclKindName();
937330f729Sjoerg if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
947330f729Sjoerg llvm::outs() << " - ";
957330f729Sjoerg ND->printQualifiedName(llvm::outs());
967330f729Sjoerg }
977330f729Sjoerg llvm::outs() << "\n";
987330f729Sjoerg
997330f729Sjoerg DelegatingDeserializationListener::DeclRead(ID, D);
1007330f729Sjoerg }
1017330f729Sjoerg };
1027330f729Sjoerg
1037330f729Sjoerg /// Checks deserialized declarations and emits error if a name
1047330f729Sjoerg /// matches one given in command-line using -error-on-deserialized-decl.
1057330f729Sjoerg class DeserializedDeclsChecker : public DelegatingDeserializationListener {
1067330f729Sjoerg ASTContext &Ctx;
1077330f729Sjoerg std::set<std::string> NamesToCheck;
1087330f729Sjoerg
1097330f729Sjoerg public:
DeserializedDeclsChecker(ASTContext & Ctx,const std::set<std::string> & NamesToCheck,ASTDeserializationListener * Previous,bool DeletePrevious)1107330f729Sjoerg DeserializedDeclsChecker(ASTContext &Ctx,
1117330f729Sjoerg const std::set<std::string> &NamesToCheck,
1127330f729Sjoerg ASTDeserializationListener *Previous,
1137330f729Sjoerg bool DeletePrevious)
1147330f729Sjoerg : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx),
1157330f729Sjoerg NamesToCheck(NamesToCheck) {}
1167330f729Sjoerg
DeclRead(serialization::DeclID ID,const Decl * D)1177330f729Sjoerg void DeclRead(serialization::DeclID ID, const Decl *D) override {
1187330f729Sjoerg if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
1197330f729Sjoerg if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
1207330f729Sjoerg unsigned DiagID
1217330f729Sjoerg = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,
1227330f729Sjoerg "%0 was deserialized");
1237330f729Sjoerg Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
124*e038c9c4Sjoerg << ND;
1257330f729Sjoerg }
1267330f729Sjoerg
1277330f729Sjoerg DelegatingDeserializationListener::DeclRead(ID, D);
1287330f729Sjoerg }
1297330f729Sjoerg };
1307330f729Sjoerg
1317330f729Sjoerg } // end anonymous namespace
1327330f729Sjoerg
FrontendAction()1337330f729Sjoerg FrontendAction::FrontendAction() : Instance(nullptr) {}
1347330f729Sjoerg
~FrontendAction()1357330f729Sjoerg FrontendAction::~FrontendAction() {}
1367330f729Sjoerg
setCurrentInput(const FrontendInputFile & CurrentInput,std::unique_ptr<ASTUnit> AST)1377330f729Sjoerg void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
1387330f729Sjoerg std::unique_ptr<ASTUnit> AST) {
1397330f729Sjoerg this->CurrentInput = CurrentInput;
1407330f729Sjoerg CurrentASTUnit = std::move(AST);
1417330f729Sjoerg }
1427330f729Sjoerg
getCurrentModule() const1437330f729Sjoerg Module *FrontendAction::getCurrentModule() const {
1447330f729Sjoerg CompilerInstance &CI = getCompilerInstance();
1457330f729Sjoerg return CI.getPreprocessor().getHeaderSearchInfo().lookupModule(
1467330f729Sjoerg CI.getLangOpts().CurrentModule, /*AllowSearch*/false);
1477330f729Sjoerg }
1487330f729Sjoerg
1497330f729Sjoerg std::unique_ptr<ASTConsumer>
CreateWrappedASTConsumer(CompilerInstance & CI,StringRef InFile)1507330f729Sjoerg FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
1517330f729Sjoerg StringRef InFile) {
1527330f729Sjoerg std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile);
1537330f729Sjoerg if (!Consumer)
1547330f729Sjoerg return nullptr;
1557330f729Sjoerg
1567330f729Sjoerg // Validate -add-plugin args.
1577330f729Sjoerg bool FoundAllPlugins = true;
1587330f729Sjoerg for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) {
1597330f729Sjoerg bool Found = false;
160*e038c9c4Sjoerg for (const FrontendPluginRegistry::entry &Plugin :
161*e038c9c4Sjoerg FrontendPluginRegistry::entries()) {
162*e038c9c4Sjoerg if (Plugin.getName() == Arg)
1637330f729Sjoerg Found = true;
1647330f729Sjoerg }
1657330f729Sjoerg if (!Found) {
1667330f729Sjoerg CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg;
1677330f729Sjoerg FoundAllPlugins = false;
1687330f729Sjoerg }
1697330f729Sjoerg }
1707330f729Sjoerg if (!FoundAllPlugins)
1717330f729Sjoerg return nullptr;
1727330f729Sjoerg
1737330f729Sjoerg // If there are no registered plugins we don't need to wrap the consumer
1747330f729Sjoerg if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end())
1757330f729Sjoerg return Consumer;
1767330f729Sjoerg
1777330f729Sjoerg // If this is a code completion run, avoid invoking the plugin consumers
1787330f729Sjoerg if (CI.hasCodeCompletionConsumer())
1797330f729Sjoerg return Consumer;
1807330f729Sjoerg
1817330f729Sjoerg // Collect the list of plugins that go before the main action (in Consumers)
1827330f729Sjoerg // or after it (in AfterConsumers)
1837330f729Sjoerg std::vector<std::unique_ptr<ASTConsumer>> Consumers;
1847330f729Sjoerg std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers;
185*e038c9c4Sjoerg for (const FrontendPluginRegistry::entry &Plugin :
186*e038c9c4Sjoerg FrontendPluginRegistry::entries()) {
187*e038c9c4Sjoerg std::unique_ptr<PluginASTAction> P = Plugin.instantiate();
1887330f729Sjoerg PluginASTAction::ActionType ActionType = P->getActionType();
1897330f729Sjoerg if (ActionType == PluginASTAction::Cmdline) {
1907330f729Sjoerg // This is O(|plugins| * |add_plugins|), but since both numbers are
1917330f729Sjoerg // way below 50 in practice, that's ok.
192*e038c9c4Sjoerg if (llvm::any_of(CI.getFrontendOpts().AddPluginActions,
193*e038c9c4Sjoerg [&](const std::string &PluginAction) {
194*e038c9c4Sjoerg return PluginAction == Plugin.getName();
195*e038c9c4Sjoerg }))
1967330f729Sjoerg ActionType = PluginASTAction::AddAfterMainAction;
1977330f729Sjoerg }
1987330f729Sjoerg if ((ActionType == PluginASTAction::AddBeforeMainAction ||
1997330f729Sjoerg ActionType == PluginASTAction::AddAfterMainAction) &&
200*e038c9c4Sjoerg P->ParseArgs(
201*e038c9c4Sjoerg CI,
202*e038c9c4Sjoerg CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) {
2037330f729Sjoerg std::unique_ptr<ASTConsumer> PluginConsumer = P->CreateASTConsumer(CI, InFile);
2047330f729Sjoerg if (ActionType == PluginASTAction::AddBeforeMainAction) {
2057330f729Sjoerg Consumers.push_back(std::move(PluginConsumer));
2067330f729Sjoerg } else {
2077330f729Sjoerg AfterConsumers.push_back(std::move(PluginConsumer));
2087330f729Sjoerg }
2097330f729Sjoerg }
2107330f729Sjoerg }
2117330f729Sjoerg
2127330f729Sjoerg // Add to Consumers the main consumer, then all the plugins that go after it
2137330f729Sjoerg Consumers.push_back(std::move(Consumer));
2147330f729Sjoerg for (auto &C : AfterConsumers) {
2157330f729Sjoerg Consumers.push_back(std::move(C));
2167330f729Sjoerg }
2177330f729Sjoerg
2187330f729Sjoerg return std::make_unique<MultiplexConsumer>(std::move(Consumers));
2197330f729Sjoerg }
2207330f729Sjoerg
2217330f729Sjoerg /// For preprocessed files, if the first line is the linemarker and specifies
2227330f729Sjoerg /// the original source file name, use that name as the input file name.
2237330f729Sjoerg /// Returns the location of the first token after the line marker directive.
2247330f729Sjoerg ///
2257330f729Sjoerg /// \param CI The compiler instance.
2267330f729Sjoerg /// \param InputFile Populated with the filename from the line marker.
2277330f729Sjoerg /// \param IsModuleMap If \c true, add a line note corresponding to this line
2287330f729Sjoerg /// directive. (We need to do this because the directive will not be
2297330f729Sjoerg /// visited by the preprocessor.)
ReadOriginalFileName(CompilerInstance & CI,std::string & InputFile,bool IsModuleMap=false)2307330f729Sjoerg static SourceLocation ReadOriginalFileName(CompilerInstance &CI,
2317330f729Sjoerg std::string &InputFile,
2327330f729Sjoerg bool IsModuleMap = false) {
2337330f729Sjoerg auto &SourceMgr = CI.getSourceManager();
2347330f729Sjoerg auto MainFileID = SourceMgr.getMainFileID();
2357330f729Sjoerg
236*e038c9c4Sjoerg auto MainFileBuf = SourceMgr.getBufferOrNone(MainFileID);
237*e038c9c4Sjoerg if (!MainFileBuf)
2387330f729Sjoerg return SourceLocation();
2397330f729Sjoerg
2407330f729Sjoerg std::unique_ptr<Lexer> RawLexer(
241*e038c9c4Sjoerg new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts()));
2427330f729Sjoerg
2437330f729Sjoerg // If the first line has the syntax of
2447330f729Sjoerg //
2457330f729Sjoerg // # NUM "FILENAME"
2467330f729Sjoerg //
2477330f729Sjoerg // we use FILENAME as the input file name.
2487330f729Sjoerg Token T;
2497330f729Sjoerg if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash)
2507330f729Sjoerg return SourceLocation();
2517330f729Sjoerg if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() ||
2527330f729Sjoerg T.getKind() != tok::numeric_constant)
2537330f729Sjoerg return SourceLocation();
2547330f729Sjoerg
2557330f729Sjoerg unsigned LineNo;
2567330f729Sjoerg SourceLocation LineNoLoc = T.getLocation();
2577330f729Sjoerg if (IsModuleMap) {
2587330f729Sjoerg llvm::SmallString<16> Buffer;
2597330f729Sjoerg if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts())
2607330f729Sjoerg .getAsInteger(10, LineNo))
2617330f729Sjoerg return SourceLocation();
2627330f729Sjoerg }
2637330f729Sjoerg
2647330f729Sjoerg RawLexer->LexFromRawLexer(T);
2657330f729Sjoerg if (T.isAtStartOfLine() || T.getKind() != tok::string_literal)
2667330f729Sjoerg return SourceLocation();
2677330f729Sjoerg
2687330f729Sjoerg StringLiteralParser Literal(T, CI.getPreprocessor());
2697330f729Sjoerg if (Literal.hadError)
2707330f729Sjoerg return SourceLocation();
2717330f729Sjoerg RawLexer->LexFromRawLexer(T);
2727330f729Sjoerg if (T.isNot(tok::eof) && !T.isAtStartOfLine())
2737330f729Sjoerg return SourceLocation();
2747330f729Sjoerg InputFile = Literal.GetString().str();
2757330f729Sjoerg
2767330f729Sjoerg if (IsModuleMap)
2777330f729Sjoerg CI.getSourceManager().AddLineNote(
2787330f729Sjoerg LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false,
2797330f729Sjoerg false, SrcMgr::C_User_ModuleMap);
2807330f729Sjoerg
2817330f729Sjoerg return T.getLocation();
2827330f729Sjoerg }
2837330f729Sjoerg
2847330f729Sjoerg static SmallVectorImpl<char> &
operator +=(SmallVectorImpl<char> & Includes,StringRef RHS)2857330f729Sjoerg operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
2867330f729Sjoerg Includes.append(RHS.begin(), RHS.end());
2877330f729Sjoerg return Includes;
2887330f729Sjoerg }
2897330f729Sjoerg
addHeaderInclude(StringRef HeaderName,SmallVectorImpl<char> & Includes,const LangOptions & LangOpts,bool IsExternC)2907330f729Sjoerg static void addHeaderInclude(StringRef HeaderName,
2917330f729Sjoerg SmallVectorImpl<char> &Includes,
2927330f729Sjoerg const LangOptions &LangOpts,
2937330f729Sjoerg bool IsExternC) {
2947330f729Sjoerg if (IsExternC && LangOpts.CPlusPlus)
2957330f729Sjoerg Includes += "extern \"C\" {\n";
2967330f729Sjoerg if (LangOpts.ObjC)
2977330f729Sjoerg Includes += "#import \"";
2987330f729Sjoerg else
2997330f729Sjoerg Includes += "#include \"";
3007330f729Sjoerg
3017330f729Sjoerg Includes += HeaderName;
3027330f729Sjoerg
3037330f729Sjoerg Includes += "\"\n";
3047330f729Sjoerg if (IsExternC && LangOpts.CPlusPlus)
3057330f729Sjoerg Includes += "}\n";
3067330f729Sjoerg }
3077330f729Sjoerg
3087330f729Sjoerg /// Collect the set of header includes needed to construct the given
3097330f729Sjoerg /// module and update the TopHeaders file set of the module.
3107330f729Sjoerg ///
3117330f729Sjoerg /// \param Module The module we're collecting includes from.
3127330f729Sjoerg ///
3137330f729Sjoerg /// \param Includes Will be augmented with the set of \#includes or \#imports
3147330f729Sjoerg /// needed to load all of the named headers.
collectModuleHeaderIncludes(const LangOptions & LangOpts,FileManager & FileMgr,DiagnosticsEngine & Diag,ModuleMap & ModMap,clang::Module * Module,SmallVectorImpl<char> & Includes)3157330f729Sjoerg static std::error_code collectModuleHeaderIncludes(
3167330f729Sjoerg const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag,
3177330f729Sjoerg ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) {
3187330f729Sjoerg // Don't collect any headers for unavailable modules.
3197330f729Sjoerg if (!Module->isAvailable())
3207330f729Sjoerg return std::error_code();
3217330f729Sjoerg
3227330f729Sjoerg // Resolve all lazy header directives to header files.
3237330f729Sjoerg ModMap.resolveHeaderDirectives(Module);
3247330f729Sjoerg
3257330f729Sjoerg // If any headers are missing, we can't build this module. In most cases,
3267330f729Sjoerg // diagnostics for this should have already been produced; we only get here
3277330f729Sjoerg // if explicit stat information was provided.
3287330f729Sjoerg // FIXME: If the name resolves to a file with different stat information,
3297330f729Sjoerg // produce a better diagnostic.
3307330f729Sjoerg if (!Module->MissingHeaders.empty()) {
3317330f729Sjoerg auto &MissingHeader = Module->MissingHeaders.front();
3327330f729Sjoerg Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
3337330f729Sjoerg << MissingHeader.IsUmbrella << MissingHeader.FileName;
3347330f729Sjoerg return std::error_code();
3357330f729Sjoerg }
3367330f729Sjoerg
3377330f729Sjoerg // Add includes for each of these headers.
3387330f729Sjoerg for (auto HK : {Module::HK_Normal, Module::HK_Private}) {
3397330f729Sjoerg for (Module::Header &H : Module->Headers[HK]) {
3407330f729Sjoerg Module->addTopHeader(H.Entry);
3417330f729Sjoerg // Use the path as specified in the module map file. We'll look for this
3427330f729Sjoerg // file relative to the module build directory (the directory containing
3437330f729Sjoerg // the module map file) so this will find the same file that we found
3447330f729Sjoerg // while parsing the module map.
345*e038c9c4Sjoerg addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,
346*e038c9c4Sjoerg Module->IsExternC);
3477330f729Sjoerg }
3487330f729Sjoerg }
3497330f729Sjoerg // Note that Module->PrivateHeaders will not be a TopHeader.
3507330f729Sjoerg
3517330f729Sjoerg if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) {
3527330f729Sjoerg Module->addTopHeader(UmbrellaHeader.Entry);
3537330f729Sjoerg if (Module->Parent)
3547330f729Sjoerg // Include the umbrella header for submodules.
355*e038c9c4Sjoerg addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
356*e038c9c4Sjoerg Includes, LangOpts, Module->IsExternC);
3577330f729Sjoerg } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
3587330f729Sjoerg // Add all of the headers we find in this subdirectory.
3597330f729Sjoerg std::error_code EC;
3607330f729Sjoerg SmallString<128> DirNative;
3617330f729Sjoerg llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative);
3627330f729Sjoerg
3637330f729Sjoerg llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
364*e038c9c4Sjoerg SmallVector<std::pair<std::string, const FileEntry *>, 8> Headers;
3657330f729Sjoerg for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
3667330f729Sjoerg Dir != End && !EC; Dir.increment(EC)) {
3677330f729Sjoerg // Check whether this entry has an extension typically associated with
3687330f729Sjoerg // headers.
3697330f729Sjoerg if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
3707330f729Sjoerg .Cases(".h", ".H", ".hh", ".hpp", true)
3717330f729Sjoerg .Default(false))
3727330f729Sjoerg continue;
3737330f729Sjoerg
3747330f729Sjoerg auto Header = FileMgr.getFile(Dir->path());
3757330f729Sjoerg // FIXME: This shouldn't happen unless there is a file system race. Is
3767330f729Sjoerg // that worth diagnosing?
3777330f729Sjoerg if (!Header)
3787330f729Sjoerg continue;
3797330f729Sjoerg
3807330f729Sjoerg // If this header is marked 'unavailable' in this module, don't include
3817330f729Sjoerg // it.
3827330f729Sjoerg if (ModMap.isHeaderUnavailableInModule(*Header, Module))
3837330f729Sjoerg continue;
3847330f729Sjoerg
3857330f729Sjoerg // Compute the relative path from the directory to this file.
3867330f729Sjoerg SmallVector<StringRef, 16> Components;
3877330f729Sjoerg auto PathIt = llvm::sys::path::rbegin(Dir->path());
3887330f729Sjoerg for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
3897330f729Sjoerg Components.push_back(*PathIt);
390*e038c9c4Sjoerg SmallString<128> RelativeHeader(
391*e038c9c4Sjoerg UmbrellaDir.PathRelativeToRootModuleDirectory);
3927330f729Sjoerg for (auto It = Components.rbegin(), End = Components.rend(); It != End;
3937330f729Sjoerg ++It)
3947330f729Sjoerg llvm::sys::path::append(RelativeHeader, *It);
3957330f729Sjoerg
396*e038c9c4Sjoerg std::string RelName = RelativeHeader.c_str();
397*e038c9c4Sjoerg Headers.push_back(std::make_pair(RelName, *Header));
3987330f729Sjoerg }
3997330f729Sjoerg
4007330f729Sjoerg if (EC)
4017330f729Sjoerg return EC;
402*e038c9c4Sjoerg
403*e038c9c4Sjoerg // Sort header paths and make the header inclusion order deterministic
404*e038c9c4Sjoerg // across different OSs and filesystems.
405*e038c9c4Sjoerg llvm::sort(Headers.begin(), Headers.end(), [](
406*e038c9c4Sjoerg const std::pair<std::string, const FileEntry *> &LHS,
407*e038c9c4Sjoerg const std::pair<std::string, const FileEntry *> &RHS) {
408*e038c9c4Sjoerg return LHS.first < RHS.first;
409*e038c9c4Sjoerg });
410*e038c9c4Sjoerg for (auto &H : Headers) {
411*e038c9c4Sjoerg // Include this header as part of the umbrella directory.
412*e038c9c4Sjoerg Module->addTopHeader(H.second);
413*e038c9c4Sjoerg addHeaderInclude(H.first, Includes, LangOpts, Module->IsExternC);
414*e038c9c4Sjoerg }
4157330f729Sjoerg }
4167330f729Sjoerg
4177330f729Sjoerg // Recurse into submodules.
4187330f729Sjoerg for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
4197330f729Sjoerg SubEnd = Module->submodule_end();
4207330f729Sjoerg Sub != SubEnd; ++Sub)
4217330f729Sjoerg if (std::error_code Err = collectModuleHeaderIncludes(
4227330f729Sjoerg LangOpts, FileMgr, Diag, ModMap, *Sub, Includes))
4237330f729Sjoerg return Err;
4247330f729Sjoerg
4257330f729Sjoerg return std::error_code();
4267330f729Sjoerg }
4277330f729Sjoerg
loadModuleMapForModuleBuild(CompilerInstance & CI,bool IsSystem,bool IsPreprocessed,std::string & PresumedModuleMapFile,unsigned & Offset)4287330f729Sjoerg static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,
4297330f729Sjoerg bool IsPreprocessed,
4307330f729Sjoerg std::string &PresumedModuleMapFile,
4317330f729Sjoerg unsigned &Offset) {
4327330f729Sjoerg auto &SrcMgr = CI.getSourceManager();
4337330f729Sjoerg HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
4347330f729Sjoerg
4357330f729Sjoerg // Map the current input to a file.
4367330f729Sjoerg FileID ModuleMapID = SrcMgr.getMainFileID();
4377330f729Sjoerg const FileEntry *ModuleMap = SrcMgr.getFileEntryForID(ModuleMapID);
4387330f729Sjoerg
4397330f729Sjoerg // If the module map is preprocessed, handle the initial line marker;
4407330f729Sjoerg // line directives are not part of the module map syntax in general.
4417330f729Sjoerg Offset = 0;
4427330f729Sjoerg if (IsPreprocessed) {
4437330f729Sjoerg SourceLocation EndOfLineMarker =
4447330f729Sjoerg ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true);
4457330f729Sjoerg if (EndOfLineMarker.isValid())
4467330f729Sjoerg Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;
4477330f729Sjoerg }
4487330f729Sjoerg
4497330f729Sjoerg // Load the module map file.
4507330f729Sjoerg if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset,
4517330f729Sjoerg PresumedModuleMapFile))
4527330f729Sjoerg return true;
4537330f729Sjoerg
454*e038c9c4Sjoerg if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset)
4557330f729Sjoerg Offset = 0;
4567330f729Sjoerg
4577330f729Sjoerg return false;
4587330f729Sjoerg }
4597330f729Sjoerg
prepareToBuildModule(CompilerInstance & CI,StringRef ModuleMapFilename)4607330f729Sjoerg static Module *prepareToBuildModule(CompilerInstance &CI,
4617330f729Sjoerg StringRef ModuleMapFilename) {
4627330f729Sjoerg if (CI.getLangOpts().CurrentModule.empty()) {
4637330f729Sjoerg CI.getDiagnostics().Report(diag::err_missing_module_name);
4647330f729Sjoerg
4657330f729Sjoerg // FIXME: Eventually, we could consider asking whether there was just
4667330f729Sjoerg // a single module described in the module map, and use that as a
4677330f729Sjoerg // default. Then it would be fairly trivial to just "compile" a module
4687330f729Sjoerg // map with a single module (the common case).
4697330f729Sjoerg return nullptr;
4707330f729Sjoerg }
4717330f729Sjoerg
4727330f729Sjoerg // Dig out the module definition.
4737330f729Sjoerg HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
4747330f729Sjoerg Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule,
475*e038c9c4Sjoerg /*AllowSearch=*/true);
4767330f729Sjoerg if (!M) {
4777330f729Sjoerg CI.getDiagnostics().Report(diag::err_missing_module)
4787330f729Sjoerg << CI.getLangOpts().CurrentModule << ModuleMapFilename;
4797330f729Sjoerg
4807330f729Sjoerg return nullptr;
4817330f729Sjoerg }
4827330f729Sjoerg
4837330f729Sjoerg // Check whether we can build this module at all.
4847330f729Sjoerg if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(),
4857330f729Sjoerg CI.getDiagnostics(), M))
4867330f729Sjoerg return nullptr;
4877330f729Sjoerg
4887330f729Sjoerg // Inform the preprocessor that includes from within the input buffer should
4897330f729Sjoerg // be resolved relative to the build directory of the module map file.
4907330f729Sjoerg CI.getPreprocessor().setMainFileDir(M->Directory);
4917330f729Sjoerg
4927330f729Sjoerg // If the module was inferred from a different module map (via an expanded
4937330f729Sjoerg // umbrella module definition), track that fact.
4947330f729Sjoerg // FIXME: It would be preferable to fill this in as part of processing
4957330f729Sjoerg // the module map, rather than adding it after the fact.
4967330f729Sjoerg StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap;
4977330f729Sjoerg if (!OriginalModuleMapName.empty()) {
4987330f729Sjoerg auto OriginalModuleMap =
4997330f729Sjoerg CI.getFileManager().getFile(OriginalModuleMapName,
5007330f729Sjoerg /*openFile*/ true);
5017330f729Sjoerg if (!OriginalModuleMap) {
5027330f729Sjoerg CI.getDiagnostics().Report(diag::err_module_map_not_found)
5037330f729Sjoerg << OriginalModuleMapName;
5047330f729Sjoerg return nullptr;
5057330f729Sjoerg }
5067330f729Sjoerg if (*OriginalModuleMap != CI.getSourceManager().getFileEntryForID(
5077330f729Sjoerg CI.getSourceManager().getMainFileID())) {
5087330f729Sjoerg M->IsInferred = true;
5097330f729Sjoerg CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()
5107330f729Sjoerg .setInferredModuleAllowedBy(M, *OriginalModuleMap);
5117330f729Sjoerg }
5127330f729Sjoerg }
5137330f729Sjoerg
5147330f729Sjoerg // If we're being run from the command-line, the module build stack will not
5157330f729Sjoerg // have been filled in yet, so complete it now in order to allow us to detect
5167330f729Sjoerg // module cycles.
5177330f729Sjoerg SourceManager &SourceMgr = CI.getSourceManager();
5187330f729Sjoerg if (SourceMgr.getModuleBuildStack().empty())
5197330f729Sjoerg SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,
5207330f729Sjoerg FullSourceLoc(SourceLocation(), SourceMgr));
5217330f729Sjoerg return M;
5227330f729Sjoerg }
5237330f729Sjoerg
5247330f729Sjoerg /// Compute the input buffer that should be used to build the specified module.
5257330f729Sjoerg static std::unique_ptr<llvm::MemoryBuffer>
getInputBufferForModule(CompilerInstance & CI,Module * M)5267330f729Sjoerg getInputBufferForModule(CompilerInstance &CI, Module *M) {
5277330f729Sjoerg FileManager &FileMgr = CI.getFileManager();
5287330f729Sjoerg
5297330f729Sjoerg // Collect the set of #includes we need to build the module.
5307330f729Sjoerg SmallString<256> HeaderContents;
5317330f729Sjoerg std::error_code Err = std::error_code();
5327330f729Sjoerg if (Module::Header UmbrellaHeader = M->getUmbrellaHeader())
533*e038c9c4Sjoerg addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
534*e038c9c4Sjoerg HeaderContents, CI.getLangOpts(), M->IsExternC);
5357330f729Sjoerg Err = collectModuleHeaderIncludes(
5367330f729Sjoerg CI.getLangOpts(), FileMgr, CI.getDiagnostics(),
5377330f729Sjoerg CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,
5387330f729Sjoerg HeaderContents);
5397330f729Sjoerg
5407330f729Sjoerg if (Err) {
5417330f729Sjoerg CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)
5427330f729Sjoerg << M->getFullModuleName() << Err.message();
5437330f729Sjoerg return nullptr;
5447330f729Sjoerg }
5457330f729Sjoerg
5467330f729Sjoerg return llvm::MemoryBuffer::getMemBufferCopy(
5477330f729Sjoerg HeaderContents, Module::getModuleInputBufferName());
5487330f729Sjoerg }
5497330f729Sjoerg
BeginSourceFile(CompilerInstance & CI,const FrontendInputFile & RealInput)5507330f729Sjoerg bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
5517330f729Sjoerg const FrontendInputFile &RealInput) {
5527330f729Sjoerg FrontendInputFile Input(RealInput);
5537330f729Sjoerg assert(!Instance && "Already processing a source file!");
5547330f729Sjoerg assert(!Input.isEmpty() && "Unexpected empty filename!");
5557330f729Sjoerg setCurrentInput(Input);
5567330f729Sjoerg setCompilerInstance(&CI);
5577330f729Sjoerg
5587330f729Sjoerg bool HasBegunSourceFile = false;
5597330f729Sjoerg bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&
5607330f729Sjoerg usesPreprocessorOnly();
5617330f729Sjoerg if (!BeginInvocation(CI))
5627330f729Sjoerg goto failure;
5637330f729Sjoerg
5647330f729Sjoerg // If we're replaying the build of an AST file, import it and set up
5657330f729Sjoerg // the initial state from its build.
5667330f729Sjoerg if (ReplayASTFile) {
5677330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
5687330f729Sjoerg
5697330f729Sjoerg // The AST unit populates its own diagnostics engine rather than ours.
5707330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags(
5717330f729Sjoerg new DiagnosticsEngine(Diags->getDiagnosticIDs(),
5727330f729Sjoerg &Diags->getDiagnosticOptions()));
5737330f729Sjoerg ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
5747330f729Sjoerg
5757330f729Sjoerg // FIXME: What if the input is a memory buffer?
5767330f729Sjoerg StringRef InputFile = Input.getFile();
5777330f729Sjoerg
5787330f729Sjoerg std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
579*e038c9c4Sjoerg std::string(InputFile), CI.getPCHContainerReader(),
580*e038c9c4Sjoerg ASTUnit::LoadPreprocessorOnly, ASTDiags, CI.getFileSystemOpts(),
581*e038c9c4Sjoerg CI.getCodeGenOpts().DebugTypeExtRefs);
5827330f729Sjoerg if (!AST)
5837330f729Sjoerg goto failure;
5847330f729Sjoerg
5857330f729Sjoerg // Options relating to how we treat the input (but not what we do with it)
5867330f729Sjoerg // are inherited from the AST unit.
5877330f729Sjoerg CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts();
5887330f729Sjoerg CI.getPreprocessorOpts() = AST->getPreprocessorOpts();
5897330f729Sjoerg CI.getLangOpts() = AST->getLangOpts();
5907330f729Sjoerg
5917330f729Sjoerg // Set the shared objects, these are reset when we finish processing the
5927330f729Sjoerg // file, otherwise the CompilerInstance will happily destroy them.
5937330f729Sjoerg CI.setFileManager(&AST->getFileManager());
5947330f729Sjoerg CI.createSourceManager(CI.getFileManager());
5957330f729Sjoerg CI.getSourceManager().initializeForReplay(AST->getSourceManager());
5967330f729Sjoerg
5977330f729Sjoerg // Preload all the module files loaded transitively by the AST unit. Also
5987330f729Sjoerg // load all module map files that were parsed as part of building the AST
5997330f729Sjoerg // unit.
6007330f729Sjoerg if (auto ASTReader = AST->getASTReader()) {
6017330f729Sjoerg auto &MM = ASTReader->getModuleManager();
6027330f729Sjoerg auto &PrimaryModule = MM.getPrimaryModule();
6037330f729Sjoerg
6047330f729Sjoerg for (serialization::ModuleFile &MF : MM)
6057330f729Sjoerg if (&MF != &PrimaryModule)
6067330f729Sjoerg CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);
6077330f729Sjoerg
608*e038c9c4Sjoerg ASTReader->visitTopLevelModuleMaps(
609*e038c9c4Sjoerg PrimaryModule, [&](const FileEntry *FE) {
610*e038c9c4Sjoerg CI.getFrontendOpts().ModuleMapFiles.push_back(
611*e038c9c4Sjoerg std::string(FE->getName()));
6127330f729Sjoerg });
6137330f729Sjoerg }
6147330f729Sjoerg
6157330f729Sjoerg // Set up the input file for replay purposes.
6167330f729Sjoerg auto Kind = AST->getInputKind();
6177330f729Sjoerg if (Kind.getFormat() == InputKind::ModuleMap) {
6187330f729Sjoerg Module *ASTModule =
6197330f729Sjoerg AST->getPreprocessor().getHeaderSearchInfo().lookupModule(
6207330f729Sjoerg AST->getLangOpts().CurrentModule, /*AllowSearch*/ false);
6217330f729Sjoerg assert(ASTModule && "module file does not define its own module");
6227330f729Sjoerg Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);
6237330f729Sjoerg } else {
6247330f729Sjoerg auto &OldSM = AST->getSourceManager();
6257330f729Sjoerg FileID ID = OldSM.getMainFileID();
6267330f729Sjoerg if (auto *File = OldSM.getFileEntryForID(ID))
6277330f729Sjoerg Input = FrontendInputFile(File->getName(), Kind);
6287330f729Sjoerg else
629*e038c9c4Sjoerg Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind);
6307330f729Sjoerg }
6317330f729Sjoerg setCurrentInput(Input, std::move(AST));
6327330f729Sjoerg }
6337330f729Sjoerg
6347330f729Sjoerg // AST files follow a very different path, since they share objects via the
6357330f729Sjoerg // AST unit.
6367330f729Sjoerg if (Input.getKind().getFormat() == InputKind::Precompiled) {
6377330f729Sjoerg assert(!usesPreprocessorOnly() && "this case was handled above");
6387330f729Sjoerg assert(hasASTFileSupport() &&
6397330f729Sjoerg "This action does not have AST file support!");
6407330f729Sjoerg
6417330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
6427330f729Sjoerg
6437330f729Sjoerg // FIXME: What if the input is a memory buffer?
6447330f729Sjoerg StringRef InputFile = Input.getFile();
6457330f729Sjoerg
6467330f729Sjoerg std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
647*e038c9c4Sjoerg std::string(InputFile), CI.getPCHContainerReader(),
648*e038c9c4Sjoerg ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts(),
649*e038c9c4Sjoerg CI.getCodeGenOpts().DebugTypeExtRefs);
6507330f729Sjoerg
6517330f729Sjoerg if (!AST)
6527330f729Sjoerg goto failure;
6537330f729Sjoerg
6547330f729Sjoerg // Inform the diagnostic client we are processing a source file.
6557330f729Sjoerg CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
6567330f729Sjoerg HasBegunSourceFile = true;
6577330f729Sjoerg
6587330f729Sjoerg // Set the shared objects, these are reset when we finish processing the
6597330f729Sjoerg // file, otherwise the CompilerInstance will happily destroy them.
6607330f729Sjoerg CI.setFileManager(&AST->getFileManager());
6617330f729Sjoerg CI.setSourceManager(&AST->getSourceManager());
6627330f729Sjoerg CI.setPreprocessor(AST->getPreprocessorPtr());
6637330f729Sjoerg Preprocessor &PP = CI.getPreprocessor();
6647330f729Sjoerg PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
6657330f729Sjoerg PP.getLangOpts());
6667330f729Sjoerg CI.setASTContext(&AST->getASTContext());
6677330f729Sjoerg
6687330f729Sjoerg setCurrentInput(Input, std::move(AST));
6697330f729Sjoerg
6707330f729Sjoerg // Initialize the action.
6717330f729Sjoerg if (!BeginSourceFileAction(CI))
6727330f729Sjoerg goto failure;
6737330f729Sjoerg
6747330f729Sjoerg // Create the AST consumer.
6757330f729Sjoerg CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile));
6767330f729Sjoerg if (!CI.hasASTConsumer())
6777330f729Sjoerg goto failure;
6787330f729Sjoerg
6797330f729Sjoerg return true;
6807330f729Sjoerg }
6817330f729Sjoerg
6827330f729Sjoerg // Set up the file and source managers, if needed.
6837330f729Sjoerg if (!CI.hasFileManager()) {
6847330f729Sjoerg if (!CI.createFileManager()) {
6857330f729Sjoerg goto failure;
6867330f729Sjoerg }
6877330f729Sjoerg }
6887330f729Sjoerg if (!CI.hasSourceManager())
6897330f729Sjoerg CI.createSourceManager(CI.getFileManager());
6907330f729Sjoerg
6917330f729Sjoerg // Set up embedding for any specified files. Do this before we load any
6927330f729Sjoerg // source files, including the primary module map for the compilation.
6937330f729Sjoerg for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
6947330f729Sjoerg if (auto FE = CI.getFileManager().getFile(F, /*openFile*/true))
6957330f729Sjoerg CI.getSourceManager().setFileIsTransient(*FE);
6967330f729Sjoerg else
6977330f729Sjoerg CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
6987330f729Sjoerg }
6997330f729Sjoerg if (CI.getFrontendOpts().ModulesEmbedAllFiles)
7007330f729Sjoerg CI.getSourceManager().setAllFilesAreTransient(true);
7017330f729Sjoerg
7027330f729Sjoerg // IR files bypass the rest of initialization.
7037330f729Sjoerg if (Input.getKind().getLanguage() == Language::LLVM_IR) {
7047330f729Sjoerg assert(hasIRSupport() &&
7057330f729Sjoerg "This action does not have IR file support!");
7067330f729Sjoerg
7077330f729Sjoerg // Inform the diagnostic client we are processing a source file.
7087330f729Sjoerg CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
7097330f729Sjoerg HasBegunSourceFile = true;
7107330f729Sjoerg
7117330f729Sjoerg // Initialize the action.
7127330f729Sjoerg if (!BeginSourceFileAction(CI))
7137330f729Sjoerg goto failure;
7147330f729Sjoerg
7157330f729Sjoerg // Initialize the main file entry.
7167330f729Sjoerg if (!CI.InitializeSourceManager(CurrentInput))
7177330f729Sjoerg goto failure;
7187330f729Sjoerg
7197330f729Sjoerg return true;
7207330f729Sjoerg }
7217330f729Sjoerg
7227330f729Sjoerg // If the implicit PCH include is actually a directory, rather than
7237330f729Sjoerg // a single file, search for a suitable PCH file in that directory.
7247330f729Sjoerg if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
7257330f729Sjoerg FileManager &FileMgr = CI.getFileManager();
7267330f729Sjoerg PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
7277330f729Sjoerg StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
7287330f729Sjoerg std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();
7297330f729Sjoerg if (auto PCHDir = FileMgr.getDirectory(PCHInclude)) {
7307330f729Sjoerg std::error_code EC;
7317330f729Sjoerg SmallString<128> DirNative;
7327330f729Sjoerg llvm::sys::path::native((*PCHDir)->getName(), DirNative);
7337330f729Sjoerg bool Found = false;
7347330f729Sjoerg llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
7357330f729Sjoerg for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
7367330f729Sjoerg DirEnd;
7377330f729Sjoerg Dir != DirEnd && !EC; Dir.increment(EC)) {
7387330f729Sjoerg // Check whether this is an acceptable AST file.
7397330f729Sjoerg if (ASTReader::isAcceptableASTFile(
7407330f729Sjoerg Dir->path(), FileMgr, CI.getPCHContainerReader(),
7417330f729Sjoerg CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
7427330f729Sjoerg SpecificModuleCachePath)) {
743*e038c9c4Sjoerg PPOpts.ImplicitPCHInclude = std::string(Dir->path());
7447330f729Sjoerg Found = true;
7457330f729Sjoerg break;
7467330f729Sjoerg }
7477330f729Sjoerg }
7487330f729Sjoerg
7497330f729Sjoerg if (!Found) {
7507330f729Sjoerg CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;
7517330f729Sjoerg goto failure;
7527330f729Sjoerg }
7537330f729Sjoerg }
7547330f729Sjoerg }
7557330f729Sjoerg
7567330f729Sjoerg // Set up the preprocessor if needed. When parsing model files the
7577330f729Sjoerg // preprocessor of the original source is reused.
7587330f729Sjoerg if (!isModelParsingAction())
7597330f729Sjoerg CI.createPreprocessor(getTranslationUnitKind());
7607330f729Sjoerg
7617330f729Sjoerg // Inform the diagnostic client we are processing a source file.
7627330f729Sjoerg CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
7637330f729Sjoerg &CI.getPreprocessor());
7647330f729Sjoerg HasBegunSourceFile = true;
7657330f729Sjoerg
7667330f729Sjoerg // Initialize the main file entry.
7677330f729Sjoerg if (!CI.InitializeSourceManager(Input))
7687330f729Sjoerg goto failure;
7697330f729Sjoerg
7707330f729Sjoerg // For module map files, we first parse the module map and synthesize a
7717330f729Sjoerg // "<module-includes>" buffer before more conventional processing.
7727330f729Sjoerg if (Input.getKind().getFormat() == InputKind::ModuleMap) {
7737330f729Sjoerg CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);
7747330f729Sjoerg
7757330f729Sjoerg std::string PresumedModuleMapFile;
7767330f729Sjoerg unsigned OffsetToContents;
7777330f729Sjoerg if (loadModuleMapForModuleBuild(CI, Input.isSystem(),
7787330f729Sjoerg Input.isPreprocessed(),
7797330f729Sjoerg PresumedModuleMapFile, OffsetToContents))
7807330f729Sjoerg goto failure;
7817330f729Sjoerg
7827330f729Sjoerg auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());
7837330f729Sjoerg if (!CurrentModule)
7847330f729Sjoerg goto failure;
7857330f729Sjoerg
7867330f729Sjoerg CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile;
7877330f729Sjoerg
7887330f729Sjoerg if (OffsetToContents)
7897330f729Sjoerg // If the module contents are in the same file, skip to them.
7907330f729Sjoerg CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);
7917330f729Sjoerg else {
7927330f729Sjoerg // Otherwise, convert the module description to a suitable input buffer.
7937330f729Sjoerg auto Buffer = getInputBufferForModule(CI, CurrentModule);
7947330f729Sjoerg if (!Buffer)
7957330f729Sjoerg goto failure;
7967330f729Sjoerg
7977330f729Sjoerg // Reinitialize the main file entry to refer to the new input.
7987330f729Sjoerg auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
7997330f729Sjoerg auto &SourceMgr = CI.getSourceManager();
8007330f729Sjoerg auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind);
801*e038c9c4Sjoerg assert(BufferID.isValid() && "couldn't create module buffer ID");
8027330f729Sjoerg SourceMgr.setMainFileID(BufferID);
8037330f729Sjoerg }
8047330f729Sjoerg }
8057330f729Sjoerg
8067330f729Sjoerg // Initialize the action.
8077330f729Sjoerg if (!BeginSourceFileAction(CI))
8087330f729Sjoerg goto failure;
8097330f729Sjoerg
8107330f729Sjoerg // If we were asked to load any module map files, do so now.
8117330f729Sjoerg for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) {
8127330f729Sjoerg if (auto File = CI.getFileManager().getFile(Filename))
8137330f729Sjoerg CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile(
8147330f729Sjoerg *File, /*IsSystem*/false);
8157330f729Sjoerg else
8167330f729Sjoerg CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
8177330f729Sjoerg }
8187330f729Sjoerg
8197330f729Sjoerg // Add a module declaration scope so that modules from -fmodule-map-file
8207330f729Sjoerg // arguments may shadow modules found implicitly in search paths.
8217330f729Sjoerg CI.getPreprocessor()
8227330f729Sjoerg .getHeaderSearchInfo()
8237330f729Sjoerg .getModuleMap()
8247330f729Sjoerg .finishModuleDeclarationScope();
8257330f729Sjoerg
8267330f729Sjoerg // Create the AST context and consumer unless this is a preprocessor only
8277330f729Sjoerg // action.
8287330f729Sjoerg if (!usesPreprocessorOnly()) {
8297330f729Sjoerg // Parsing a model file should reuse the existing ASTContext.
8307330f729Sjoerg if (!isModelParsingAction())
8317330f729Sjoerg CI.createASTContext();
8327330f729Sjoerg
8337330f729Sjoerg // For preprocessed files, check if the first line specifies the original
8347330f729Sjoerg // source file name with a linemarker.
835*e038c9c4Sjoerg std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
8367330f729Sjoerg if (Input.isPreprocessed())
8377330f729Sjoerg ReadOriginalFileName(CI, PresumedInputFile);
8387330f729Sjoerg
8397330f729Sjoerg std::unique_ptr<ASTConsumer> Consumer =
8407330f729Sjoerg CreateWrappedASTConsumer(CI, PresumedInputFile);
8417330f729Sjoerg if (!Consumer)
8427330f729Sjoerg goto failure;
8437330f729Sjoerg
8447330f729Sjoerg // FIXME: should not overwrite ASTMutationListener when parsing model files?
8457330f729Sjoerg if (!isModelParsingAction())
8467330f729Sjoerg CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
8477330f729Sjoerg
8487330f729Sjoerg if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
8497330f729Sjoerg // Convert headers to PCH and chain them.
8507330f729Sjoerg IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;
8517330f729Sjoerg source = createChainedIncludesSource(CI, FinalReader);
8527330f729Sjoerg if (!source)
8537330f729Sjoerg goto failure;
854*e038c9c4Sjoerg CI.setASTReader(static_cast<ASTReader *>(FinalReader.get()));
8557330f729Sjoerg CI.getASTContext().setExternalSource(source);
8567330f729Sjoerg } else if (CI.getLangOpts().Modules ||
8577330f729Sjoerg !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
8587330f729Sjoerg // Use PCM or PCH.
8597330f729Sjoerg assert(hasPCHSupport() && "This action does not have PCH support!");
8607330f729Sjoerg ASTDeserializationListener *DeserialListener =
8617330f729Sjoerg Consumer->GetASTDeserializationListener();
8627330f729Sjoerg bool DeleteDeserialListener = false;
8637330f729Sjoerg if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) {
8647330f729Sjoerg DeserialListener = new DeserializedDeclsDumper(DeserialListener,
8657330f729Sjoerg DeleteDeserialListener);
8667330f729Sjoerg DeleteDeserialListener = true;
8677330f729Sjoerg }
8687330f729Sjoerg if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) {
8697330f729Sjoerg DeserialListener = new DeserializedDeclsChecker(
8707330f729Sjoerg CI.getASTContext(),
8717330f729Sjoerg CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
8727330f729Sjoerg DeserialListener, DeleteDeserialListener);
8737330f729Sjoerg DeleteDeserialListener = true;
8747330f729Sjoerg }
8757330f729Sjoerg if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
8767330f729Sjoerg CI.createPCHExternalASTSource(
8777330f729Sjoerg CI.getPreprocessorOpts().ImplicitPCHInclude,
878*e038c9c4Sjoerg CI.getPreprocessorOpts().DisablePCHOrModuleValidation,
879*e038c9c4Sjoerg CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
880*e038c9c4Sjoerg DeserialListener, DeleteDeserialListener);
8817330f729Sjoerg if (!CI.getASTContext().getExternalSource())
8827330f729Sjoerg goto failure;
8837330f729Sjoerg }
884*e038c9c4Sjoerg // If modules are enabled, create the AST reader before creating
8857330f729Sjoerg // any builtins, so that all declarations know that they might be
8867330f729Sjoerg // extended by an external source.
8877330f729Sjoerg if (CI.getLangOpts().Modules || !CI.hasASTContext() ||
8887330f729Sjoerg !CI.getASTContext().getExternalSource()) {
889*e038c9c4Sjoerg CI.createASTReader();
890*e038c9c4Sjoerg CI.getASTReader()->setDeserializationListener(DeserialListener,
8917330f729Sjoerg DeleteDeserialListener);
8927330f729Sjoerg }
8937330f729Sjoerg }
8947330f729Sjoerg
8957330f729Sjoerg CI.setASTConsumer(std::move(Consumer));
8967330f729Sjoerg if (!CI.hasASTConsumer())
8977330f729Sjoerg goto failure;
8987330f729Sjoerg }
8997330f729Sjoerg
9007330f729Sjoerg // Initialize built-in info as long as we aren't using an external AST
9017330f729Sjoerg // source.
9027330f729Sjoerg if (CI.getLangOpts().Modules || !CI.hasASTContext() ||
9037330f729Sjoerg !CI.getASTContext().getExternalSource()) {
9047330f729Sjoerg Preprocessor &PP = CI.getPreprocessor();
9057330f729Sjoerg PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
9067330f729Sjoerg PP.getLangOpts());
9077330f729Sjoerg } else {
9087330f729Sjoerg // FIXME: If this is a problem, recover from it by creating a multiplex
9097330f729Sjoerg // source.
910*e038c9c4Sjoerg assert((!CI.getLangOpts().Modules || CI.getASTReader()) &&
9117330f729Sjoerg "modules enabled but created an external source that "
9127330f729Sjoerg "doesn't support modules");
9137330f729Sjoerg }
9147330f729Sjoerg
9157330f729Sjoerg // If we were asked to load any module files, do so now.
9167330f729Sjoerg for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles)
9177330f729Sjoerg if (!CI.loadModuleFile(ModuleFile))
9187330f729Sjoerg goto failure;
9197330f729Sjoerg
9207330f729Sjoerg // If there is a layout overrides file, attach an external AST source that
9217330f729Sjoerg // provides the layouts from that file.
9227330f729Sjoerg if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&
9237330f729Sjoerg CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {
9247330f729Sjoerg IntrusiveRefCntPtr<ExternalASTSource>
9257330f729Sjoerg Override(new LayoutOverrideSource(
9267330f729Sjoerg CI.getFrontendOpts().OverrideRecordLayoutsFile));
9277330f729Sjoerg CI.getASTContext().setExternalSource(Override);
9287330f729Sjoerg }
9297330f729Sjoerg
9307330f729Sjoerg return true;
9317330f729Sjoerg
9327330f729Sjoerg // If we failed, reset state since the client will not end up calling the
9337330f729Sjoerg // matching EndSourceFile().
9347330f729Sjoerg failure:
9357330f729Sjoerg if (HasBegunSourceFile)
9367330f729Sjoerg CI.getDiagnosticClient().EndSourceFile();
9377330f729Sjoerg CI.clearOutputFiles(/*EraseFiles=*/true);
9387330f729Sjoerg CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
9397330f729Sjoerg setCurrentInput(FrontendInputFile());
9407330f729Sjoerg setCompilerInstance(nullptr);
9417330f729Sjoerg return false;
9427330f729Sjoerg }
9437330f729Sjoerg
Execute()9447330f729Sjoerg llvm::Error FrontendAction::Execute() {
9457330f729Sjoerg CompilerInstance &CI = getCompilerInstance();
9467330f729Sjoerg
9477330f729Sjoerg if (CI.hasFrontendTimer()) {
9487330f729Sjoerg llvm::TimeRegion Timer(CI.getFrontendTimer());
9497330f729Sjoerg ExecuteAction();
9507330f729Sjoerg }
9517330f729Sjoerg else ExecuteAction();
9527330f729Sjoerg
9537330f729Sjoerg // If we are supposed to rebuild the global module index, do so now unless
9547330f729Sjoerg // there were any module-build failures.
9557330f729Sjoerg if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&
9567330f729Sjoerg CI.hasPreprocessor()) {
9577330f729Sjoerg StringRef Cache =
9587330f729Sjoerg CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath();
9597330f729Sjoerg if (!Cache.empty()) {
9607330f729Sjoerg if (llvm::Error Err = GlobalModuleIndex::writeIndex(
9617330f729Sjoerg CI.getFileManager(), CI.getPCHContainerReader(), Cache)) {
9627330f729Sjoerg // FIXME this drops the error on the floor, but
9637330f729Sjoerg // Index/pch-from-libclang.c seems to rely on dropping at least some of
9647330f729Sjoerg // the error conditions!
9657330f729Sjoerg consumeError(std::move(Err));
9667330f729Sjoerg }
9677330f729Sjoerg }
9687330f729Sjoerg }
9697330f729Sjoerg
9707330f729Sjoerg return llvm::Error::success();
9717330f729Sjoerg }
9727330f729Sjoerg
EndSourceFile()9737330f729Sjoerg void FrontendAction::EndSourceFile() {
9747330f729Sjoerg CompilerInstance &CI = getCompilerInstance();
9757330f729Sjoerg
9767330f729Sjoerg // Inform the diagnostic client we are done with this source file.
9777330f729Sjoerg CI.getDiagnosticClient().EndSourceFile();
9787330f729Sjoerg
9797330f729Sjoerg // Inform the preprocessor we are done.
9807330f729Sjoerg if (CI.hasPreprocessor())
9817330f729Sjoerg CI.getPreprocessor().EndSourceFile();
9827330f729Sjoerg
9837330f729Sjoerg // Finalize the action.
9847330f729Sjoerg EndSourceFileAction();
9857330f729Sjoerg
9867330f729Sjoerg // Sema references the ast consumer, so reset sema first.
9877330f729Sjoerg //
9887330f729Sjoerg // FIXME: There is more per-file stuff we could just drop here?
9897330f729Sjoerg bool DisableFree = CI.getFrontendOpts().DisableFree;
9907330f729Sjoerg if (DisableFree) {
9917330f729Sjoerg CI.resetAndLeakSema();
9927330f729Sjoerg CI.resetAndLeakASTContext();
9937330f729Sjoerg llvm::BuryPointer(CI.takeASTConsumer().get());
9947330f729Sjoerg } else {
9957330f729Sjoerg CI.setSema(nullptr);
9967330f729Sjoerg CI.setASTContext(nullptr);
9977330f729Sjoerg CI.setASTConsumer(nullptr);
9987330f729Sjoerg }
9997330f729Sjoerg
10007330f729Sjoerg if (CI.getFrontendOpts().ShowStats) {
10017330f729Sjoerg llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
10027330f729Sjoerg CI.getPreprocessor().PrintStats();
10037330f729Sjoerg CI.getPreprocessor().getIdentifierTable().PrintStats();
10047330f729Sjoerg CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
10057330f729Sjoerg CI.getSourceManager().PrintStats();
10067330f729Sjoerg llvm::errs() << "\n";
10077330f729Sjoerg }
10087330f729Sjoerg
10097330f729Sjoerg // Cleanup the output streams, and erase the output files if instructed by the
10107330f729Sjoerg // FrontendAction.
10117330f729Sjoerg CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());
10127330f729Sjoerg
10137330f729Sjoerg if (isCurrentFileAST()) {
10147330f729Sjoerg if (DisableFree) {
10157330f729Sjoerg CI.resetAndLeakPreprocessor();
10167330f729Sjoerg CI.resetAndLeakSourceManager();
10177330f729Sjoerg CI.resetAndLeakFileManager();
10187330f729Sjoerg llvm::BuryPointer(std::move(CurrentASTUnit));
10197330f729Sjoerg } else {
10207330f729Sjoerg CI.setPreprocessor(nullptr);
10217330f729Sjoerg CI.setSourceManager(nullptr);
10227330f729Sjoerg CI.setFileManager(nullptr);
10237330f729Sjoerg }
10247330f729Sjoerg }
10257330f729Sjoerg
10267330f729Sjoerg setCompilerInstance(nullptr);
10277330f729Sjoerg setCurrentInput(FrontendInputFile());
10287330f729Sjoerg CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
10297330f729Sjoerg }
10307330f729Sjoerg
shouldEraseOutputFiles()10317330f729Sjoerg bool FrontendAction::shouldEraseOutputFiles() {
10327330f729Sjoerg return getCompilerInstance().getDiagnostics().hasErrorOccurred();
10337330f729Sjoerg }
10347330f729Sjoerg
10357330f729Sjoerg //===----------------------------------------------------------------------===//
10367330f729Sjoerg // Utility Actions
10377330f729Sjoerg //===----------------------------------------------------------------------===//
10387330f729Sjoerg
ExecuteAction()10397330f729Sjoerg void ASTFrontendAction::ExecuteAction() {
10407330f729Sjoerg CompilerInstance &CI = getCompilerInstance();
10417330f729Sjoerg if (!CI.hasPreprocessor())
10427330f729Sjoerg return;
10437330f729Sjoerg
10447330f729Sjoerg // FIXME: Move the truncation aspect of this into Sema, we delayed this till
10457330f729Sjoerg // here so the source manager would be initialized.
10467330f729Sjoerg if (hasCodeCompletionSupport() &&
10477330f729Sjoerg !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
10487330f729Sjoerg CI.createCodeCompletionConsumer();
10497330f729Sjoerg
10507330f729Sjoerg // Use a code completion consumer?
10517330f729Sjoerg CodeCompleteConsumer *CompletionConsumer = nullptr;
10527330f729Sjoerg if (CI.hasCodeCompletionConsumer())
10537330f729Sjoerg CompletionConsumer = &CI.getCodeCompletionConsumer();
10547330f729Sjoerg
10557330f729Sjoerg if (!CI.hasSema())
10567330f729Sjoerg CI.createSema(getTranslationUnitKind(), CompletionConsumer);
10577330f729Sjoerg
10587330f729Sjoerg ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
10597330f729Sjoerg CI.getFrontendOpts().SkipFunctionBodies);
10607330f729Sjoerg }
10617330f729Sjoerg
anchor()10627330f729Sjoerg void PluginASTAction::anchor() { }
10637330f729Sjoerg
10647330f729Sjoerg std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)10657330f729Sjoerg PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
10667330f729Sjoerg StringRef InFile) {
10677330f729Sjoerg llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
10687330f729Sjoerg }
10697330f729Sjoerg
PrepareToExecuteAction(CompilerInstance & CI)10707330f729Sjoerg bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) {
10717330f729Sjoerg return WrappedAction->PrepareToExecuteAction(CI);
10727330f729Sjoerg }
10737330f729Sjoerg std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)10747330f729Sjoerg WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
10757330f729Sjoerg StringRef InFile) {
10767330f729Sjoerg return WrappedAction->CreateASTConsumer(CI, InFile);
10777330f729Sjoerg }
BeginInvocation(CompilerInstance & CI)10787330f729Sjoerg bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {
10797330f729Sjoerg return WrappedAction->BeginInvocation(CI);
10807330f729Sjoerg }
BeginSourceFileAction(CompilerInstance & CI)10817330f729Sjoerg bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) {
10827330f729Sjoerg WrappedAction->setCurrentInput(getCurrentInput());
10837330f729Sjoerg WrappedAction->setCompilerInstance(&CI);
10847330f729Sjoerg auto Ret = WrappedAction->BeginSourceFileAction(CI);
10857330f729Sjoerg // BeginSourceFileAction may change CurrentInput, e.g. during module builds.
10867330f729Sjoerg setCurrentInput(WrappedAction->getCurrentInput());
10877330f729Sjoerg return Ret;
10887330f729Sjoerg }
ExecuteAction()10897330f729Sjoerg void WrapperFrontendAction::ExecuteAction() {
10907330f729Sjoerg WrappedAction->ExecuteAction();
10917330f729Sjoerg }
EndSourceFile()1092*e038c9c4Sjoerg void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); }
EndSourceFileAction()10937330f729Sjoerg void WrapperFrontendAction::EndSourceFileAction() {
10947330f729Sjoerg WrappedAction->EndSourceFileAction();
10957330f729Sjoerg }
shouldEraseOutputFiles()1096*e038c9c4Sjoerg bool WrapperFrontendAction::shouldEraseOutputFiles() {
1097*e038c9c4Sjoerg return WrappedAction->shouldEraseOutputFiles();
1098*e038c9c4Sjoerg }
10997330f729Sjoerg
usesPreprocessorOnly() const11007330f729Sjoerg bool WrapperFrontendAction::usesPreprocessorOnly() const {
11017330f729Sjoerg return WrappedAction->usesPreprocessorOnly();
11027330f729Sjoerg }
getTranslationUnitKind()11037330f729Sjoerg TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {
11047330f729Sjoerg return WrappedAction->getTranslationUnitKind();
11057330f729Sjoerg }
hasPCHSupport() const11067330f729Sjoerg bool WrapperFrontendAction::hasPCHSupport() const {
11077330f729Sjoerg return WrappedAction->hasPCHSupport();
11087330f729Sjoerg }
hasASTFileSupport() const11097330f729Sjoerg bool WrapperFrontendAction::hasASTFileSupport() const {
11107330f729Sjoerg return WrappedAction->hasASTFileSupport();
11117330f729Sjoerg }
hasIRSupport() const11127330f729Sjoerg bool WrapperFrontendAction::hasIRSupport() const {
11137330f729Sjoerg return WrappedAction->hasIRSupport();
11147330f729Sjoerg }
hasCodeCompletionSupport() const11157330f729Sjoerg bool WrapperFrontendAction::hasCodeCompletionSupport() const {
11167330f729Sjoerg return WrappedAction->hasCodeCompletionSupport();
11177330f729Sjoerg }
11187330f729Sjoerg
WrapperFrontendAction(std::unique_ptr<FrontendAction> WrappedAction)11197330f729Sjoerg WrapperFrontendAction::WrapperFrontendAction(
11207330f729Sjoerg std::unique_ptr<FrontendAction> WrappedAction)
11217330f729Sjoerg : WrappedAction(std::move(WrappedAction)) {}
11227330f729Sjoerg
1123