Path: blob/main/contrib/llvm-project/clang/lib/Frontend/ASTUnit.cpp
35233 views
//===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//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//===----------------------------------------------------------------------===//7//8// ASTUnit Implementation.9//10//===----------------------------------------------------------------------===//1112#include "clang/Frontend/ASTUnit.h"13#include "clang/AST/ASTConsumer.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/CommentCommandTraits.h"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclBase.h"18#include "clang/AST/DeclCXX.h"19#include "clang/AST/DeclGroup.h"20#include "clang/AST/DeclObjC.h"21#include "clang/AST/DeclTemplate.h"22#include "clang/AST/DeclarationName.h"23#include "clang/AST/ExternalASTSource.h"24#include "clang/AST/PrettyPrinter.h"25#include "clang/AST/Type.h"26#include "clang/AST/TypeOrdering.h"27#include "clang/Basic/Diagnostic.h"28#include "clang/Basic/FileManager.h"29#include "clang/Basic/IdentifierTable.h"30#include "clang/Basic/LLVM.h"31#include "clang/Basic/LangOptions.h"32#include "clang/Basic/LangStandard.h"33#include "clang/Basic/Module.h"34#include "clang/Basic/SourceLocation.h"35#include "clang/Basic/SourceManager.h"36#include "clang/Basic/TargetInfo.h"37#include "clang/Basic/TargetOptions.h"38#include "clang/Frontend/CompilerInstance.h"39#include "clang/Frontend/CompilerInvocation.h"40#include "clang/Frontend/FrontendAction.h"41#include "clang/Frontend/FrontendActions.h"42#include "clang/Frontend/FrontendDiagnostic.h"43#include "clang/Frontend/FrontendOptions.h"44#include "clang/Frontend/MultiplexConsumer.h"45#include "clang/Frontend/PrecompiledPreamble.h"46#include "clang/Frontend/Utils.h"47#include "clang/Lex/HeaderSearch.h"48#include "clang/Lex/HeaderSearchOptions.h"49#include "clang/Lex/Lexer.h"50#include "clang/Lex/PPCallbacks.h"51#include "clang/Lex/PreprocessingRecord.h"52#include "clang/Lex/Preprocessor.h"53#include "clang/Lex/PreprocessorOptions.h"54#include "clang/Lex/Token.h"55#include "clang/Sema/CodeCompleteConsumer.h"56#include "clang/Sema/CodeCompleteOptions.h"57#include "clang/Sema/Sema.h"58#include "clang/Sema/SemaCodeCompletion.h"59#include "clang/Serialization/ASTBitCodes.h"60#include "clang/Serialization/ASTReader.h"61#include "clang/Serialization/ASTWriter.h"62#include "clang/Serialization/ContinuousRangeMap.h"63#include "clang/Serialization/InMemoryModuleCache.h"64#include "clang/Serialization/ModuleFile.h"65#include "clang/Serialization/PCHContainerOperations.h"66#include "llvm/ADT/ArrayRef.h"67#include "llvm/ADT/DenseMap.h"68#include "llvm/ADT/IntrusiveRefCntPtr.h"69#include "llvm/ADT/STLExtras.h"70#include "llvm/ADT/ScopeExit.h"71#include "llvm/ADT/SmallVector.h"72#include "llvm/ADT/StringMap.h"73#include "llvm/ADT/StringRef.h"74#include "llvm/ADT/StringSet.h"75#include "llvm/ADT/Twine.h"76#include "llvm/ADT/iterator_range.h"77#include "llvm/Bitstream/BitstreamWriter.h"78#include "llvm/Support/Allocator.h"79#include "llvm/Support/Casting.h"80#include "llvm/Support/CrashRecoveryContext.h"81#include "llvm/Support/DJB.h"82#include "llvm/Support/ErrorHandling.h"83#include "llvm/Support/ErrorOr.h"84#include "llvm/Support/FileSystem.h"85#include "llvm/Support/MemoryBuffer.h"86#include "llvm/Support/SaveAndRestore.h"87#include "llvm/Support/Timer.h"88#include "llvm/Support/VirtualFileSystem.h"89#include "llvm/Support/raw_ostream.h"90#include <algorithm>91#include <atomic>92#include <cassert>93#include <cstdint>94#include <cstdio>95#include <cstdlib>96#include <memory>97#include <mutex>98#include <optional>99#include <string>100#include <tuple>101#include <utility>102#include <vector>103104using namespace clang;105106using llvm::TimeRecord;107108namespace {109110class SimpleTimer {111bool WantTiming;112TimeRecord Start;113std::string Output;114115public:116explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {117if (WantTiming)118Start = TimeRecord::getCurrentTime();119}120121~SimpleTimer() {122if (WantTiming) {123TimeRecord Elapsed = TimeRecord::getCurrentTime();124Elapsed -= Start;125llvm::errs() << Output << ':';126Elapsed.print(Elapsed, llvm::errs());127llvm::errs() << '\n';128}129}130131void setOutput(const Twine &Output) {132if (WantTiming)133this->Output = Output.str();134}135};136137} // namespace138139template <class T>140static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {141if (!Val)142return nullptr;143return std::move(*Val);144}145146template <class T>147static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {148if (!Val)149return false;150Output = std::move(*Val);151return true;152}153154/// Get a source buffer for \p MainFilePath, handling all file-to-file155/// and file-to-buffer remappings inside \p Invocation.156static std::unique_ptr<llvm::MemoryBuffer>157getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,158llvm::vfs::FileSystem *VFS,159StringRef FilePath, bool isVolatile) {160const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();161162// Try to determine if the main file has been remapped, either from the163// command line (to another file) or directly through the compiler164// invocation (to a memory buffer).165llvm::MemoryBuffer *Buffer = nullptr;166std::unique_ptr<llvm::MemoryBuffer> BufferOwner;167auto FileStatus = VFS->status(FilePath);168if (FileStatus) {169llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID();170171// Check whether there is a file-file remapping of the main file172for (const auto &RF : PreprocessorOpts.RemappedFiles) {173std::string MPath(RF.first);174auto MPathStatus = VFS->status(MPath);175if (MPathStatus) {176llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();177if (MainFileID == MID) {178// We found a remapping. Try to load the resulting, remapped source.179BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));180if (!BufferOwner)181return nullptr;182}183}184}185186// Check whether there is a file-buffer remapping. It supercedes the187// file-file remapping.188for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {189std::string MPath(RB.first);190auto MPathStatus = VFS->status(MPath);191if (MPathStatus) {192llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();193if (MainFileID == MID) {194// We found a remapping.195BufferOwner.reset();196Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);197}198}199}200}201202// If the main source file was not remapped, load it now.203if (!Buffer && !BufferOwner) {204BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));205if (!BufferOwner)206return nullptr;207}208209if (BufferOwner)210return BufferOwner;211if (!Buffer)212return nullptr;213return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);214}215216struct ASTUnit::ASTWriterData {217SmallString<128> Buffer;218llvm::BitstreamWriter Stream;219ASTWriter Writer;220221ASTWriterData(InMemoryModuleCache &ModuleCache)222: Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {}223};224225void ASTUnit::clearFileLevelDecls() {226FileDecls.clear();227}228229/// After failing to build a precompiled preamble (due to230/// errors in the source that occurs in the preamble), the number of231/// reparses during which we'll skip even trying to precompile the232/// preamble.233const unsigned DefaultPreambleRebuildInterval = 5;234235/// Tracks the number of ASTUnit objects that are currently active.236///237/// Used for debugging purposes only.238static std::atomic<unsigned> ActiveASTUnitObjects;239240ASTUnit::ASTUnit(bool _MainFileIsAST)241: MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),242ShouldCacheCodeCompletionResults(false),243IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),244UnsafeToFree(false) {245if (getenv("LIBCLANG_OBJTRACKING"))246fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);247}248249ASTUnit::~ASTUnit() {250// If we loaded from an AST file, balance out the BeginSourceFile call.251if (MainFileIsAST && getDiagnostics().getClient()) {252getDiagnostics().getClient()->EndSourceFile();253}254255clearFileLevelDecls();256257// Free the buffers associated with remapped files. We are required to258// perform this operation here because we explicitly request that the259// compiler instance *not* free these buffers for each invocation of the260// parser.261if (Invocation && OwnsRemappedFileBuffers) {262PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();263for (const auto &RB : PPOpts.RemappedFileBuffers)264delete RB.second;265}266267ClearCachedCompletionResults();268269if (getenv("LIBCLANG_OBJTRACKING"))270fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);271}272273void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {274this->PP = std::move(PP);275}276277void ASTUnit::enableSourceFileDiagnostics() {278assert(getDiagnostics().getClient() && Ctx &&279"Bad context for source file");280getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());281}282283/// Determine the set of code-completion contexts in which this284/// declaration should be shown.285static uint64_t getDeclShowContexts(const NamedDecl *ND,286const LangOptions &LangOpts,287bool &IsNestedNameSpecifier) {288IsNestedNameSpecifier = false;289290if (isa<UsingShadowDecl>(ND))291ND = ND->getUnderlyingDecl();292if (!ND)293return 0;294295uint64_t Contexts = 0;296if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||297isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||298isa<TypeAliasTemplateDecl>(ND)) {299// Types can appear in these contexts.300if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))301Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)302| (1LL << CodeCompletionContext::CCC_ObjCIvarList)303| (1LL << CodeCompletionContext::CCC_ClassStructUnion)304| (1LL << CodeCompletionContext::CCC_Statement)305| (1LL << CodeCompletionContext::CCC_Type)306| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);307308// In C++, types can appear in expressions contexts (for functional casts).309if (LangOpts.CPlusPlus)310Contexts |= (1LL << CodeCompletionContext::CCC_Expression);311312// In Objective-C, message sends can send interfaces. In Objective-C++,313// all types are available due to functional casts.314if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))315Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);316317// In Objective-C, you can only be a subclass of another Objective-C class318if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {319// Objective-C interfaces can be used in a class property expression.320if (ID->getDefinition())321Contexts |= (1LL << CodeCompletionContext::CCC_Expression);322Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);323Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);324}325326// Deal with tag names.327if (isa<EnumDecl>(ND)) {328Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);329330// Part of the nested-name-specifier in C++0x.331if (LangOpts.CPlusPlus11)332IsNestedNameSpecifier = true;333} else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {334if (Record->isUnion())335Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);336else337Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);338339if (LangOpts.CPlusPlus)340IsNestedNameSpecifier = true;341} else if (isa<ClassTemplateDecl>(ND))342IsNestedNameSpecifier = true;343} else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {344// Values can appear in these contexts.345Contexts = (1LL << CodeCompletionContext::CCC_Statement)346| (1LL << CodeCompletionContext::CCC_Expression)347| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)348| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);349} else if (isa<ObjCProtocolDecl>(ND)) {350Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);351} else if (isa<ObjCCategoryDecl>(ND)) {352Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);353} else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {354Contexts = (1LL << CodeCompletionContext::CCC_Namespace);355356// Part of the nested-name-specifier.357IsNestedNameSpecifier = true;358}359360return Contexts;361}362363void ASTUnit::CacheCodeCompletionResults() {364if (!TheSema)365return;366367SimpleTimer Timer(WantTiming);368Timer.setOutput("Cache global code completions for " + getMainFileName());369370// Clear out the previous results.371ClearCachedCompletionResults();372373// Gather the set of global code completions.374using Result = CodeCompletionResult;375SmallVector<Result, 8> Results;376CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();377CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);378TheSema->CodeCompletion().GatherGlobalCodeCompletions(379*CachedCompletionAllocator, CCTUInfo, Results);380381// Translate global code completions into cached completions.382llvm::DenseMap<CanQualType, unsigned> CompletionTypes;383CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);384385for (auto &R : Results) {386switch (R.Kind) {387case Result::RK_Declaration: {388bool IsNestedNameSpecifier = false;389CachedCodeCompletionResult CachedResult;390CachedResult.Completion = R.CreateCodeCompletionString(391*TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,392IncludeBriefCommentsInCodeCompletion);393CachedResult.ShowInContexts = getDeclShowContexts(394R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);395CachedResult.Priority = R.Priority;396CachedResult.Kind = R.CursorKind;397CachedResult.Availability = R.Availability;398399// Keep track of the type of this completion in an ASTContext-agnostic400// way.401QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);402if (UsageType.isNull()) {403CachedResult.TypeClass = STC_Void;404CachedResult.Type = 0;405} else {406CanQualType CanUsageType407= Ctx->getCanonicalType(UsageType.getUnqualifiedType());408CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);409410// Determine whether we have already seen this type. If so, we save411// ourselves the work of formatting the type string by using the412// temporary, CanQualType-based hash table to find the associated value.413unsigned &TypeValue = CompletionTypes[CanUsageType];414if (TypeValue == 0) {415TypeValue = CompletionTypes.size();416CachedCompletionTypes[QualType(CanUsageType).getAsString()]417= TypeValue;418}419420CachedResult.Type = TypeValue;421}422423CachedCompletionResults.push_back(CachedResult);424425/// Handle nested-name-specifiers in C++.426if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&427!R.StartsNestedNameSpecifier) {428// The contexts in which a nested-name-specifier can appear in C++.429uint64_t NNSContexts430= (1LL << CodeCompletionContext::CCC_TopLevel)431| (1LL << CodeCompletionContext::CCC_ObjCIvarList)432| (1LL << CodeCompletionContext::CCC_ClassStructUnion)433| (1LL << CodeCompletionContext::CCC_Statement)434| (1LL << CodeCompletionContext::CCC_Expression)435| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)436| (1LL << CodeCompletionContext::CCC_EnumTag)437| (1LL << CodeCompletionContext::CCC_UnionTag)438| (1LL << CodeCompletionContext::CCC_ClassOrStructTag)439| (1LL << CodeCompletionContext::CCC_Type)440| (1LL << CodeCompletionContext::CCC_SymbolOrNewName)441| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);442443if (isa<NamespaceDecl>(R.Declaration) ||444isa<NamespaceAliasDecl>(R.Declaration))445NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);446447if (uint64_t RemainingContexts448= NNSContexts & ~CachedResult.ShowInContexts) {449// If there any contexts where this completion can be a450// nested-name-specifier but isn't already an option, create a451// nested-name-specifier completion.452R.StartsNestedNameSpecifier = true;453CachedResult.Completion = R.CreateCodeCompletionString(454*TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,455IncludeBriefCommentsInCodeCompletion);456CachedResult.ShowInContexts = RemainingContexts;457CachedResult.Priority = CCP_NestedNameSpecifier;458CachedResult.TypeClass = STC_Void;459CachedResult.Type = 0;460CachedCompletionResults.push_back(CachedResult);461}462}463break;464}465466case Result::RK_Keyword:467case Result::RK_Pattern:468// Ignore keywords and patterns; we don't care, since they are so469// easily regenerated.470break;471472case Result::RK_Macro: {473CachedCodeCompletionResult CachedResult;474CachedResult.Completion = R.CreateCodeCompletionString(475*TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,476IncludeBriefCommentsInCodeCompletion);477CachedResult.ShowInContexts478= (1LL << CodeCompletionContext::CCC_TopLevel)479| (1LL << CodeCompletionContext::CCC_ObjCInterface)480| (1LL << CodeCompletionContext::CCC_ObjCImplementation)481| (1LL << CodeCompletionContext::CCC_ObjCIvarList)482| (1LL << CodeCompletionContext::CCC_ClassStructUnion)483| (1LL << CodeCompletionContext::CCC_Statement)484| (1LL << CodeCompletionContext::CCC_Expression)485| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)486| (1LL << CodeCompletionContext::CCC_MacroNameUse)487| (1LL << CodeCompletionContext::CCC_PreprocessorExpression)488| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)489| (1LL << CodeCompletionContext::CCC_OtherWithMacros);490491CachedResult.Priority = R.Priority;492CachedResult.Kind = R.CursorKind;493CachedResult.Availability = R.Availability;494CachedResult.TypeClass = STC_Void;495CachedResult.Type = 0;496CachedCompletionResults.push_back(CachedResult);497break;498}499}500}501502// Save the current top-level hash value.503CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;504}505506void ASTUnit::ClearCachedCompletionResults() {507CachedCompletionResults.clear();508CachedCompletionTypes.clear();509CachedCompletionAllocator = nullptr;510}511512namespace {513514/// Gathers information from ASTReader that will be used to initialize515/// a Preprocessor.516class ASTInfoCollector : public ASTReaderListener {517Preprocessor &PP;518ASTContext *Context;519HeaderSearchOptions &HSOpts;520PreprocessorOptions &PPOpts;521LangOptions &LangOpt;522std::shared_ptr<TargetOptions> &TargetOpts;523IntrusiveRefCntPtr<TargetInfo> &Target;524unsigned &Counter;525bool InitializedLanguage = false;526bool InitializedHeaderSearchPaths = false;527528public:529ASTInfoCollector(Preprocessor &PP, ASTContext *Context,530HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,531LangOptions &LangOpt,532std::shared_ptr<TargetOptions> &TargetOpts,533IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)534: PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),535LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),536Counter(Counter) {}537538bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,539bool AllowCompatibleDifferences) override {540if (InitializedLanguage)541return false;542543// FIXME: We did similar things in ReadHeaderSearchOptions too. But such544// style is not scaling. Probably we need to invite some mechanism to545// handle such patterns generally.546auto PICLevel = LangOpt.PICLevel;547auto PIE = LangOpt.PIE;548549LangOpt = LangOpts;550551LangOpt.PICLevel = PICLevel;552LangOpt.PIE = PIE;553554InitializedLanguage = true;555556updated();557return false;558}559560bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,561StringRef SpecificModuleCachePath,562bool Complain) override {563// llvm::SaveAndRestore doesn't support bit field.564auto ForceCheckCXX20ModulesInputFiles =565this->HSOpts.ForceCheckCXX20ModulesInputFiles;566llvm::SaveAndRestore X(this->HSOpts.UserEntries);567llvm::SaveAndRestore Y(this->HSOpts.SystemHeaderPrefixes);568llvm::SaveAndRestore Z(this->HSOpts.VFSOverlayFiles);569570this->HSOpts = HSOpts;571this->HSOpts.ForceCheckCXX20ModulesInputFiles =572ForceCheckCXX20ModulesInputFiles;573574return false;575}576577bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,578bool Complain) override {579if (InitializedHeaderSearchPaths)580return false;581582this->HSOpts.UserEntries = HSOpts.UserEntries;583this->HSOpts.SystemHeaderPrefixes = HSOpts.SystemHeaderPrefixes;584this->HSOpts.VFSOverlayFiles = HSOpts.VFSOverlayFiles;585586// Initialize the FileManager. We can't do this in update(), since that587// performs the initialization too late (once both target and language588// options are read).589PP.getFileManager().setVirtualFileSystem(createVFSFromOverlayFiles(590HSOpts.VFSOverlayFiles, PP.getDiagnostics(),591PP.getFileManager().getVirtualFileSystemPtr()));592593InitializedHeaderSearchPaths = true;594595return false;596}597598bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,599bool ReadMacros, bool Complain,600std::string &SuggestedPredefines) override {601this->PPOpts = PPOpts;602return false;603}604605bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,606bool AllowCompatibleDifferences) override {607// If we've already initialized the target, don't do it again.608if (Target)609return false;610611this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);612Target =613TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts);614615updated();616return false;617}618619void ReadCounter(const serialization::ModuleFile &M,620unsigned Value) override {621Counter = Value;622}623624private:625void updated() {626if (!Target || !InitializedLanguage)627return;628629// Inform the target of the language options.630//631// FIXME: We shouldn't need to do this, the target should be immutable once632// created. This complexity should be lifted elsewhere.633Target->adjust(PP.getDiagnostics(), LangOpt);634635// Initialize the preprocessor.636PP.Initialize(*Target);637638if (!Context)639return;640641// Initialize the ASTContext642Context->InitBuiltinTypes(*Target);643644// Adjust printing policy based on language options.645Context->setPrintingPolicy(PrintingPolicy(LangOpt));646647// We didn't have access to the comment options when the ASTContext was648// constructed, so register them now.649Context->getCommentCommandTraits().registerCommentOptions(650LangOpt.CommentOpts);651}652};653654/// Diagnostic consumer that saves each diagnostic it is given.655class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {656SmallVectorImpl<StoredDiagnostic> *StoredDiags;657SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;658bool CaptureNonErrorsFromIncludes = true;659const LangOptions *LangOpts = nullptr;660SourceManager *SourceMgr = nullptr;661662public:663FilterAndStoreDiagnosticConsumer(664SmallVectorImpl<StoredDiagnostic> *StoredDiags,665SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags,666bool CaptureNonErrorsFromIncludes)667: StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),668CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {669assert((StoredDiags || StandaloneDiags) &&670"No output collections were passed to StoredDiagnosticConsumer.");671}672673void BeginSourceFile(const LangOptions &LangOpts,674const Preprocessor *PP = nullptr) override {675this->LangOpts = &LangOpts;676if (PP)677SourceMgr = &PP->getSourceManager();678}679680void HandleDiagnostic(DiagnosticsEngine::Level Level,681const Diagnostic &Info) override;682};683684/// RAII object that optionally captures and filters diagnostics, if685/// there is no diagnostic client to capture them already.686class CaptureDroppedDiagnostics {687DiagnosticsEngine &Diags;688FilterAndStoreDiagnosticConsumer Client;689DiagnosticConsumer *PreviousClient = nullptr;690std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;691692public:693CaptureDroppedDiagnostics(694CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,695SmallVectorImpl<StoredDiagnostic> *StoredDiags,696SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)697: Diags(Diags),698Client(StoredDiags, StandaloneDiags,699CaptureDiagnostics !=700CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {701if (CaptureDiagnostics != CaptureDiagsKind::None ||702Diags.getClient() == nullptr) {703OwningPreviousClient = Diags.takeClient();704PreviousClient = Diags.getClient();705Diags.setClient(&Client, false);706}707}708709~CaptureDroppedDiagnostics() {710if (Diags.getClient() == &Client)711Diags.setClient(PreviousClient, !!OwningPreviousClient.release());712}713};714715} // namespace716717static ASTUnit::StandaloneDiagnostic718makeStandaloneDiagnostic(const LangOptions &LangOpts,719const StoredDiagnostic &InDiag);720721static bool isInMainFile(const clang::Diagnostic &D) {722if (!D.hasSourceManager() || !D.getLocation().isValid())723return false;724725auto &M = D.getSourceManager();726return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation()));727}728729void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(730DiagnosticsEngine::Level Level, const Diagnostic &Info) {731// Default implementation (Warnings/errors count).732DiagnosticConsumer::HandleDiagnostic(Level, Info);733734// Only record the diagnostic if it's part of the source manager we know735// about. This effectively drops diagnostics from modules we're building.736// FIXME: In the long run, ee don't want to drop source managers from modules.737if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) {738if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning &&739!isInMainFile(Info)) {740return;741}742743StoredDiagnostic *ResultDiag = nullptr;744if (StoredDiags) {745StoredDiags->emplace_back(Level, Info);746ResultDiag = &StoredDiags->back();747}748749if (StandaloneDiags) {750std::optional<StoredDiagnostic> StoredDiag;751if (!ResultDiag) {752StoredDiag.emplace(Level, Info);753ResultDiag = &*StoredDiag;754}755StandaloneDiags->push_back(756makeStandaloneDiagnostic(*LangOpts, *ResultDiag));757}758}759}760761IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {762return Reader;763}764765ASTMutationListener *ASTUnit::getASTMutationListener() {766if (WriterData)767return &WriterData->Writer;768return nullptr;769}770771ASTDeserializationListener *ASTUnit::getDeserializationListener() {772if (WriterData)773return &WriterData->Writer;774return nullptr;775}776777std::unique_ptr<llvm::MemoryBuffer>778ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {779assert(FileMgr);780auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);781if (Buffer)782return std::move(*Buffer);783if (ErrorStr)784*ErrorStr = Buffer.getError().message();785return nullptr;786}787788/// Configure the diagnostics object for use with ASTUnit.789void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,790ASTUnit &AST,791CaptureDiagsKind CaptureDiagnostics) {792assert(Diags.get() && "no DiagnosticsEngine was provided");793if (CaptureDiagnostics != CaptureDiagsKind::None)794Diags->setClient(new FilterAndStoreDiagnosticConsumer(795&AST.StoredDiagnostics, nullptr,796CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes));797}798799std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(800const std::string &Filename, const PCHContainerReader &PCHContainerRdr,801WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,802const FileSystemOptions &FileSystemOpts,803std::shared_ptr<HeaderSearchOptions> HSOpts,804std::shared_ptr<LangOptions> LangOpts, bool OnlyLocalDecls,805CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,806bool UserFilesAreVolatile, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {807std::unique_ptr<ASTUnit> AST(new ASTUnit(true));808809// Recover resources if we crash before exiting this method.810llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>811ASTUnitCleanup(AST.get());812llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,813llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>814DiagCleanup(Diags.get());815816ConfigureDiags(Diags, *AST, CaptureDiagnostics);817818AST->LangOpts = LangOpts ? LangOpts : std::make_shared<LangOptions>();819AST->OnlyLocalDecls = OnlyLocalDecls;820AST->CaptureDiagnostics = CaptureDiagnostics;821AST->Diagnostics = Diags;822AST->FileMgr = new FileManager(FileSystemOpts, VFS);823AST->UserFilesAreVolatile = UserFilesAreVolatile;824AST->SourceMgr = new SourceManager(AST->getDiagnostics(),825AST->getFileManager(),826UserFilesAreVolatile);827AST->ModuleCache = new InMemoryModuleCache;828AST->HSOpts = HSOpts ? HSOpts : std::make_shared<HeaderSearchOptions>();829AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front());830AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,831AST->getSourceManager(),832AST->getDiagnostics(),833AST->getLangOpts(),834/*Target=*/nullptr));835AST->PPOpts = std::make_shared<PreprocessorOptions>();836837// Gather Info for preprocessor construction later on.838839HeaderSearch &HeaderInfo = *AST->HeaderInfo;840841AST->PP = std::make_shared<Preprocessor>(842AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts,843AST->getSourceManager(), HeaderInfo, AST->ModuleLoader,844/*IILookup=*/nullptr,845/*OwnsHeaderSearch=*/false);846Preprocessor &PP = *AST->PP;847848if (ToLoad >= LoadASTOnly)849AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),850PP.getIdentifierTable(), PP.getSelectorTable(),851PP.getBuiltinInfo(),852AST->getTranslationUnitKind());853854DisableValidationForModuleKind disableValid =855DisableValidationForModuleKind::None;856if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))857disableValid = DisableValidationForModuleKind::All;858AST->Reader = new ASTReader(859PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},860/*isysroot=*/"",861/*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);862863unsigned Counter = 0;864AST->Reader->setListener(std::make_unique<ASTInfoCollector>(865*AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,866AST->TargetOpts, AST->Target, Counter));867868// Attach the AST reader to the AST context as an external AST869// source, so that declarations will be deserialized from the870// AST file as needed.871// We need the external source to be set up before we read the AST, because872// eagerly-deserialized declarations may use it.873if (AST->Ctx)874AST->Ctx->setExternalSource(AST->Reader);875876switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,877SourceLocation(), ASTReader::ARR_None)) {878case ASTReader::Success:879break;880881case ASTReader::Failure:882case ASTReader::Missing:883case ASTReader::OutOfDate:884case ASTReader::VersionMismatch:885case ASTReader::ConfigurationMismatch:886case ASTReader::HadErrors:887AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);888return nullptr;889}890891AST->OriginalSourceFile = std::string(AST->Reader->getOriginalSourceFile());892893PP.setCounterValue(Counter);894895Module *M = HeaderInfo.lookupModule(AST->getLangOpts().CurrentModule);896if (M && AST->getLangOpts().isCompilingModule() && M->isNamedModule())897AST->Ctx->setCurrentNamedModule(M);898899// Create an AST consumer, even though it isn't used.900if (ToLoad >= LoadASTOnly)901AST->Consumer.reset(new ASTConsumer);902903// Create a semantic analysis object and tell the AST reader about it.904if (ToLoad >= LoadEverything) {905AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer));906AST->TheSema->Initialize();907AST->Reader->InitializeSema(*AST->TheSema);908}909910// Tell the diagnostic client that we have started a source file.911AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP);912913return AST;914}915916/// Add the given macro to the hash of all top-level entities.917static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {918Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);919}920921namespace {922923/// Preprocessor callback class that updates a hash value with the names924/// of all macros that have been defined by the translation unit.925class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {926unsigned &Hash;927928public:929explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}930931void MacroDefined(const Token &MacroNameTok,932const MacroDirective *MD) override {933AddDefinedMacroToHash(MacroNameTok, Hash);934}935};936937} // namespace938939/// Add the given declaration to the hash of all top-level entities.940static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {941if (!D)942return;943944DeclContext *DC = D->getDeclContext();945if (!DC)946return;947948if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))949return;950951if (const auto *ND = dyn_cast<NamedDecl>(D)) {952if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {953// For an unscoped enum include the enumerators in the hash since they954// enter the top-level namespace.955if (!EnumD->isScoped()) {956for (const auto *EI : EnumD->enumerators()) {957if (EI->getIdentifier())958Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);959}960}961}962963if (ND->getIdentifier())964Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);965else if (DeclarationName Name = ND->getDeclName()) {966std::string NameStr = Name.getAsString();967Hash = llvm::djbHash(NameStr, Hash);968}969return;970}971972if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {973if (const Module *Mod = ImportD->getImportedModule()) {974std::string ModName = Mod->getFullModuleName();975Hash = llvm::djbHash(ModName, Hash);976}977return;978}979}980981namespace {982983class TopLevelDeclTrackerConsumer : public ASTConsumer {984ASTUnit &Unit;985unsigned &Hash;986987public:988TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)989: Unit(_Unit), Hash(Hash) {990Hash = 0;991}992993void handleTopLevelDecl(Decl *D) {994if (!D)995return;996997// FIXME: Currently ObjC method declarations are incorrectly being998// reported as top-level declarations, even though their DeclContext999// is the containing ObjC @interface/@implementation. This is a1000// fundamental problem in the parser right now.1001if (isa<ObjCMethodDecl>(D))1002return;10031004AddTopLevelDeclarationToHash(D, Hash);1005Unit.addTopLevelDecl(D);10061007handleFileLevelDecl(D);1008}10091010void handleFileLevelDecl(Decl *D) {1011Unit.addFileLevelDecl(D);1012if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {1013for (auto *I : NSD->decls())1014handleFileLevelDecl(I);1015}1016}10171018bool HandleTopLevelDecl(DeclGroupRef D) override {1019for (auto *TopLevelDecl : D)1020handleTopLevelDecl(TopLevelDecl);1021return true;1022}10231024// We're not interested in "interesting" decls.1025void HandleInterestingDecl(DeclGroupRef) override {}10261027void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {1028for (auto *TopLevelDecl : D)1029handleTopLevelDecl(TopLevelDecl);1030}10311032ASTMutationListener *GetASTMutationListener() override {1033return Unit.getASTMutationListener();1034}10351036ASTDeserializationListener *GetASTDeserializationListener() override {1037return Unit.getDeserializationListener();1038}1039};10401041class TopLevelDeclTrackerAction : public ASTFrontendAction {1042public:1043ASTUnit &Unit;10441045std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,1046StringRef InFile) override {1047CI.getPreprocessor().addPPCallbacks(1048std::make_unique<MacroDefinitionTrackerPPCallbacks>(1049Unit.getCurrentTopLevelHashValue()));1050return std::make_unique<TopLevelDeclTrackerConsumer>(1051Unit, Unit.getCurrentTopLevelHashValue());1052}10531054public:1055TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}10561057bool hasCodeCompletionSupport() const override { return false; }10581059TranslationUnitKind getTranslationUnitKind() override {1060return Unit.getTranslationUnitKind();1061}1062};10631064class ASTUnitPreambleCallbacks : public PreambleCallbacks {1065public:1066unsigned getHash() const { return Hash; }10671068std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }10691070std::vector<LocalDeclID> takeTopLevelDeclIDs() {1071return std::move(TopLevelDeclIDs);1072}10731074void AfterPCHEmitted(ASTWriter &Writer) override {1075TopLevelDeclIDs.reserve(TopLevelDecls.size());1076for (const auto *D : TopLevelDecls) {1077// Invalid top-level decls may not have been serialized.1078if (D->isInvalidDecl())1079continue;1080TopLevelDeclIDs.push_back(Writer.getDeclID(D));1081}1082}10831084void HandleTopLevelDecl(DeclGroupRef DG) override {1085for (auto *D : DG) {1086// FIXME: Currently ObjC method declarations are incorrectly being1087// reported as top-level declarations, even though their DeclContext1088// is the containing ObjC @interface/@implementation. This is a1089// fundamental problem in the parser right now.1090if (isa<ObjCMethodDecl>(D))1091continue;1092AddTopLevelDeclarationToHash(D, Hash);1093TopLevelDecls.push_back(D);1094}1095}10961097std::unique_ptr<PPCallbacks> createPPCallbacks() override {1098return std::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash);1099}11001101private:1102unsigned Hash = 0;1103std::vector<Decl *> TopLevelDecls;1104std::vector<LocalDeclID> TopLevelDeclIDs;1105llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;1106};11071108} // namespace11091110static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {1111return StoredDiag.getLocation().isValid();1112}11131114static void1115checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {1116// Get rid of stored diagnostics except the ones from the driver which do not1117// have a source location.1118llvm::erase_if(StoredDiags, isNonDriverDiag);1119}11201121static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &1122StoredDiagnostics,1123SourceManager &SM) {1124// The stored diagnostic has the old source manager in it; update1125// the locations to refer into the new source manager. Since we've1126// been careful to make sure that the source manager's state1127// before and after are identical, so that we can reuse the source1128// location itself.1129for (auto &SD : StoredDiagnostics) {1130if (SD.getLocation().isValid()) {1131FullSourceLoc Loc(SD.getLocation(), SM);1132SD.setLocation(Loc);1133}1134}1135}11361137/// Parse the source file into a translation unit using the given compiler1138/// invocation, replacing the current translation unit.1139///1140/// \returns True if a failure occurred that causes the ASTUnit not to1141/// contain any translation-unit information, false otherwise.1142bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,1143std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,1144IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1145if (!Invocation)1146return true;11471148if (VFS && FileMgr)1149assert(VFS == &FileMgr->getVirtualFileSystem() &&1150"VFS passed to Parse and VFS in FileMgr are different");11511152auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);1153if (OverrideMainBuffer) {1154assert(Preamble &&1155"No preamble was built, but OverrideMainBuffer is not null");1156Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());1157// VFS may have changed...1158}11591160// Create the compiler instance to use for building the AST.1161std::unique_ptr<CompilerInstance> Clang(1162new CompilerInstance(std::move(PCHContainerOps)));1163Clang->setInvocation(CCInvocation);11641165// Clean up on error, disengage it if the function returns successfully.1166auto CleanOnError = llvm::make_scope_exit([&]() {1167// Remove the overridden buffer we used for the preamble.1168SavedMainFileBuffer = nullptr;11691170// Keep the ownership of the data in the ASTUnit because the client may1171// want to see the diagnostics.1172transferASTDataFromCompilerInstance(*Clang);1173FailedParseDiagnostics.swap(StoredDiagnostics);1174StoredDiagnostics.clear();1175NumStoredDiagnosticsFromDriver = 0;1176});11771178// Ensure that Clang has a FileManager with the right VFS, which may have1179// changed above in AddImplicitPreamble. If VFS is nullptr, rely on1180// createFileManager to create one.1181if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS)1182Clang->setFileManager(&*FileMgr);1183else1184FileMgr = Clang->createFileManager(std::move(VFS));11851186// Recover resources if we crash before exiting this method.1187llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>1188CICleanup(Clang.get());11891190OriginalSourceFile =1191std::string(Clang->getFrontendOpts().Inputs[0].getFile());11921193// Set up diagnostics, capturing any diagnostics that would1194// otherwise be dropped.1195Clang->setDiagnostics(&getDiagnostics());11961197// Create the target instance.1198if (!Clang->createTarget())1199return true;12001201assert(Clang->getFrontendOpts().Inputs.size() == 1 &&1202"Invocation must have exactly one source file!");1203assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==1204InputKind::Source &&1205"FIXME: AST inputs not yet supported here!");1206assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=1207Language::LLVM_IR &&1208"IR inputs not support here!");12091210// Configure the various subsystems.1211LangOpts = Clang->getInvocation().LangOpts;1212FileSystemOpts = Clang->getFileSystemOpts();12131214ResetForParse();12151216SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,1217UserFilesAreVolatile);1218if (!OverrideMainBuffer) {1219checkAndRemoveNonDriverDiags(StoredDiagnostics);1220TopLevelDeclsInPreamble.clear();1221}12221223// Create the source manager.1224Clang->setSourceManager(&getSourceManager());12251226// If the main file has been overridden due to the use of a preamble,1227// make that override happen and introduce the preamble.1228if (OverrideMainBuffer) {1229// The stored diagnostic has the old source manager in it; update1230// the locations to refer into the new source manager. Since we've1231// been careful to make sure that the source manager's state1232// before and after are identical, so that we can reuse the source1233// location itself.1234checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());12351236// Keep track of the override buffer;1237SavedMainFileBuffer = std::move(OverrideMainBuffer);1238}12391240std::unique_ptr<TopLevelDeclTrackerAction> Act(1241new TopLevelDeclTrackerAction(*this));12421243// Recover resources if we crash before exiting this method.1244llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>1245ActCleanup(Act.get());12461247if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))1248return true;12491250if (SavedMainFileBuffer)1251TranslateStoredDiagnostics(getFileManager(), getSourceManager(),1252PreambleDiagnostics, StoredDiagnostics);1253else1254PreambleSrcLocCache.clear();12551256if (llvm::Error Err = Act->Execute()) {1257consumeError(std::move(Err)); // FIXME this drops errors on the floor.1258return true;1259}12601261transferASTDataFromCompilerInstance(*Clang);12621263Act->EndSourceFile();12641265FailedParseDiagnostics.clear();12661267CleanOnError.release();12681269return false;1270}12711272static std::pair<unsigned, unsigned>1273makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,1274const LangOptions &LangOpts) {1275CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts);1276unsigned Offset = SM.getFileOffset(FileRange.getBegin());1277unsigned EndOffset = SM.getFileOffset(FileRange.getEnd());1278return std::make_pair(Offset, EndOffset);1279}12801281static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,1282const LangOptions &LangOpts,1283const FixItHint &InFix) {1284ASTUnit::StandaloneFixIt OutFix;1285OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);1286OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM,1287LangOpts);1288OutFix.CodeToInsert = InFix.CodeToInsert;1289OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;1290return OutFix;1291}12921293static ASTUnit::StandaloneDiagnostic1294makeStandaloneDiagnostic(const LangOptions &LangOpts,1295const StoredDiagnostic &InDiag) {1296ASTUnit::StandaloneDiagnostic OutDiag;1297OutDiag.ID = InDiag.getID();1298OutDiag.Level = InDiag.getLevel();1299OutDiag.Message = std::string(InDiag.getMessage());1300OutDiag.LocOffset = 0;1301if (InDiag.getLocation().isInvalid())1302return OutDiag;1303const SourceManager &SM = InDiag.getLocation().getManager();1304SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());1305OutDiag.Filename = std::string(SM.getFilename(FileLoc));1306if (OutDiag.Filename.empty())1307return OutDiag;1308OutDiag.LocOffset = SM.getFileOffset(FileLoc);1309for (const auto &Range : InDiag.getRanges())1310OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));1311for (const auto &FixIt : InDiag.getFixIts())1312OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));13131314return OutDiag;1315}13161317/// Attempt to build or re-use a precompiled preamble when (re-)parsing1318/// the source file.1319///1320/// This routine will compute the preamble of the main source file. If a1321/// non-trivial preamble is found, it will precompile that preamble into a1322/// precompiled header so that the precompiled preamble can be used to reduce1323/// reparsing time. If a precompiled preamble has already been constructed,1324/// this routine will determine if it is still valid and, if so, avoid1325/// rebuilding the precompiled preamble.1326///1327/// \param AllowRebuild When true (the default), this routine is1328/// allowed to rebuild the precompiled preamble if it is found to be1329/// out-of-date.1330///1331/// \param MaxLines When non-zero, the maximum number of lines that1332/// can occur within the preamble.1333///1334/// \returns If the precompiled preamble can be used, returns a newly-allocated1335/// buffer that should be used in place of the main file when doing so.1336/// Otherwise, returns a NULL pointer.1337std::unique_ptr<llvm::MemoryBuffer>1338ASTUnit::getMainBufferWithPrecompiledPreamble(1339std::shared_ptr<PCHContainerOperations> PCHContainerOps,1340CompilerInvocation &PreambleInvocationIn,1341IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,1342unsigned MaxLines) {1343auto MainFilePath =1344PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();1345std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =1346getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),1347MainFilePath, UserFilesAreVolatile);1348if (!MainFileBuffer)1349return nullptr;13501351PreambleBounds Bounds = ComputePreambleBounds(1352PreambleInvocationIn.getLangOpts(), *MainFileBuffer, MaxLines);1353if (!Bounds.Size)1354return nullptr;13551356if (Preamble) {1357if (Preamble->CanReuse(PreambleInvocationIn, *MainFileBuffer, Bounds,1358*VFS)) {1359// Okay! We can re-use the precompiled preamble.13601361// Set the state of the diagnostic object to mimic its state1362// after parsing the preamble.1363getDiagnostics().Reset();1364ProcessWarningOptions(getDiagnostics(),1365PreambleInvocationIn.getDiagnosticOpts());1366getDiagnostics().setNumWarnings(NumWarningsInPreamble);13671368PreambleRebuildCountdown = 1;1369return MainFileBuffer;1370} else {1371Preamble.reset();1372PreambleDiagnostics.clear();1373TopLevelDeclsInPreamble.clear();1374PreambleSrcLocCache.clear();1375PreambleRebuildCountdown = 1;1376}1377}13781379// If the preamble rebuild counter > 1, it's because we previously1380// failed to build a preamble and we're not yet ready to try1381// again. Decrement the counter and return a failure.1382if (PreambleRebuildCountdown > 1) {1383--PreambleRebuildCountdown;1384return nullptr;1385}13861387assert(!Preamble && "No Preamble should be stored at that point");1388// If we aren't allowed to rebuild the precompiled preamble, just1389// return now.1390if (!AllowRebuild)1391return nullptr;13921393++PreambleCounter;13941395SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone;1396SmallVector<StoredDiagnostic, 4> NewPreambleDiags;1397ASTUnitPreambleCallbacks Callbacks;1398{1399std::optional<CaptureDroppedDiagnostics> Capture;1400if (CaptureDiagnostics != CaptureDiagsKind::None)1401Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags,1402&NewPreambleDiagsStandalone);14031404// We did not previously compute a preamble, or it can't be reused anyway.1405SimpleTimer PreambleTimer(WantTiming);1406PreambleTimer.setOutput("Precompiling preamble");14071408const bool PreviousSkipFunctionBodies =1409PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;1410if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)1411PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;14121413llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(1414PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,1415PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath,1416Callbacks);14171418PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =1419PreviousSkipFunctionBodies;14201421if (NewPreamble) {1422Preamble = std::move(*NewPreamble);1423PreambleRebuildCountdown = 1;1424} else {1425switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {1426case BuildPreambleError::CouldntCreateTempFile:1427// Try again next time.1428PreambleRebuildCountdown = 1;1429return nullptr;1430case BuildPreambleError::CouldntCreateTargetInfo:1431case BuildPreambleError::BeginSourceFileFailed:1432case BuildPreambleError::CouldntEmitPCH:1433case BuildPreambleError::BadInputs:1434// These erros are more likely to repeat, retry after some period.1435PreambleRebuildCountdown = DefaultPreambleRebuildInterval;1436return nullptr;1437}1438llvm_unreachable("unexpected BuildPreambleError");1439}1440}14411442assert(Preamble && "Preamble wasn't built");14431444TopLevelDecls.clear();1445TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs();1446PreambleTopLevelHashValue = Callbacks.getHash();14471448NumWarningsInPreamble = getDiagnostics().getNumWarnings();14491450checkAndRemoveNonDriverDiags(NewPreambleDiags);1451StoredDiagnostics = std::move(NewPreambleDiags);1452PreambleDiagnostics = std::move(NewPreambleDiagsStandalone);14531454// If the hash of top-level entities differs from the hash of the top-level1455// entities the last time we rebuilt the preamble, clear out the completion1456// cache.1457if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {1458CompletionCacheTopLevelHashValue = 0;1459PreambleTopLevelHashValue = CurrentTopLevelHashValue;1460}14611462return MainFileBuffer;1463}14641465void ASTUnit::RealizeTopLevelDeclsFromPreamble() {1466assert(Preamble && "Should only be called when preamble was built");14671468std::vector<Decl *> Resolved;1469Resolved.reserve(TopLevelDeclsInPreamble.size());1470// The module file of the preamble.1471serialization::ModuleFile &MF = Reader->getModuleManager().getPrimaryModule();1472for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {1473// Resolve the declaration ID to an actual declaration, possibly1474// deserializing the declaration in the process.1475if (Decl *D = Reader->GetLocalDecl(MF, TopLevelDecl))1476Resolved.push_back(D);1477}1478TopLevelDeclsInPreamble.clear();1479TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());1480}14811482void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {1483// Steal the created target, context, and preprocessor if they have been1484// created.1485assert(CI.hasInvocation() && "missing invocation");1486LangOpts = CI.getInvocation().LangOpts;1487TheSema = CI.takeSema();1488Consumer = CI.takeASTConsumer();1489if (CI.hasASTContext())1490Ctx = &CI.getASTContext();1491if (CI.hasPreprocessor())1492PP = CI.getPreprocessorPtr();1493CI.setSourceManager(nullptr);1494CI.setFileManager(nullptr);1495if (CI.hasTarget())1496Target = &CI.getTarget();1497Reader = CI.getASTReader();1498HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();1499}15001501StringRef ASTUnit::getMainFileName() const {1502if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) {1503const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0];1504if (Input.isFile())1505return Input.getFile();1506else1507return Input.getBuffer().getBufferIdentifier();1508}15091510if (SourceMgr) {1511if (OptionalFileEntryRef FE =1512SourceMgr->getFileEntryRefForID(SourceMgr->getMainFileID()))1513return FE->getName();1514}15151516return {};1517}15181519StringRef ASTUnit::getASTFileName() const {1520if (!isMainFileAST())1521return {};15221523serialization::ModuleFile &1524Mod = Reader->getModuleManager().getPrimaryModule();1525return Mod.FileName;1526}15271528std::unique_ptr<ASTUnit>1529ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,1530IntrusiveRefCntPtr<DiagnosticsEngine> Diags,1531CaptureDiagsKind CaptureDiagnostics,1532bool UserFilesAreVolatile) {1533std::unique_ptr<ASTUnit> AST(new ASTUnit(false));1534ConfigureDiags(Diags, *AST, CaptureDiagnostics);1535IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =1536createVFSFromCompilerInvocation(*CI, *Diags);1537AST->Diagnostics = Diags;1538AST->FileSystemOpts = CI->getFileSystemOpts();1539AST->Invocation = std::move(CI);1540AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);1541AST->UserFilesAreVolatile = UserFilesAreVolatile;1542AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,1543UserFilesAreVolatile);1544AST->ModuleCache = new InMemoryModuleCache;15451546return AST;1547}15481549ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(1550std::shared_ptr<CompilerInvocation> CI,1551std::shared_ptr<PCHContainerOperations> PCHContainerOps,1552IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action,1553ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,1554bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1555unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,1556bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {1557assert(CI && "A CompilerInvocation is required");15581559std::unique_ptr<ASTUnit> OwnAST;1560ASTUnit *AST = Unit;1561if (!AST) {1562// Create the AST unit.1563OwnAST = create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile);1564AST = OwnAST.get();1565if (!AST)1566return nullptr;1567}15681569if (!ResourceFilesPath.empty()) {1570// Override the resources path.1571CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);1572}1573AST->OnlyLocalDecls = OnlyLocalDecls;1574AST->CaptureDiagnostics = CaptureDiagnostics;1575if (PrecompilePreambleAfterNParses > 0)1576AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses;1577AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;1578AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1579AST->IncludeBriefCommentsInCodeCompletion = false;15801581// Recover resources if we crash before exiting this method.1582llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1583ASTUnitCleanup(OwnAST.get());1584llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,1585llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>1586DiagCleanup(Diags.get());15871588// We'll manage file buffers ourselves.1589CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;1590CI->getFrontendOpts().DisableFree = false;1591ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());15921593// Create the compiler instance to use for building the AST.1594std::unique_ptr<CompilerInstance> Clang(1595new CompilerInstance(std::move(PCHContainerOps)));15961597// Recover resources if we crash before exiting this method.1598llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>1599CICleanup(Clang.get());16001601Clang->setInvocation(std::move(CI));1602AST->OriginalSourceFile =1603std::string(Clang->getFrontendOpts().Inputs[0].getFile());16041605// Set up diagnostics, capturing any diagnostics that would1606// otherwise be dropped.1607Clang->setDiagnostics(&AST->getDiagnostics());16081609// Create the target instance.1610if (!Clang->createTarget())1611return nullptr;16121613assert(Clang->getFrontendOpts().Inputs.size() == 1 &&1614"Invocation must have exactly one source file!");1615assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==1616InputKind::Source &&1617"FIXME: AST inputs not yet supported here!");1618assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=1619Language::LLVM_IR &&1620"IR inputs not support here!");16211622// Configure the various subsystems.1623AST->TheSema.reset();1624AST->Ctx = nullptr;1625AST->PP = nullptr;1626AST->Reader = nullptr;16271628// Create a file manager object to provide access to and cache the filesystem.1629Clang->setFileManager(&AST->getFileManager());16301631// Create the source manager.1632Clang->setSourceManager(&AST->getSourceManager());16331634FrontendAction *Act = Action;16351636std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct;1637if (!Act) {1638TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));1639Act = TrackerAct.get();1640}16411642// Recover resources if we crash before exiting this method.1643llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>1644ActCleanup(TrackerAct.get());16451646if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {1647AST->transferASTDataFromCompilerInstance(*Clang);1648if (OwnAST && ErrAST)1649ErrAST->swap(OwnAST);16501651return nullptr;1652}16531654if (Persistent && !TrackerAct) {1655Clang->getPreprocessor().addPPCallbacks(1656std::make_unique<MacroDefinitionTrackerPPCallbacks>(1657AST->getCurrentTopLevelHashValue()));1658std::vector<std::unique_ptr<ASTConsumer>> Consumers;1659if (Clang->hasASTConsumer())1660Consumers.push_back(Clang->takeASTConsumer());1661Consumers.push_back(std::make_unique<TopLevelDeclTrackerConsumer>(1662*AST, AST->getCurrentTopLevelHashValue()));1663Clang->setASTConsumer(1664std::make_unique<MultiplexConsumer>(std::move(Consumers)));1665}1666if (llvm::Error Err = Act->Execute()) {1667consumeError(std::move(Err)); // FIXME this drops errors on the floor.1668AST->transferASTDataFromCompilerInstance(*Clang);1669if (OwnAST && ErrAST)1670ErrAST->swap(OwnAST);16711672return nullptr;1673}16741675// Steal the created target, context, and preprocessor.1676AST->transferASTDataFromCompilerInstance(*Clang);16771678Act->EndSourceFile();16791680if (OwnAST)1681return OwnAST.release();1682else1683return AST;1684}16851686bool ASTUnit::LoadFromCompilerInvocation(1687std::shared_ptr<PCHContainerOperations> PCHContainerOps,1688unsigned PrecompilePreambleAfterNParses,1689IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1690if (!Invocation)1691return true;16921693assert(VFS && "VFS is null");16941695// We'll manage file buffers ourselves.1696Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;1697Invocation->getFrontendOpts().DisableFree = false;1698getDiagnostics().Reset();1699ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());17001701std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;1702if (PrecompilePreambleAfterNParses > 0) {1703PreambleRebuildCountdown = PrecompilePreambleAfterNParses;1704OverrideMainBuffer =1705getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);1706getDiagnostics().Reset();1707ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());1708}17091710SimpleTimer ParsingTimer(WantTiming);1711ParsingTimer.setOutput("Parsing " + getMainFileName());17121713// Recover resources if we crash before exiting this method.1714llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>1715MemBufferCleanup(OverrideMainBuffer.get());17161717return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);1718}17191720std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(1721std::shared_ptr<CompilerInvocation> CI,1722std::shared_ptr<PCHContainerOperations> PCHContainerOps,1723IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,1724bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1725unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,1726bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,1727bool UserFilesAreVolatile) {1728// Create the AST unit.1729std::unique_ptr<ASTUnit> AST(new ASTUnit(false));1730ConfigureDiags(Diags, *AST, CaptureDiagnostics);1731AST->Diagnostics = Diags;1732AST->OnlyLocalDecls = OnlyLocalDecls;1733AST->CaptureDiagnostics = CaptureDiagnostics;1734AST->TUKind = TUKind;1735AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1736AST->IncludeBriefCommentsInCodeCompletion1737= IncludeBriefCommentsInCodeCompletion;1738AST->Invocation = std::move(CI);1739AST->FileSystemOpts = FileMgr->getFileSystemOpts();1740AST->FileMgr = FileMgr;1741AST->UserFilesAreVolatile = UserFilesAreVolatile;17421743// Recover resources if we crash before exiting this method.1744llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1745ASTUnitCleanup(AST.get());1746llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,1747llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>1748DiagCleanup(Diags.get());17491750if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),1751PrecompilePreambleAfterNParses,1752&AST->FileMgr->getVirtualFileSystem()))1753return nullptr;1754return AST;1755}17561757std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(1758const char **ArgBegin, const char **ArgEnd,1759std::shared_ptr<PCHContainerOperations> PCHContainerOps,1760IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,1761bool StorePreamblesInMemory, StringRef PreambleStoragePath,1762bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1763ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,1764unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,1765bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,1766bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,1767bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,1768bool RetainExcludedConditionalBlocks, std::optional<StringRef> ModuleFormat,1769std::unique_ptr<ASTUnit> *ErrAST,1770IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1771assert(Diags.get() && "no DiagnosticsEngine was provided");17721773// If no VFS was provided, create one that tracks the physical file system.1774// If '-working-directory' was passed as an argument, 'createInvocation' will1775// set this as the current working directory of the VFS.1776if (!VFS)1777VFS = llvm::vfs::createPhysicalFileSystem();17781779SmallVector<StoredDiagnostic, 4> StoredDiagnostics;17801781std::shared_ptr<CompilerInvocation> CI;17821783{1784CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,1785&StoredDiagnostics, nullptr);17861787CreateInvocationOptions CIOpts;1788CIOpts.VFS = VFS;1789CIOpts.Diags = Diags;1790CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?1791CI = createInvocation(llvm::ArrayRef(ArgBegin, ArgEnd), std::move(CIOpts));1792if (!CI)1793return nullptr;1794}17951796// Override any files that need remapping1797for (const auto &RemappedFile : RemappedFiles) {1798CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,1799RemappedFile.second);1800}1801PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();1802PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;1803PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;1804PPOpts.SingleFileParseMode = SingleFileParse;1805PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;18061807// Override the resources path.1808CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);18091810CI->getFrontendOpts().SkipFunctionBodies =1811SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;18121813if (ModuleFormat)1814CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat);18151816// Create the AST unit.1817std::unique_ptr<ASTUnit> AST;1818AST.reset(new ASTUnit(false));1819AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();1820AST->StoredDiagnostics.swap(StoredDiagnostics);1821ConfigureDiags(Diags, *AST, CaptureDiagnostics);1822AST->Diagnostics = Diags;1823AST->FileSystemOpts = CI->getFileSystemOpts();1824VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);1825AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);1826AST->StorePreamblesInMemory = StorePreamblesInMemory;1827AST->PreambleStoragePath = PreambleStoragePath;1828AST->ModuleCache = new InMemoryModuleCache;1829AST->OnlyLocalDecls = OnlyLocalDecls;1830AST->CaptureDiagnostics = CaptureDiagnostics;1831AST->TUKind = TUKind;1832AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1833AST->IncludeBriefCommentsInCodeCompletion1834= IncludeBriefCommentsInCodeCompletion;1835AST->UserFilesAreVolatile = UserFilesAreVolatile;1836AST->Invocation = CI;1837AST->SkipFunctionBodies = SkipFunctionBodies;1838if (ForSerialization)1839AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache));1840// Zero out now to ease cleanup during crash recovery.1841CI = nullptr;1842Diags = nullptr;18431844// Recover resources if we crash before exiting this method.1845llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1846ASTUnitCleanup(AST.get());18471848if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),1849PrecompilePreambleAfterNParses,1850VFS)) {1851// Some error occurred, if caller wants to examine diagnostics, pass it the1852// ASTUnit.1853if (ErrAST) {1854AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);1855ErrAST->swap(AST);1856}1857return nullptr;1858}18591860return AST;1861}18621863bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,1864ArrayRef<RemappedFile> RemappedFiles,1865IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1866if (!Invocation)1867return true;18681869if (!VFS) {1870assert(FileMgr && "FileMgr is null on Reparse call");1871VFS = &FileMgr->getVirtualFileSystem();1872}18731874clearFileLevelDecls();18751876SimpleTimer ParsingTimer(WantTiming);1877ParsingTimer.setOutput("Reparsing " + getMainFileName());18781879// Remap files.1880PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();1881for (const auto &RB : PPOpts.RemappedFileBuffers)1882delete RB.second;18831884Invocation->getPreprocessorOpts().clearRemappedFiles();1885for (const auto &RemappedFile : RemappedFiles) {1886Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first,1887RemappedFile.second);1888}18891890// If we have a preamble file lying around, or if we might try to1891// build a precompiled preamble, do so now.1892std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;1893if (Preamble || PreambleRebuildCountdown > 0)1894OverrideMainBuffer =1895getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);18961897// Clear out the diagnostics state.1898FileMgr.reset();1899getDiagnostics().Reset();1900ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());1901if (OverrideMainBuffer)1902getDiagnostics().setNumWarnings(NumWarningsInPreamble);19031904// Parse the sources1905bool Result =1906Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);19071908// If we're caching global code-completion results, and the top-level1909// declarations have changed, clear out the code-completion cache.1910if (!Result && ShouldCacheCodeCompletionResults &&1911CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)1912CacheCodeCompletionResults();19131914// We now need to clear out the completion info related to this translation1915// unit; it'll be recreated if necessary.1916CCTUInfo.reset();19171918return Result;1919}19201921void ASTUnit::ResetForParse() {1922SavedMainFileBuffer.reset();19231924SourceMgr.reset();1925TheSema.reset();1926Ctx.reset();1927PP.reset();1928Reader.reset();19291930TopLevelDecls.clear();1931clearFileLevelDecls();1932}19331934//----------------------------------------------------------------------------//1935// Code completion1936//----------------------------------------------------------------------------//19371938namespace {19391940/// Code completion consumer that combines the cached code-completion1941/// results from an ASTUnit with the code-completion results provided to it,1942/// then passes the result on to1943class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {1944uint64_t NormalContexts;1945ASTUnit &AST;1946CodeCompleteConsumer &Next;19471948public:1949AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,1950const CodeCompleteOptions &CodeCompleteOpts)1951: CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) {1952// Compute the set of contexts in which we will look when we don't have1953// any information about the specific context.1954NormalContexts1955= (1LL << CodeCompletionContext::CCC_TopLevel)1956| (1LL << CodeCompletionContext::CCC_ObjCInterface)1957| (1LL << CodeCompletionContext::CCC_ObjCImplementation)1958| (1LL << CodeCompletionContext::CCC_ObjCIvarList)1959| (1LL << CodeCompletionContext::CCC_Statement)1960| (1LL << CodeCompletionContext::CCC_Expression)1961| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)1962| (1LL << CodeCompletionContext::CCC_DotMemberAccess)1963| (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)1964| (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)1965| (1LL << CodeCompletionContext::CCC_ObjCProtocolName)1966| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)1967| (1LL << CodeCompletionContext::CCC_Recovery);19681969if (AST.getASTContext().getLangOpts().CPlusPlus)1970NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)1971| (1LL << CodeCompletionContext::CCC_UnionTag)1972| (1LL << CodeCompletionContext::CCC_ClassOrStructTag);1973}19741975void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,1976CodeCompletionResult *Results,1977unsigned NumResults) override;19781979void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,1980OverloadCandidate *Candidates,1981unsigned NumCandidates,1982SourceLocation OpenParLoc,1983bool Braced) override {1984Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,1985OpenParLoc, Braced);1986}19871988CodeCompletionAllocator &getAllocator() override {1989return Next.getAllocator();1990}19911992CodeCompletionTUInfo &getCodeCompletionTUInfo() override {1993return Next.getCodeCompletionTUInfo();1994}1995};19961997} // namespace19981999/// Helper function that computes which global names are hidden by the2000/// local code-completion results.2001static void CalculateHiddenNames(const CodeCompletionContext &Context,2002CodeCompletionResult *Results,2003unsigned NumResults,2004ASTContext &Ctx,2005llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){2006bool OnlyTagNames = false;2007switch (Context.getKind()) {2008case CodeCompletionContext::CCC_Recovery:2009case CodeCompletionContext::CCC_TopLevel:2010case CodeCompletionContext::CCC_ObjCInterface:2011case CodeCompletionContext::CCC_ObjCImplementation:2012case CodeCompletionContext::CCC_ObjCIvarList:2013case CodeCompletionContext::CCC_ClassStructUnion:2014case CodeCompletionContext::CCC_Statement:2015case CodeCompletionContext::CCC_Expression:2016case CodeCompletionContext::CCC_ObjCMessageReceiver:2017case CodeCompletionContext::CCC_DotMemberAccess:2018case CodeCompletionContext::CCC_ArrowMemberAccess:2019case CodeCompletionContext::CCC_ObjCPropertyAccess:2020case CodeCompletionContext::CCC_Namespace:2021case CodeCompletionContext::CCC_Type:2022case CodeCompletionContext::CCC_Symbol:2023case CodeCompletionContext::CCC_SymbolOrNewName:2024case CodeCompletionContext::CCC_ParenthesizedExpression:2025case CodeCompletionContext::CCC_ObjCInterfaceName:2026case CodeCompletionContext::CCC_TopLevelOrExpression:2027break;20282029case CodeCompletionContext::CCC_EnumTag:2030case CodeCompletionContext::CCC_UnionTag:2031case CodeCompletionContext::CCC_ClassOrStructTag:2032OnlyTagNames = true;2033break;20342035case CodeCompletionContext::CCC_ObjCProtocolName:2036case CodeCompletionContext::CCC_MacroName:2037case CodeCompletionContext::CCC_MacroNameUse:2038case CodeCompletionContext::CCC_PreprocessorExpression:2039case CodeCompletionContext::CCC_PreprocessorDirective:2040case CodeCompletionContext::CCC_NaturalLanguage:2041case CodeCompletionContext::CCC_SelectorName:2042case CodeCompletionContext::CCC_TypeQualifiers:2043case CodeCompletionContext::CCC_Other:2044case CodeCompletionContext::CCC_OtherWithMacros:2045case CodeCompletionContext::CCC_ObjCInstanceMessage:2046case CodeCompletionContext::CCC_ObjCClassMessage:2047case CodeCompletionContext::CCC_ObjCCategoryName:2048case CodeCompletionContext::CCC_IncludedFile:2049case CodeCompletionContext::CCC_Attribute:2050case CodeCompletionContext::CCC_NewName:2051case CodeCompletionContext::CCC_ObjCClassForwardDecl:2052// We're looking for nothing, or we're looking for names that cannot2053// be hidden.2054return;2055}20562057using Result = CodeCompletionResult;2058for (unsigned I = 0; I != NumResults; ++I) {2059if (Results[I].Kind != Result::RK_Declaration)2060continue;20612062unsigned IDNS2063= Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();20642065bool Hiding = false;2066if (OnlyTagNames)2067Hiding = (IDNS & Decl::IDNS_Tag);2068else {2069unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |2070Decl::IDNS_Namespace | Decl::IDNS_Ordinary |2071Decl::IDNS_NonMemberOperator);2072if (Ctx.getLangOpts().CPlusPlus)2073HiddenIDNS |= Decl::IDNS_Tag;2074Hiding = (IDNS & HiddenIDNS);2075}20762077if (!Hiding)2078continue;20792080DeclarationName Name = Results[I].Declaration->getDeclName();2081if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())2082HiddenNames.insert(Identifier->getName());2083else2084HiddenNames.insert(Name.getAsString());2085}2086}20872088void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,2089CodeCompletionContext Context,2090CodeCompletionResult *Results,2091unsigned NumResults) {2092// Merge the results we were given with the results we cached.2093bool AddedResult = false;2094uint64_t InContexts =2095Context.getKind() == CodeCompletionContext::CCC_Recovery2096? NormalContexts : (1LL << Context.getKind());2097// Contains the set of names that are hidden by "local" completion results.2098llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;2099using Result = CodeCompletionResult;2100SmallVector<Result, 8> AllResults;2101for (ASTUnit::cached_completion_iterator2102C = AST.cached_completion_begin(),2103CEnd = AST.cached_completion_end();2104C != CEnd; ++C) {2105// If the context we are in matches any of the contexts we are2106// interested in, we'll add this result.2107if ((C->ShowInContexts & InContexts) == 0)2108continue;21092110// If we haven't added any results previously, do so now.2111if (!AddedResult) {2112CalculateHiddenNames(Context, Results, NumResults, S.Context,2113HiddenNames);2114AllResults.insert(AllResults.end(), Results, Results + NumResults);2115AddedResult = true;2116}21172118// Determine whether this global completion result is hidden by a local2119// completion result. If so, skip it.2120if (C->Kind != CXCursor_MacroDefinition &&2121HiddenNames.count(C->Completion->getTypedText()))2122continue;21232124// Adjust priority based on similar type classes.2125unsigned Priority = C->Priority;2126CodeCompletionString *Completion = C->Completion;2127if (!Context.getPreferredType().isNull()) {2128if (C->Kind == CXCursor_MacroDefinition) {2129Priority = getMacroUsagePriority(C->Completion->getTypedText(),2130S.getLangOpts(),2131Context.getPreferredType()->isAnyPointerType());2132} else if (C->Type) {2133CanQualType Expected2134= S.Context.getCanonicalType(2135Context.getPreferredType().getUnqualifiedType());2136SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);2137if (ExpectedSTC == C->TypeClass) {2138// We know this type is similar; check for an exact match.2139llvm::StringMap<unsigned> &CachedCompletionTypes2140= AST.getCachedCompletionTypes();2141llvm::StringMap<unsigned>::iterator Pos2142= CachedCompletionTypes.find(QualType(Expected).getAsString());2143if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)2144Priority /= CCF_ExactTypeMatch;2145else2146Priority /= CCF_SimilarTypeMatch;2147}2148}2149}21502151// Adjust the completion string, if required.2152if (C->Kind == CXCursor_MacroDefinition &&2153Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {2154// Create a new code-completion string that just contains the2155// macro name, without its arguments.2156CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),2157CCP_CodePattern, C->Availability);2158Builder.AddTypedTextChunk(C->Completion->getTypedText());2159Priority = CCP_CodePattern;2160Completion = Builder.TakeString();2161}21622163AllResults.push_back(Result(Completion, Priority, C->Kind,2164C->Availability));2165}21662167// If we did not add any cached completion results, just forward the2168// results we were given to the next consumer.2169if (!AddedResult) {2170Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);2171return;2172}21732174Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),2175AllResults.size());2176}21772178void ASTUnit::CodeComplete(2179StringRef File, unsigned Line, unsigned Column,2180ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,2181bool IncludeCodePatterns, bool IncludeBriefComments,2182CodeCompleteConsumer &Consumer,2183std::shared_ptr<PCHContainerOperations> PCHContainerOps,2184DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,2185FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,2186SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers,2187std::unique_ptr<SyntaxOnlyAction> Act) {2188if (!Invocation)2189return;21902191SimpleTimer CompletionTimer(WantTiming);2192CompletionTimer.setOutput("Code completion @ " + File + ":" +2193Twine(Line) + ":" + Twine(Column));21942195auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);21962197FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();2198CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;2199PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();22002201CodeCompleteOpts.IncludeMacros = IncludeMacros &&2202CachedCompletionResults.empty();2203CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;2204CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();2205CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;2206CodeCompleteOpts.LoadExternal = Consumer.loadExternal();2207CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts();22082209assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);22102211FrontendOpts.CodeCompletionAt.FileName = std::string(File);2212FrontendOpts.CodeCompletionAt.Line = Line;2213FrontendOpts.CodeCompletionAt.Column = Column;22142215// Set the language options appropriately.2216LangOpts = CCInvocation->getLangOpts();22172218// Spell-checking and warnings are wasteful during code-completion.2219LangOpts.SpellChecking = false;2220CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;22212222std::unique_ptr<CompilerInstance> Clang(2223new CompilerInstance(PCHContainerOps));22242225// Recover resources if we crash before exiting this method.2226llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>2227CICleanup(Clang.get());22282229auto &Inv = *CCInvocation;2230Clang->setInvocation(std::move(CCInvocation));2231OriginalSourceFile =2232std::string(Clang->getFrontendOpts().Inputs[0].getFile());22332234// Set up diagnostics, capturing any diagnostics produced.2235Clang->setDiagnostics(&Diag);2236CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All,2237Clang->getDiagnostics(),2238&StoredDiagnostics, nullptr);2239ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());22402241// Create the target instance.2242if (!Clang->createTarget()) {2243Clang->setInvocation(nullptr);2244return;2245}22462247assert(Clang->getFrontendOpts().Inputs.size() == 1 &&2248"Invocation must have exactly one source file!");2249assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==2250InputKind::Source &&2251"FIXME: AST inputs not yet supported here!");2252assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=2253Language::LLVM_IR &&2254"IR inputs not support here!");22552256// Use the source and file managers that we were given.2257Clang->setFileManager(&FileMgr);2258Clang->setSourceManager(&SourceMgr);22592260// Remap files.2261PreprocessorOpts.clearRemappedFiles();2262PreprocessorOpts.RetainRemappedFileBuffers = true;2263for (const auto &RemappedFile : RemappedFiles) {2264PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second);2265OwnedBuffers.push_back(RemappedFile.second);2266}22672268// Use the code completion consumer we were given, but adding any cached2269// code-completion results.2270AugmentedCodeCompleteConsumer *AugmentedConsumer2271= new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);2272Clang->setCodeCompletionConsumer(AugmentedConsumer);22732274auto getUniqueID =2275[&FileMgr](StringRef Filename) -> std::optional<llvm::sys::fs::UniqueID> {2276if (auto Status = FileMgr.getVirtualFileSystem().status(Filename))2277return Status->getUniqueID();2278return std::nullopt;2279};22802281auto hasSameUniqueID = [getUniqueID](StringRef LHS, StringRef RHS) {2282if (LHS == RHS)2283return true;2284if (auto LHSID = getUniqueID(LHS))2285if (auto RHSID = getUniqueID(RHS))2286return *LHSID == *RHSID;2287return false;2288};22892290// If we have a precompiled preamble, try to use it. We only allow2291// the use of the precompiled preamble if we're if the completion2292// point is within the main file, after the end of the precompiled2293// preamble.2294std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;2295if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) {2296OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(2297PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1);2298}22992300// If the main file has been overridden due to the use of a preamble,2301// make that override happen and introduce the preamble.2302if (OverrideMainBuffer) {2303assert(Preamble &&2304"No preamble was built, but OverrideMainBuffer is not null");23052306IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =2307&FileMgr.getVirtualFileSystem();2308Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,2309OverrideMainBuffer.get());2310// FIXME: there is no way to update VFS if it was changed by2311// AddImplicitPreamble as FileMgr is accepted as a parameter by this method.2312// We use on-disk preambles instead and rely on FileMgr's VFS to ensure the2313// PCH files are always readable.2314OwnedBuffers.push_back(OverrideMainBuffer.release());2315} else {2316PreprocessorOpts.PrecompiledPreambleBytes.first = 0;2317PreprocessorOpts.PrecompiledPreambleBytes.second = false;2318}23192320// Disable the preprocessing record if modules are not enabled.2321if (!Clang->getLangOpts().Modules)2322PreprocessorOpts.DetailedRecord = false;23232324if (!Act)2325Act.reset(new SyntaxOnlyAction);23262327if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {2328if (llvm::Error Err = Act->Execute()) {2329consumeError(std::move(Err)); // FIXME this drops errors on the floor.2330}2331Act->EndSourceFile();2332}2333}23342335bool ASTUnit::Save(StringRef File) {2336if (HadModuleLoaderFatalFailure)2337return true;23382339// FIXME: Can we somehow regenerate the stat cache here, or do we need to2340// unconditionally create a stat cache when we parse the file?23412342if (llvm::Error Err = llvm::writeToOutput(2343File, [this](llvm::raw_ostream &Out) {2344return serialize(Out) ? llvm::make_error<llvm::StringError>(2345"ASTUnit serialization failed",2346llvm::inconvertibleErrorCode())2347: llvm::Error::success();2348})) {2349consumeError(std::move(Err));2350return true;2351}2352return false;2353}23542355static bool serializeUnit(ASTWriter &Writer, SmallVectorImpl<char> &Buffer,2356Sema &S, raw_ostream &OS) {2357Writer.WriteAST(S, std::string(), nullptr, "");23582359// Write the generated bitstream to "Out".2360if (!Buffer.empty())2361OS.write(Buffer.data(), Buffer.size());23622363return false;2364}23652366bool ASTUnit::serialize(raw_ostream &OS) {2367if (WriterData)2368return serializeUnit(WriterData->Writer, WriterData->Buffer, getSema(), OS);23692370SmallString<128> Buffer;2371llvm::BitstreamWriter Stream(Buffer);2372InMemoryModuleCache ModuleCache;2373ASTWriter Writer(Stream, Buffer, ModuleCache, {});2374return serializeUnit(Writer, Buffer, getSema(), OS);2375}23762377void ASTUnit::TranslateStoredDiagnostics(2378FileManager &FileMgr,2379SourceManager &SrcMgr,2380const SmallVectorImpl<StandaloneDiagnostic> &Diags,2381SmallVectorImpl<StoredDiagnostic> &Out) {2382// Map the standalone diagnostic into the new source manager. We also need to2383// remap all the locations to the new view. This includes the diag location,2384// any associated source ranges, and the source ranges of associated fix-its.2385// FIXME: There should be a cleaner way to do this.2386SmallVector<StoredDiagnostic, 4> Result;2387Result.reserve(Diags.size());23882389for (const auto &SD : Diags) {2390// Rebuild the StoredDiagnostic.2391if (SD.Filename.empty())2392continue;2393auto FE = FileMgr.getFile(SD.Filename);2394if (!FE)2395continue;2396SourceLocation FileLoc;2397auto ItFileID = PreambleSrcLocCache.find(SD.Filename);2398if (ItFileID == PreambleSrcLocCache.end()) {2399FileID FID = SrcMgr.translateFile(*FE);2400FileLoc = SrcMgr.getLocForStartOfFile(FID);2401PreambleSrcLocCache[SD.Filename] = FileLoc;2402} else {2403FileLoc = ItFileID->getValue();2404}24052406if (FileLoc.isInvalid())2407continue;2408SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);2409FullSourceLoc Loc(L, SrcMgr);24102411SmallVector<CharSourceRange, 4> Ranges;2412Ranges.reserve(SD.Ranges.size());2413for (const auto &Range : SD.Ranges) {2414SourceLocation BL = FileLoc.getLocWithOffset(Range.first);2415SourceLocation EL = FileLoc.getLocWithOffset(Range.second);2416Ranges.push_back(CharSourceRange::getCharRange(BL, EL));2417}24182419SmallVector<FixItHint, 2> FixIts;2420FixIts.reserve(SD.FixIts.size());2421for (const auto &FixIt : SD.FixIts) {2422FixIts.push_back(FixItHint());2423FixItHint &FH = FixIts.back();2424FH.CodeToInsert = FixIt.CodeToInsert;2425SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first);2426SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second);2427FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);2428}24292430Result.push_back(StoredDiagnostic(SD.Level, SD.ID,2431SD.Message, Loc, Ranges, FixIts));2432}2433Result.swap(Out);2434}24352436void ASTUnit::addFileLevelDecl(Decl *D) {2437assert(D);24382439// We only care about local declarations.2440if (D->isFromASTFile())2441return;24422443SourceManager &SM = *SourceMgr;2444SourceLocation Loc = D->getLocation();2445if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc))2446return;24472448// We only keep track of the file-level declarations of each file.2449if (!D->getLexicalDeclContext()->isFileContext())2450return;24512452SourceLocation FileLoc = SM.getFileLoc(Loc);2453assert(SM.isLocalSourceLocation(FileLoc));2454FileID FID;2455unsigned Offset;2456std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);2457if (FID.isInvalid())2458return;24592460std::unique_ptr<LocDeclsTy> &Decls = FileDecls[FID];2461if (!Decls)2462Decls = std::make_unique<LocDeclsTy>();24632464std::pair<unsigned, Decl *> LocDecl(Offset, D);24652466if (Decls->empty() || Decls->back().first <= Offset) {2467Decls->push_back(LocDecl);2468return;2469}24702471LocDeclsTy::iterator I =2472llvm::upper_bound(*Decls, LocDecl, llvm::less_first());24732474Decls->insert(I, LocDecl);2475}24762477void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,2478SmallVectorImpl<Decl *> &Decls) {2479if (File.isInvalid())2480return;24812482if (SourceMgr->isLoadedFileID(File)) {2483assert(Ctx->getExternalSource() && "No external source!");2484return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length,2485Decls);2486}24872488FileDeclsTy::iterator I = FileDecls.find(File);2489if (I == FileDecls.end())2490return;24912492LocDeclsTy &LocDecls = *I->second;2493if (LocDecls.empty())2494return;24952496LocDeclsTy::iterator BeginIt =2497llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) {2498return LD.first < Offset;2499});2500if (BeginIt != LocDecls.begin())2501--BeginIt;25022503// If we are pointing at a top-level decl inside an objc container, we need2504// to backtrack until we find it otherwise we will fail to report that the2505// region overlaps with an objc container.2506while (BeginIt != LocDecls.begin() &&2507BeginIt->second->isTopLevelDeclInObjCContainer())2508--BeginIt;25092510LocDeclsTy::iterator EndIt = llvm::upper_bound(2511LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr),2512llvm::less_first());2513if (EndIt != LocDecls.end())2514++EndIt;25152516for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)2517Decls.push_back(DIt->second);2518}25192520SourceLocation ASTUnit::getLocation(const FileEntry *File,2521unsigned Line, unsigned Col) const {2522const SourceManager &SM = getSourceManager();2523SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);2524return SM.getMacroArgExpandedLocation(Loc);2525}25262527SourceLocation ASTUnit::getLocation(const FileEntry *File,2528unsigned Offset) const {2529const SourceManager &SM = getSourceManager();2530SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);2531return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));2532}25332534/// If \arg Loc is a loaded location from the preamble, returns2535/// the corresponding local location of the main file, otherwise it returns2536/// \arg Loc.2537SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {2538FileID PreambleID;2539if (SourceMgr)2540PreambleID = SourceMgr->getPreambleFileID();25412542if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())2543return Loc;25442545unsigned Offs;2546if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) {2547SourceLocation FileLoc2548= SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());2549return FileLoc.getLocWithOffset(Offs);2550}25512552return Loc;2553}25542555/// If \arg Loc is a local location of the main file but inside the2556/// preamble chunk, returns the corresponding loaded location from the2557/// preamble, otherwise it returns \arg Loc.2558SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {2559FileID PreambleID;2560if (SourceMgr)2561PreambleID = SourceMgr->getPreambleFileID();25622563if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())2564return Loc;25652566unsigned Offs;2567if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&2568Offs < Preamble->getBounds().Size) {2569SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);2570return FileLoc.getLocWithOffset(Offs);2571}25722573return Loc;2574}25752576bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {2577FileID FID;2578if (SourceMgr)2579FID = SourceMgr->getPreambleFileID();25802581if (Loc.isInvalid() || FID.isInvalid())2582return false;25832584return SourceMgr->isInFileID(Loc, FID);2585}25862587bool ASTUnit::isInMainFileID(SourceLocation Loc) const {2588FileID FID;2589if (SourceMgr)2590FID = SourceMgr->getMainFileID();25912592if (Loc.isInvalid() || FID.isInvalid())2593return false;25942595return SourceMgr->isInFileID(Loc, FID);2596}25972598SourceLocation ASTUnit::getEndOfPreambleFileID() const {2599FileID FID;2600if (SourceMgr)2601FID = SourceMgr->getPreambleFileID();26022603if (FID.isInvalid())2604return {};26052606return SourceMgr->getLocForEndOfFile(FID);2607}26082609SourceLocation ASTUnit::getStartOfMainFileID() const {2610FileID FID;2611if (SourceMgr)2612FID = SourceMgr->getMainFileID();26132614if (FID.isInvalid())2615return {};26162617return SourceMgr->getLocForStartOfFile(FID);2618}26192620llvm::iterator_range<PreprocessingRecord::iterator>2621ASTUnit::getLocalPreprocessingEntities() const {2622if (isMainFileAST()) {2623serialization::ModuleFile &2624Mod = Reader->getModuleManager().getPrimaryModule();2625return Reader->getModulePreprocessedEntities(Mod);2626}26272628if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())2629return llvm::make_range(PPRec->local_begin(), PPRec->local_end());26302631return llvm::make_range(PreprocessingRecord::iterator(),2632PreprocessingRecord::iterator());2633}26342635bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {2636if (isMainFileAST()) {2637serialization::ModuleFile &2638Mod = Reader->getModuleManager().getPrimaryModule();2639for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {2640if (!Fn(context, D))2641return false;2642}26432644return true;2645}26462647for (ASTUnit::top_level_iterator TL = top_level_begin(),2648TLEnd = top_level_end();2649TL != TLEnd; ++TL) {2650if (!Fn(context, *TL))2651return false;2652}26532654return true;2655}26562657OptionalFileEntryRef ASTUnit::getPCHFile() {2658if (!Reader)2659return std::nullopt;26602661serialization::ModuleFile *Mod = nullptr;2662Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) {2663switch (M.Kind) {2664case serialization::MK_ImplicitModule:2665case serialization::MK_ExplicitModule:2666case serialization::MK_PrebuiltModule:2667return true; // skip dependencies.2668case serialization::MK_PCH:2669Mod = &M;2670return true; // found it.2671case serialization::MK_Preamble:2672return false; // look in dependencies.2673case serialization::MK_MainFile:2674return false; // look in dependencies.2675}26762677return true;2678});2679if (Mod)2680return Mod->File;26812682return std::nullopt;2683}26842685bool ASTUnit::isModuleFile() const {2686return isMainFileAST() && getLangOpts().isCompilingModule();2687}26882689InputKind ASTUnit::getInputKind() const {2690auto &LangOpts = getLangOpts();26912692Language Lang;2693if (LangOpts.OpenCL)2694Lang = Language::OpenCL;2695else if (LangOpts.CUDA)2696Lang = Language::CUDA;2697else if (LangOpts.RenderScript)2698Lang = Language::RenderScript;2699else if (LangOpts.CPlusPlus)2700Lang = LangOpts.ObjC ? Language::ObjCXX : Language::CXX;2701else2702Lang = LangOpts.ObjC ? Language::ObjC : Language::C;27032704InputKind::Format Fmt = InputKind::Source;2705if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)2706Fmt = InputKind::ModuleMap;27072708// We don't know if input was preprocessed. Assume not.2709bool PP = false;27102711return InputKind(Lang, Fmt, PP);2712}27132714#ifndef NDEBUG2715ASTUnit::ConcurrencyState::ConcurrencyState() {2716Mutex = new std::recursive_mutex;2717}27182719ASTUnit::ConcurrencyState::~ConcurrencyState() {2720delete static_cast<std::recursive_mutex *>(Mutex);2721}27222723void ASTUnit::ConcurrencyState::start() {2724bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock();2725assert(acquired && "Concurrent access to ASTUnit!");2726}27272728void ASTUnit::ConcurrencyState::finish() {2729static_cast<std::recursive_mutex *>(Mutex)->unlock();2730}27312732#else // NDEBUG27332734ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; }2735ASTUnit::ConcurrencyState::~ConcurrencyState() {}2736void ASTUnit::ConcurrencyState::start() {}2737void ASTUnit::ConcurrencyState::finish() {}27382739#endif // NDEBUG274027412742