167 lines · cpp
1//===--- CreateASTUnitFromArgs.h - Create an ASTUnit from Args ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Utility for creating an ASTUnit from a vector of command line arguments.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Driver/CreateASTUnitFromArgs.h"14#include "clang/Driver/CreateInvocationFromArgs.h"15#include "clang/Frontend/CompilerInvocation.h"16#include "clang/Lex/PreprocessorOptions.h"17#include "clang/Serialization/ModuleCache.h"18#include "llvm/Support/CrashRecoveryContext.h"19 20using namespace clang;21 22/// Create an ASTUnit from a vector of command line arguments, which must23/// specify exactly one source file.24///25/// \param ArgBegin - The beginning of the argument vector.26///27/// \param ArgEnd - The end of the argument vector.28///29/// \param PCHContainerOps - The PCHContainerOperations to use for loading and30/// creating modules.31///32/// \param Diags - The diagnostics engine to use for reporting errors; its33/// lifetime is expected to extend past that of the returned ASTUnit.34///35/// \param ResourceFilesPath - The path to the compiler resource files.36///37/// \param StorePreamblesInMemory - Whether to store PCH in memory. If false,38/// PCH are stored in temporary files.39///40/// \param PreambleStoragePath - The path to a directory, in which to create41/// temporary PCH files. If empty, the default system temporary directory is42/// used. This parameter is ignored if \p StorePreamblesInMemory is true.43///44/// \param ModuleFormat - If provided, uses the specific module format.45///46/// \param ErrAST - If non-null and parsing failed without any AST to return47/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit48/// mainly to allow the caller to see the diagnostics.49///50/// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.51/// Note that preamble is saved to a temporary directory on a RealFileSystem,52/// so in order for it to be loaded correctly, VFS should have access to53/// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used54/// if \p VFS is nullptr.55///56// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we57// shouldn't need to specify them at construction time.58std::unique_ptr<ASTUnit> clang::CreateASTUnitFromCommandLine(59 const char **ArgBegin, const char **ArgEnd,60 std::shared_ptr<PCHContainerOperations> PCHContainerOps,61 std::shared_ptr<DiagnosticOptions> DiagOpts,62 IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,63 bool StorePreamblesInMemory, StringRef PreambleStoragePath,64 bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,65 ArrayRef<ASTUnit::RemappedFile> RemappedFiles,66 bool RemappedFilesKeepOriginalName, unsigned PrecompilePreambleAfterNParses,67 TranslationUnitKind TUKind, bool CacheCodeCompletionResults,68 bool IncludeBriefCommentsInCodeCompletion, bool AllowPCHWithCompilerErrors,69 SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse,70 bool UserFilesAreVolatile, bool ForSerialization,71 bool RetainExcludedConditionalBlocks, std::optional<StringRef> ModuleFormat,72 std::unique_ptr<ASTUnit> *ErrAST,73 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {74 assert(Diags.get() && "no DiagnosticsEngine was provided");75 76 // If no VFS was provided, create one that tracks the physical file system.77 // If '-working-directory' was passed as an argument, 'createInvocation' will78 // set this as the current working directory of the VFS.79 if (!VFS)80 VFS = llvm::vfs::createPhysicalFileSystem();81 82 SmallVector<StoredDiagnostic, 4> StoredDiagnostics;83 84 std::shared_ptr<CompilerInvocation> CI;85 86 {87 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,88 &StoredDiagnostics, nullptr);89 90 CreateInvocationOptions CIOpts;91 CIOpts.VFS = VFS;92 CIOpts.Diags = Diags;93 CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?94 CI = createInvocation(llvm::ArrayRef(ArgBegin, ArgEnd), std::move(CIOpts));95 if (!CI)96 return nullptr;97 }98 99 // Override any files that need remapping100 for (const auto &RemappedFile : RemappedFiles) {101 CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,102 RemappedFile.second);103 }104 PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();105 PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;106 PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;107 PPOpts.SingleFileParseMode = SingleFileParse;108 PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;109 110 // Override the resources path.111 CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);112 113 CI->getFrontendOpts().SkipFunctionBodies =114 SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;115 116 if (ModuleFormat)117 CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat);118 119 // Create the AST unit.120 std::unique_ptr<ASTUnit> AST;121 AST.reset(new ASTUnit(false));122 AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();123 AST->StoredDiagnostics.swap(StoredDiagnostics);124 ASTUnit::ConfigureDiags(Diags, *AST, CaptureDiagnostics);125 AST->DiagOpts = DiagOpts;126 AST->Diagnostics = Diags;127 AST->FileSystemOpts = CI->getFileSystemOpts();128 AST->CodeGenOpts = std::make_unique<CodeGenOptions>(CI->getCodeGenOpts());129 VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);130 AST->FileMgr =131 llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);132 AST->StorePreamblesInMemory = StorePreamblesInMemory;133 AST->PreambleStoragePath = PreambleStoragePath;134 AST->ModCache = createCrossProcessModuleCache();135 AST->OnlyLocalDecls = OnlyLocalDecls;136 AST->CaptureDiagnostics = CaptureDiagnostics;137 AST->TUKind = TUKind;138 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;139 AST->IncludeBriefCommentsInCodeCompletion =140 IncludeBriefCommentsInCodeCompletion;141 AST->UserFilesAreVolatile = UserFilesAreVolatile;142 AST->Invocation = CI;143 AST->SkipFunctionBodies = SkipFunctionBodies;144 if (ForSerialization)145 AST->WriterData.reset(146 new ASTUnit::ASTWriterData(*AST->ModCache, *AST->CodeGenOpts));147 // Zero out now to ease cleanup during crash recovery.148 CI = nullptr;149 Diags = nullptr;150 151 // Recover resources if we crash before exiting this method.152 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get());153 154 if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),155 PrecompilePreambleAfterNParses, VFS)) {156 // Some error occurred, if caller wants to examine diagnostics, pass it the157 // ASTUnit.158 if (ErrAST) {159 AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);160 ErrAST->swap(AST);161 }162 return nullptr;163 }164 165 return AST;166}167