llvm-project
2740 строк · 97.1 Кб
1//===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// ASTUnit Implementation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Frontend/ASTUnit.h"14#include "clang/AST/ASTConsumer.h"15#include "clang/AST/ASTContext.h"16#include "clang/AST/CommentCommandTraits.h"17#include "clang/AST/Decl.h"18#include "clang/AST/DeclBase.h"19#include "clang/AST/DeclCXX.h"20#include "clang/AST/DeclGroup.h"21#include "clang/AST/DeclObjC.h"22#include "clang/AST/DeclTemplate.h"23#include "clang/AST/DeclarationName.h"24#include "clang/AST/ExternalASTSource.h"25#include "clang/AST/PrettyPrinter.h"26#include "clang/AST/Type.h"27#include "clang/AST/TypeOrdering.h"28#include "clang/Basic/Diagnostic.h"29#include "clang/Basic/FileManager.h"30#include "clang/Basic/IdentifierTable.h"31#include "clang/Basic/LLVM.h"32#include "clang/Basic/LangOptions.h"33#include "clang/Basic/LangStandard.h"34#include "clang/Basic/Module.h"35#include "clang/Basic/SourceLocation.h"36#include "clang/Basic/SourceManager.h"37#include "clang/Basic/TargetInfo.h"38#include "clang/Basic/TargetOptions.h"39#include "clang/Frontend/CompilerInstance.h"40#include "clang/Frontend/CompilerInvocation.h"41#include "clang/Frontend/FrontendAction.h"42#include "clang/Frontend/FrontendActions.h"43#include "clang/Frontend/FrontendDiagnostic.h"44#include "clang/Frontend/FrontendOptions.h"45#include "clang/Frontend/MultiplexConsumer.h"46#include "clang/Frontend/PrecompiledPreamble.h"47#include "clang/Frontend/Utils.h"48#include "clang/Lex/HeaderSearch.h"49#include "clang/Lex/HeaderSearchOptions.h"50#include "clang/Lex/Lexer.h"51#include "clang/Lex/PPCallbacks.h"52#include "clang/Lex/PreprocessingRecord.h"53#include "clang/Lex/Preprocessor.h"54#include "clang/Lex/PreprocessorOptions.h"55#include "clang/Lex/Token.h"56#include "clang/Sema/CodeCompleteConsumer.h"57#include "clang/Sema/CodeCompleteOptions.h"58#include "clang/Sema/Sema.h"59#include "clang/Sema/SemaCodeCompletion.h"60#include "clang/Serialization/ASTBitCodes.h"61#include "clang/Serialization/ASTReader.h"62#include "clang/Serialization/ASTWriter.h"63#include "clang/Serialization/ContinuousRangeMap.h"64#include "clang/Serialization/InMemoryModuleCache.h"65#include "clang/Serialization/ModuleFile.h"66#include "clang/Serialization/PCHContainerOperations.h"67#include "llvm/ADT/ArrayRef.h"68#include "llvm/ADT/DenseMap.h"69#include "llvm/ADT/IntrusiveRefCntPtr.h"70#include "llvm/ADT/STLExtras.h"71#include "llvm/ADT/ScopeExit.h"72#include "llvm/ADT/SmallVector.h"73#include "llvm/ADT/StringMap.h"74#include "llvm/ADT/StringRef.h"75#include "llvm/ADT/StringSet.h"76#include "llvm/ADT/Twine.h"77#include "llvm/ADT/iterator_range.h"78#include "llvm/Bitstream/BitstreamWriter.h"79#include "llvm/Support/Allocator.h"80#include "llvm/Support/Casting.h"81#include "llvm/Support/CrashRecoveryContext.h"82#include "llvm/Support/DJB.h"83#include "llvm/Support/ErrorHandling.h"84#include "llvm/Support/ErrorOr.h"85#include "llvm/Support/FileSystem.h"86#include "llvm/Support/MemoryBuffer.h"87#include "llvm/Support/SaveAndRestore.h"88#include "llvm/Support/Timer.h"89#include "llvm/Support/VirtualFileSystem.h"90#include "llvm/Support/raw_ostream.h"91#include <algorithm>92#include <atomic>93#include <cassert>94#include <cstdint>95#include <cstdio>96#include <cstdlib>97#include <memory>98#include <mutex>99#include <optional>100#include <string>101#include <tuple>102#include <utility>103#include <vector>104
105using namespace clang;106
107using llvm::TimeRecord;108
109namespace {110
111class SimpleTimer {112bool WantTiming;113TimeRecord Start;114std::string Output;115
116public:117explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {118if (WantTiming)119Start = TimeRecord::getCurrentTime();120}121
122~SimpleTimer() {123if (WantTiming) {124TimeRecord Elapsed = TimeRecord::getCurrentTime();125Elapsed -= Start;126llvm::errs() << Output << ':';127Elapsed.print(Elapsed, llvm::errs());128llvm::errs() << '\n';129}130}131
132void setOutput(const Twine &Output) {133if (WantTiming)134this->Output = Output.str();135}136};137
138} // namespace139
140template <class T>141static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {142if (!Val)143return nullptr;144return std::move(*Val);145}
146
147template <class T>148static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {149if (!Val)150return false;151Output = std::move(*Val);152return true;153}
154
155/// Get a source buffer for \p MainFilePath, handling all file-to-file
156/// and file-to-buffer remappings inside \p Invocation.
157static std::unique_ptr<llvm::MemoryBuffer>158getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,159llvm::vfs::FileSystem *VFS,160StringRef FilePath, bool isVolatile) {161const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();162
163// Try to determine if the main file has been remapped, either from the164// command line (to another file) or directly through the compiler165// invocation (to a memory buffer).166llvm::MemoryBuffer *Buffer = nullptr;167std::unique_ptr<llvm::MemoryBuffer> BufferOwner;168auto FileStatus = VFS->status(FilePath);169if (FileStatus) {170llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID();171
172// Check whether there is a file-file remapping of the main file173for (const auto &RF : PreprocessorOpts.RemappedFiles) {174std::string MPath(RF.first);175auto MPathStatus = VFS->status(MPath);176if (MPathStatus) {177llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();178if (MainFileID == MID) {179// We found a remapping. Try to load the resulting, remapped source.180BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));181if (!BufferOwner)182return nullptr;183}184}185}186
187// Check whether there is a file-buffer remapping. It supercedes the188// file-file remapping.189for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {190std::string MPath(RB.first);191auto MPathStatus = VFS->status(MPath);192if (MPathStatus) {193llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();194if (MainFileID == MID) {195// We found a remapping.196BufferOwner.reset();197Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);198}199}200}201}202
203// If the main source file was not remapped, load it now.204if (!Buffer && !BufferOwner) {205BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));206if (!BufferOwner)207return nullptr;208}209
210if (BufferOwner)211return BufferOwner;212if (!Buffer)213return nullptr;214return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);215}
216
217struct ASTUnit::ASTWriterData {218SmallString<128> Buffer;219llvm::BitstreamWriter Stream;220ASTWriter Writer;221
222ASTWriterData(InMemoryModuleCache &ModuleCache)223: Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {}224};225
226void ASTUnit::clearFileLevelDecls() {227FileDecls.clear();228}
229
230/// After failing to build a precompiled preamble (due to
231/// errors in the source that occurs in the preamble), the number of
232/// reparses during which we'll skip even trying to precompile the
233/// preamble.
234const unsigned DefaultPreambleRebuildInterval = 5;235
236/// Tracks the number of ASTUnit objects that are currently active.
237///
238/// Used for debugging purposes only.
239static std::atomic<unsigned> ActiveASTUnitObjects;240
241ASTUnit::ASTUnit(bool _MainFileIsAST)242: MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),243ShouldCacheCodeCompletionResults(false),244IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),245UnsafeToFree(false) {246if (getenv("LIBCLANG_OBJTRACKING"))247fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);248}
249
250ASTUnit::~ASTUnit() {251// If we loaded from an AST file, balance out the BeginSourceFile call.252if (MainFileIsAST && getDiagnostics().getClient()) {253getDiagnostics().getClient()->EndSourceFile();254}255
256clearFileLevelDecls();257
258// Free the buffers associated with remapped files. We are required to259// perform this operation here because we explicitly request that the260// compiler instance *not* free these buffers for each invocation of the261// parser.262if (Invocation && OwnsRemappedFileBuffers) {263PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();264for (const auto &RB : PPOpts.RemappedFileBuffers)265delete RB.second;266}267
268ClearCachedCompletionResults();269
270if (getenv("LIBCLANG_OBJTRACKING"))271fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);272}
273
274void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {275this->PP = std::move(PP);276}
277
278void ASTUnit::enableSourceFileDiagnostics() {279assert(getDiagnostics().getClient() && Ctx &&280"Bad context for source file");281getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());282}
283
284/// Determine the set of code-completion contexts in which this
285/// declaration should be shown.
286static uint64_t getDeclShowContexts(const NamedDecl *ND,287const LangOptions &LangOpts,288bool &IsNestedNameSpecifier) {289IsNestedNameSpecifier = false;290
291if (isa<UsingShadowDecl>(ND))292ND = ND->getUnderlyingDecl();293if (!ND)294return 0;295
296uint64_t Contexts = 0;297if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||298isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||299isa<TypeAliasTemplateDecl>(ND)) {300// Types can appear in these contexts.301if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))302Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)303| (1LL << CodeCompletionContext::CCC_ObjCIvarList)304| (1LL << CodeCompletionContext::CCC_ClassStructUnion)305| (1LL << CodeCompletionContext::CCC_Statement)306| (1LL << CodeCompletionContext::CCC_Type)307| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);308
309// In C++, types can appear in expressions contexts (for functional casts).310if (LangOpts.CPlusPlus)311Contexts |= (1LL << CodeCompletionContext::CCC_Expression);312
313// In Objective-C, message sends can send interfaces. In Objective-C++,314// all types are available due to functional casts.315if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))316Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);317
318// In Objective-C, you can only be a subclass of another Objective-C class319if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {320// Objective-C interfaces can be used in a class property expression.321if (ID->getDefinition())322Contexts |= (1LL << CodeCompletionContext::CCC_Expression);323Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);324Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);325}326
327// Deal with tag names.328if (isa<EnumDecl>(ND)) {329Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);330
331// Part of the nested-name-specifier in C++0x.332if (LangOpts.CPlusPlus11)333IsNestedNameSpecifier = true;334} else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {335if (Record->isUnion())336Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);337else338Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);339
340if (LangOpts.CPlusPlus)341IsNestedNameSpecifier = true;342} else if (isa<ClassTemplateDecl>(ND))343IsNestedNameSpecifier = true;344} else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {345// Values can appear in these contexts.346Contexts = (1LL << CodeCompletionContext::CCC_Statement)347| (1LL << CodeCompletionContext::CCC_Expression)348| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)349| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);350} else if (isa<ObjCProtocolDecl>(ND)) {351Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);352} else if (isa<ObjCCategoryDecl>(ND)) {353Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);354} else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {355Contexts = (1LL << CodeCompletionContext::CCC_Namespace);356
357// Part of the nested-name-specifier.358IsNestedNameSpecifier = true;359}360
361return Contexts;362}
363
364void ASTUnit::CacheCodeCompletionResults() {365if (!TheSema)366return;367
368SimpleTimer Timer(WantTiming);369Timer.setOutput("Cache global code completions for " + getMainFileName());370
371// Clear out the previous results.372ClearCachedCompletionResults();373
374// Gather the set of global code completions.375using Result = CodeCompletionResult;376SmallVector<Result, 8> Results;377CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();378CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);379TheSema->CodeCompletion().GatherGlobalCodeCompletions(380*CachedCompletionAllocator, CCTUInfo, Results);381
382// Translate global code completions into cached completions.383llvm::DenseMap<CanQualType, unsigned> CompletionTypes;384CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);385
386for (auto &R : Results) {387switch (R.Kind) {388case Result::RK_Declaration: {389bool IsNestedNameSpecifier = false;390CachedCodeCompletionResult CachedResult;391CachedResult.Completion = R.CreateCodeCompletionString(392*TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,393IncludeBriefCommentsInCodeCompletion);394CachedResult.ShowInContexts = getDeclShowContexts(395R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);396CachedResult.Priority = R.Priority;397CachedResult.Kind = R.CursorKind;398CachedResult.Availability = R.Availability;399
400// Keep track of the type of this completion in an ASTContext-agnostic401// way.402QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);403if (UsageType.isNull()) {404CachedResult.TypeClass = STC_Void;405CachedResult.Type = 0;406} else {407CanQualType CanUsageType
408= Ctx->getCanonicalType(UsageType.getUnqualifiedType());409CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);410
411// Determine whether we have already seen this type. If so, we save412// ourselves the work of formatting the type string by using the413// temporary, CanQualType-based hash table to find the associated value.414unsigned &TypeValue = CompletionTypes[CanUsageType];415if (TypeValue == 0) {416TypeValue = CompletionTypes.size();417CachedCompletionTypes[QualType(CanUsageType).getAsString()]418= TypeValue;419}420
421CachedResult.Type = TypeValue;422}423
424CachedCompletionResults.push_back(CachedResult);425
426/// Handle nested-name-specifiers in C++.427if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&428!R.StartsNestedNameSpecifier) {429// The contexts in which a nested-name-specifier can appear in C++.430uint64_t NNSContexts431= (1LL << CodeCompletionContext::CCC_TopLevel)432| (1LL << CodeCompletionContext::CCC_ObjCIvarList)433| (1LL << CodeCompletionContext::CCC_ClassStructUnion)434| (1LL << CodeCompletionContext::CCC_Statement)435| (1LL << CodeCompletionContext::CCC_Expression)436| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)437| (1LL << CodeCompletionContext::CCC_EnumTag)438| (1LL << CodeCompletionContext::CCC_UnionTag)439| (1LL << CodeCompletionContext::CCC_ClassOrStructTag)440| (1LL << CodeCompletionContext::CCC_Type)441| (1LL << CodeCompletionContext::CCC_SymbolOrNewName)442| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);443
444if (isa<NamespaceDecl>(R.Declaration) ||445isa<NamespaceAliasDecl>(R.Declaration))446NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);447
448if (uint64_t RemainingContexts449= NNSContexts & ~CachedResult.ShowInContexts) {450// If there any contexts where this completion can be a451// nested-name-specifier but isn't already an option, create a452// nested-name-specifier completion.453R.StartsNestedNameSpecifier = true;454CachedResult.Completion = R.CreateCodeCompletionString(455*TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,456IncludeBriefCommentsInCodeCompletion);457CachedResult.ShowInContexts = RemainingContexts;458CachedResult.Priority = CCP_NestedNameSpecifier;459CachedResult.TypeClass = STC_Void;460CachedResult.Type = 0;461CachedCompletionResults.push_back(CachedResult);462}463}464break;465}466
467case Result::RK_Keyword:468case Result::RK_Pattern:469// Ignore keywords and patterns; we don't care, since they are so470// easily regenerated.471break;472
473case Result::RK_Macro: {474CachedCodeCompletionResult CachedResult;475CachedResult.Completion = R.CreateCodeCompletionString(476*TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,477IncludeBriefCommentsInCodeCompletion);478CachedResult.ShowInContexts479= (1LL << CodeCompletionContext::CCC_TopLevel)480| (1LL << CodeCompletionContext::CCC_ObjCInterface)481| (1LL << CodeCompletionContext::CCC_ObjCImplementation)482| (1LL << CodeCompletionContext::CCC_ObjCIvarList)483| (1LL << CodeCompletionContext::CCC_ClassStructUnion)484| (1LL << CodeCompletionContext::CCC_Statement)485| (1LL << CodeCompletionContext::CCC_Expression)486| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)487| (1LL << CodeCompletionContext::CCC_MacroNameUse)488| (1LL << CodeCompletionContext::CCC_PreprocessorExpression)489| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)490| (1LL << CodeCompletionContext::CCC_OtherWithMacros);491
492CachedResult.Priority = R.Priority;493CachedResult.Kind = R.CursorKind;494CachedResult.Availability = R.Availability;495CachedResult.TypeClass = STC_Void;496CachedResult.Type = 0;497CachedCompletionResults.push_back(CachedResult);498break;499}500}501}502
503// Save the current top-level hash value.504CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;505}
506
507void ASTUnit::ClearCachedCompletionResults() {508CachedCompletionResults.clear();509CachedCompletionTypes.clear();510CachedCompletionAllocator = nullptr;511}
512
513namespace {514
515/// Gathers information from ASTReader that will be used to initialize
516/// a Preprocessor.
517class ASTInfoCollector : public ASTReaderListener {518Preprocessor &PP;519ASTContext *Context;520HeaderSearchOptions &HSOpts;521PreprocessorOptions &PPOpts;522LangOptions &LangOpt;523std::shared_ptr<TargetOptions> &TargetOpts;524IntrusiveRefCntPtr<TargetInfo> &Target;525unsigned &Counter;526bool InitializedLanguage = false;527bool InitializedHeaderSearchPaths = false;528
529public:530ASTInfoCollector(Preprocessor &PP, ASTContext *Context,531HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,532LangOptions &LangOpt,533std::shared_ptr<TargetOptions> &TargetOpts,534IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)535: PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),536LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),537Counter(Counter) {}538
539bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,540bool AllowCompatibleDifferences) override {541if (InitializedLanguage)542return false;543
544// FIXME: We did similar things in ReadHeaderSearchOptions too. But such545// style is not scaling. Probably we need to invite some mechanism to546// handle such patterns generally.547auto PICLevel = LangOpt.PICLevel;548auto PIE = LangOpt.PIE;549
550LangOpt = LangOpts;551
552LangOpt.PICLevel = PICLevel;553LangOpt.PIE = PIE;554
555InitializedLanguage = true;556
557updated();558return false;559}560
561bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,562StringRef SpecificModuleCachePath,563bool Complain) override {564// llvm::SaveAndRestore doesn't support bit field.565auto ForceCheckCXX20ModulesInputFiles =566this->HSOpts.ForceCheckCXX20ModulesInputFiles;567llvm::SaveAndRestore X(this->HSOpts.UserEntries);568llvm::SaveAndRestore Y(this->HSOpts.SystemHeaderPrefixes);569llvm::SaveAndRestore Z(this->HSOpts.VFSOverlayFiles);570
571this->HSOpts = HSOpts;572this->HSOpts.ForceCheckCXX20ModulesInputFiles =573ForceCheckCXX20ModulesInputFiles;574
575return false;576}577
578bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,579bool Complain) override {580if (InitializedHeaderSearchPaths)581return false;582
583this->HSOpts.UserEntries = HSOpts.UserEntries;584this->HSOpts.SystemHeaderPrefixes = HSOpts.SystemHeaderPrefixes;585this->HSOpts.VFSOverlayFiles = HSOpts.VFSOverlayFiles;586
587// Initialize the FileManager. We can't do this in update(), since that588// performs the initialization too late (once both target and language589// options are read).590PP.getFileManager().setVirtualFileSystem(createVFSFromOverlayFiles(591HSOpts.VFSOverlayFiles, PP.getDiagnostics(),592PP.getFileManager().getVirtualFileSystemPtr()));593
594InitializedHeaderSearchPaths = true;595
596return false;597}598
599bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,600bool ReadMacros, bool Complain,601std::string &SuggestedPredefines) override {602this->PPOpts = PPOpts;603return false;604}605
606bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,607bool AllowCompatibleDifferences) override {608// If we've already initialized the target, don't do it again.609if (Target)610return false;611
612this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);613Target =614TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts);615
616updated();617return false;618}619
620void ReadCounter(const serialization::ModuleFile &M,621unsigned Value) override {622Counter = Value;623}624
625private:626void updated() {627if (!Target || !InitializedLanguage)628return;629
630// Inform the target of the language options.631//632// FIXME: We shouldn't need to do this, the target should be immutable once633// created. This complexity should be lifted elsewhere.634Target->adjust(PP.getDiagnostics(), LangOpt);635
636// Initialize the preprocessor.637PP.Initialize(*Target);638
639if (!Context)640return;641
642// Initialize the ASTContext643Context->InitBuiltinTypes(*Target);644
645// Adjust printing policy based on language options.646Context->setPrintingPolicy(PrintingPolicy(LangOpt));647
648// We didn't have access to the comment options when the ASTContext was649// constructed, so register them now.650Context->getCommentCommandTraits().registerCommentOptions(651LangOpt.CommentOpts);652}653};654
655/// Diagnostic consumer that saves each diagnostic it is given.
656class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {657SmallVectorImpl<StoredDiagnostic> *StoredDiags;658SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;659bool CaptureNonErrorsFromIncludes = true;660const LangOptions *LangOpts = nullptr;661SourceManager *SourceMgr = nullptr;662
663public:664FilterAndStoreDiagnosticConsumer(665SmallVectorImpl<StoredDiagnostic> *StoredDiags,666SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags,667bool CaptureNonErrorsFromIncludes)668: StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),669CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {670assert((StoredDiags || StandaloneDiags) &&671"No output collections were passed to StoredDiagnosticConsumer.");672}673
674void BeginSourceFile(const LangOptions &LangOpts,675const Preprocessor *PP = nullptr) override {676this->LangOpts = &LangOpts;677if (PP)678SourceMgr = &PP->getSourceManager();679}680
681void HandleDiagnostic(DiagnosticsEngine::Level Level,682const Diagnostic &Info) override;683};684
685/// RAII object that optionally captures and filters diagnostics, if
686/// there is no diagnostic client to capture them already.
687class CaptureDroppedDiagnostics {688DiagnosticsEngine &Diags;689FilterAndStoreDiagnosticConsumer Client;690DiagnosticConsumer *PreviousClient = nullptr;691std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;692
693public:694CaptureDroppedDiagnostics(695CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,696SmallVectorImpl<StoredDiagnostic> *StoredDiags,697SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)698: Diags(Diags),699Client(StoredDiags, StandaloneDiags,700CaptureDiagnostics !=701CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {702if (CaptureDiagnostics != CaptureDiagsKind::None ||703Diags.getClient() == nullptr) {704OwningPreviousClient = Diags.takeClient();705PreviousClient = Diags.getClient();706Diags.setClient(&Client, false);707}708}709
710~CaptureDroppedDiagnostics() {711if (Diags.getClient() == &Client)712Diags.setClient(PreviousClient, !!OwningPreviousClient.release());713}714};715
716} // namespace717
718static ASTUnit::StandaloneDiagnostic719makeStandaloneDiagnostic(const LangOptions &LangOpts,720const StoredDiagnostic &InDiag);721
722static bool isInMainFile(const clang::Diagnostic &D) {723if (!D.hasSourceManager() || !D.getLocation().isValid())724return false;725
726auto &M = D.getSourceManager();727return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation()));728}
729
730void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(731DiagnosticsEngine::Level Level, const Diagnostic &Info) {732// Default implementation (Warnings/errors count).733DiagnosticConsumer::HandleDiagnostic(Level, Info);734
735// Only record the diagnostic if it's part of the source manager we know736// about. This effectively drops diagnostics from modules we're building.737// FIXME: In the long run, ee don't want to drop source managers from modules.738if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) {739if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning &&740!isInMainFile(Info)) {741return;742}743
744StoredDiagnostic *ResultDiag = nullptr;745if (StoredDiags) {746StoredDiags->emplace_back(Level, Info);747ResultDiag = &StoredDiags->back();748}749
750if (StandaloneDiags) {751std::optional<StoredDiagnostic> StoredDiag;752if (!ResultDiag) {753StoredDiag.emplace(Level, Info);754ResultDiag = &*StoredDiag;755}756StandaloneDiags->push_back(757makeStandaloneDiagnostic(*LangOpts, *ResultDiag));758}759}760}
761
762IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {763return Reader;764}
765
766ASTMutationListener *ASTUnit::getASTMutationListener() {767if (WriterData)768return &WriterData->Writer;769return nullptr;770}
771
772ASTDeserializationListener *ASTUnit::getDeserializationListener() {773if (WriterData)774return &WriterData->Writer;775return nullptr;776}
777
778std::unique_ptr<llvm::MemoryBuffer>779ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {780assert(FileMgr);781auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);782if (Buffer)783return std::move(*Buffer);784if (ErrorStr)785*ErrorStr = Buffer.getError().message();786return nullptr;787}
788
789/// Configure the diagnostics object for use with ASTUnit.
790void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,791ASTUnit &AST,792CaptureDiagsKind CaptureDiagnostics) {793assert(Diags.get() && "no DiagnosticsEngine was provided");794if (CaptureDiagnostics != CaptureDiagsKind::None)795Diags->setClient(new FilterAndStoreDiagnosticConsumer(796&AST.StoredDiagnostics, nullptr,797CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes));798}
799
800std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(801const std::string &Filename, const PCHContainerReader &PCHContainerRdr,802WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,803const FileSystemOptions &FileSystemOpts,804std::shared_ptr<HeaderSearchOptions> HSOpts,805std::shared_ptr<LangOptions> LangOpts, bool OnlyLocalDecls,806CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,807bool UserFilesAreVolatile, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {808std::unique_ptr<ASTUnit> AST(new ASTUnit(true));809
810// Recover resources if we crash before exiting this method.811llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>812ASTUnitCleanup(AST.get());813llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,814llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>815DiagCleanup(Diags.get());816
817ConfigureDiags(Diags, *AST, CaptureDiagnostics);818
819AST->LangOpts = LangOpts ? LangOpts : std::make_shared<LangOptions>();820AST->OnlyLocalDecls = OnlyLocalDecls;821AST->CaptureDiagnostics = CaptureDiagnostics;822AST->Diagnostics = Diags;823AST->FileMgr = new FileManager(FileSystemOpts, VFS);824AST->UserFilesAreVolatile = UserFilesAreVolatile;825AST->SourceMgr = new SourceManager(AST->getDiagnostics(),826AST->getFileManager(),827UserFilesAreVolatile);828AST->ModuleCache = new InMemoryModuleCache;829AST->HSOpts = HSOpts ? HSOpts : std::make_shared<HeaderSearchOptions>();830AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front());831AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,832AST->getSourceManager(),833AST->getDiagnostics(),834AST->getLangOpts(),835/*Target=*/nullptr));836AST->PPOpts = std::make_shared<PreprocessorOptions>();837
838// Gather Info for preprocessor construction later on.839
840HeaderSearch &HeaderInfo = *AST->HeaderInfo;841
842AST->PP = std::make_shared<Preprocessor>(843AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts,844AST->getSourceManager(), HeaderInfo, AST->ModuleLoader,845/*IILookup=*/nullptr,846/*OwnsHeaderSearch=*/false);847Preprocessor &PP = *AST->PP;848
849if (ToLoad >= LoadASTOnly)850AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),851PP.getIdentifierTable(), PP.getSelectorTable(),852PP.getBuiltinInfo(),853AST->getTranslationUnitKind());854
855DisableValidationForModuleKind disableValid =856DisableValidationForModuleKind::None;857if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))858disableValid = DisableValidationForModuleKind::All;859AST->Reader = new ASTReader(860PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},861/*isysroot=*/"",862/*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);863
864unsigned Counter = 0;865AST->Reader->setListener(std::make_unique<ASTInfoCollector>(866*AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,867AST->TargetOpts, AST->Target, Counter));868
869// Attach the AST reader to the AST context as an external AST870// source, so that declarations will be deserialized from the871// AST file as needed.872// We need the external source to be set up before we read the AST, because873// eagerly-deserialized declarations may use it.874if (AST->Ctx)875AST->Ctx->setExternalSource(AST->Reader);876
877switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,878SourceLocation(), ASTReader::ARR_None)) {879case ASTReader::Success:880break;881
882case ASTReader::Failure:883case ASTReader::Missing:884case ASTReader::OutOfDate:885case ASTReader::VersionMismatch:886case ASTReader::ConfigurationMismatch:887case ASTReader::HadErrors:888AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);889return nullptr;890}891
892AST->OriginalSourceFile = std::string(AST->Reader->getOriginalSourceFile());893
894PP.setCounterValue(Counter);895
896Module *M = HeaderInfo.lookupModule(AST->getLangOpts().CurrentModule);897if (M && AST->getLangOpts().isCompilingModule() && M->isNamedModule())898AST->Ctx->setCurrentNamedModule(M);899
900// Create an AST consumer, even though it isn't used.901if (ToLoad >= LoadASTOnly)902AST->Consumer.reset(new ASTConsumer);903
904// Create a semantic analysis object and tell the AST reader about it.905if (ToLoad >= LoadEverything) {906AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer));907AST->TheSema->Initialize();908AST->Reader->InitializeSema(*AST->TheSema);909}910
911// Tell the diagnostic client that we have started a source file.912AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP);913
914return AST;915}
916
917/// Add the given macro to the hash of all top-level entities.
918static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {919Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);920}
921
922namespace {923
924/// Preprocessor callback class that updates a hash value with the names
925/// of all macros that have been defined by the translation unit.
926class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {927unsigned &Hash;928
929public:930explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}931
932void MacroDefined(const Token &MacroNameTok,933const MacroDirective *MD) override {934AddDefinedMacroToHash(MacroNameTok, Hash);935}936};937
938} // namespace939
940/// Add the given declaration to the hash of all top-level entities.
941static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {942if (!D)943return;944
945DeclContext *DC = D->getDeclContext();946if (!DC)947return;948
949if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))950return;951
952if (const auto *ND = dyn_cast<NamedDecl>(D)) {953if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {954// For an unscoped enum include the enumerators in the hash since they955// enter the top-level namespace.956if (!EnumD->isScoped()) {957for (const auto *EI : EnumD->enumerators()) {958if (EI->getIdentifier())959Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);960}961}962}963
964if (ND->getIdentifier())965Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);966else if (DeclarationName Name = ND->getDeclName()) {967std::string NameStr = Name.getAsString();968Hash = llvm::djbHash(NameStr, Hash);969}970return;971}972
973if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {974if (const Module *Mod = ImportD->getImportedModule()) {975std::string ModName = Mod->getFullModuleName();976Hash = llvm::djbHash(ModName, Hash);977}978return;979}980}
981
982namespace {983
984class TopLevelDeclTrackerConsumer : public ASTConsumer {985ASTUnit &Unit;986unsigned &Hash;987
988public:989TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)990: Unit(_Unit), Hash(Hash) {991Hash = 0;992}993
994void handleTopLevelDecl(Decl *D) {995if (!D)996return;997
998// FIXME: Currently ObjC method declarations are incorrectly being999// reported as top-level declarations, even though their DeclContext1000// is the containing ObjC @interface/@implementation. This is a1001// fundamental problem in the parser right now.1002if (isa<ObjCMethodDecl>(D))1003return;1004
1005AddTopLevelDeclarationToHash(D, Hash);1006Unit.addTopLevelDecl(D);1007
1008handleFileLevelDecl(D);1009}1010
1011void handleFileLevelDecl(Decl *D) {1012Unit.addFileLevelDecl(D);1013if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {1014for (auto *I : NSD->decls())1015handleFileLevelDecl(I);1016}1017}1018
1019bool HandleTopLevelDecl(DeclGroupRef D) override {1020for (auto *TopLevelDecl : D)1021handleTopLevelDecl(TopLevelDecl);1022return true;1023}1024
1025// We're not interested in "interesting" decls.1026void HandleInterestingDecl(DeclGroupRef) override {}1027
1028void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {1029for (auto *TopLevelDecl : D)1030handleTopLevelDecl(TopLevelDecl);1031}1032
1033ASTMutationListener *GetASTMutationListener() override {1034return Unit.getASTMutationListener();1035}1036
1037ASTDeserializationListener *GetASTDeserializationListener() override {1038return Unit.getDeserializationListener();1039}1040};1041
1042class TopLevelDeclTrackerAction : public ASTFrontendAction {1043public:1044ASTUnit &Unit;1045
1046std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,1047StringRef InFile) override {1048CI.getPreprocessor().addPPCallbacks(1049std::make_unique<MacroDefinitionTrackerPPCallbacks>(1050Unit.getCurrentTopLevelHashValue()));1051return std::make_unique<TopLevelDeclTrackerConsumer>(1052Unit, Unit.getCurrentTopLevelHashValue());1053}1054
1055public:1056TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}1057
1058bool hasCodeCompletionSupport() const override { return false; }1059
1060TranslationUnitKind getTranslationUnitKind() override {1061return Unit.getTranslationUnitKind();1062}1063};1064
1065class ASTUnitPreambleCallbacks : public PreambleCallbacks {1066public:1067unsigned getHash() const { return Hash; }1068
1069std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }1070
1071std::vector<LocalDeclID> takeTopLevelDeclIDs() {1072return std::move(TopLevelDeclIDs);1073}1074
1075void AfterPCHEmitted(ASTWriter &Writer) override {1076TopLevelDeclIDs.reserve(TopLevelDecls.size());1077for (const auto *D : TopLevelDecls) {1078// Invalid top-level decls may not have been serialized.1079if (D->isInvalidDecl())1080continue;1081TopLevelDeclIDs.push_back(Writer.getDeclID(D));1082}1083}1084
1085void HandleTopLevelDecl(DeclGroupRef DG) override {1086for (auto *D : DG) {1087// FIXME: Currently ObjC method declarations are incorrectly being1088// reported as top-level declarations, even though their DeclContext1089// is the containing ObjC @interface/@implementation. This is a1090// fundamental problem in the parser right now.1091if (isa<ObjCMethodDecl>(D))1092continue;1093AddTopLevelDeclarationToHash(D, Hash);1094TopLevelDecls.push_back(D);1095}1096}1097
1098std::unique_ptr<PPCallbacks> createPPCallbacks() override {1099return std::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash);1100}1101
1102private:1103unsigned Hash = 0;1104std::vector<Decl *> TopLevelDecls;1105std::vector<LocalDeclID> TopLevelDeclIDs;1106llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;1107};1108
1109} // namespace1110
1111static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {1112return StoredDiag.getLocation().isValid();1113}
1114
1115static void1116checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {1117// Get rid of stored diagnostics except the ones from the driver which do not1118// have a source location.1119llvm::erase_if(StoredDiags, isNonDriverDiag);1120}
1121
1122static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &1123StoredDiagnostics,1124SourceManager &SM) {1125// The stored diagnostic has the old source manager in it; update1126// the locations to refer into the new source manager. Since we've1127// been careful to make sure that the source manager's state1128// before and after are identical, so that we can reuse the source1129// location itself.1130for (auto &SD : StoredDiagnostics) {1131if (SD.getLocation().isValid()) {1132FullSourceLoc Loc(SD.getLocation(), SM);1133SD.setLocation(Loc);1134}1135}1136}
1137
1138/// Parse the source file into a translation unit using the given compiler
1139/// invocation, replacing the current translation unit.
1140///
1141/// \returns True if a failure occurred that causes the ASTUnit not to
1142/// contain any translation-unit information, false otherwise.
1143bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,1144std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,1145IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1146if (!Invocation)1147return true;1148
1149if (VFS && FileMgr)1150assert(VFS == &FileMgr->getVirtualFileSystem() &&1151"VFS passed to Parse and VFS in FileMgr are different");1152
1153auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);1154if (OverrideMainBuffer) {1155assert(Preamble &&1156"No preamble was built, but OverrideMainBuffer is not null");1157Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());1158// VFS may have changed...1159}1160
1161// Create the compiler instance to use for building the AST.1162std::unique_ptr<CompilerInstance> Clang(1163new CompilerInstance(std::move(PCHContainerOps)));1164Clang->setInvocation(CCInvocation);1165
1166// Clean up on error, disengage it if the function returns successfully.1167auto CleanOnError = llvm::make_scope_exit([&]() {1168// Remove the overridden buffer we used for the preamble.1169SavedMainFileBuffer = nullptr;1170
1171// Keep the ownership of the data in the ASTUnit because the client may1172// want to see the diagnostics.1173transferASTDataFromCompilerInstance(*Clang);1174FailedParseDiagnostics.swap(StoredDiagnostics);1175StoredDiagnostics.clear();1176NumStoredDiagnosticsFromDriver = 0;1177});1178
1179// Ensure that Clang has a FileManager with the right VFS, which may have1180// changed above in AddImplicitPreamble. If VFS is nullptr, rely on1181// createFileManager to create one.1182if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS)1183Clang->setFileManager(&*FileMgr);1184else1185FileMgr = Clang->createFileManager(std::move(VFS));1186
1187// Recover resources if we crash before exiting this method.1188llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>1189CICleanup(Clang.get());1190
1191OriginalSourceFile =1192std::string(Clang->getFrontendOpts().Inputs[0].getFile());1193
1194// Set up diagnostics, capturing any diagnostics that would1195// otherwise be dropped.1196Clang->setDiagnostics(&getDiagnostics());1197
1198// Create the target instance.1199if (!Clang->createTarget())1200return true;1201
1202assert(Clang->getFrontendOpts().Inputs.size() == 1 &&1203"Invocation must have exactly one source file!");1204assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==1205InputKind::Source &&1206"FIXME: AST inputs not yet supported here!");1207assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=1208Language::LLVM_IR &&1209"IR inputs not support here!");1210
1211// Configure the various subsystems.1212LangOpts = Clang->getInvocation().LangOpts;1213FileSystemOpts = Clang->getFileSystemOpts();1214
1215ResetForParse();1216
1217SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,1218UserFilesAreVolatile);1219if (!OverrideMainBuffer) {1220checkAndRemoveNonDriverDiags(StoredDiagnostics);1221TopLevelDeclsInPreamble.clear();1222}1223
1224// Create the source manager.1225Clang->setSourceManager(&getSourceManager());1226
1227// If the main file has been overridden due to the use of a preamble,1228// make that override happen and introduce the preamble.1229if (OverrideMainBuffer) {1230// The stored diagnostic has the old source manager in it; update1231// the locations to refer into the new source manager. Since we've1232// been careful to make sure that the source manager's state1233// before and after are identical, so that we can reuse the source1234// location itself.1235checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());1236
1237// Keep track of the override buffer;1238SavedMainFileBuffer = std::move(OverrideMainBuffer);1239}1240
1241std::unique_ptr<TopLevelDeclTrackerAction> Act(1242new TopLevelDeclTrackerAction(*this));1243
1244// Recover resources if we crash before exiting this method.1245llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>1246ActCleanup(Act.get());1247
1248if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))1249return true;1250
1251if (SavedMainFileBuffer)1252TranslateStoredDiagnostics(getFileManager(), getSourceManager(),1253PreambleDiagnostics, StoredDiagnostics);1254else1255PreambleSrcLocCache.clear();1256
1257if (llvm::Error Err = Act->Execute()) {1258consumeError(std::move(Err)); // FIXME this drops errors on the floor.1259return true;1260}1261
1262transferASTDataFromCompilerInstance(*Clang);1263
1264Act->EndSourceFile();1265
1266FailedParseDiagnostics.clear();1267
1268CleanOnError.release();1269
1270return false;1271}
1272
1273static std::pair<unsigned, unsigned>1274makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,1275const LangOptions &LangOpts) {1276CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts);1277unsigned Offset = SM.getFileOffset(FileRange.getBegin());1278unsigned EndOffset = SM.getFileOffset(FileRange.getEnd());1279return std::make_pair(Offset, EndOffset);1280}
1281
1282static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,1283const LangOptions &LangOpts,1284const FixItHint &InFix) {1285ASTUnit::StandaloneFixIt OutFix;1286OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);1287OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM,1288LangOpts);1289OutFix.CodeToInsert = InFix.CodeToInsert;1290OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;1291return OutFix;1292}
1293
1294static ASTUnit::StandaloneDiagnostic1295makeStandaloneDiagnostic(const LangOptions &LangOpts,1296const StoredDiagnostic &InDiag) {1297ASTUnit::StandaloneDiagnostic OutDiag;1298OutDiag.ID = InDiag.getID();1299OutDiag.Level = InDiag.getLevel();1300OutDiag.Message = std::string(InDiag.getMessage());1301OutDiag.LocOffset = 0;1302if (InDiag.getLocation().isInvalid())1303return OutDiag;1304const SourceManager &SM = InDiag.getLocation().getManager();1305SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());1306OutDiag.Filename = std::string(SM.getFilename(FileLoc));1307if (OutDiag.Filename.empty())1308return OutDiag;1309OutDiag.LocOffset = SM.getFileOffset(FileLoc);1310for (const auto &Range : InDiag.getRanges())1311OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));1312for (const auto &FixIt : InDiag.getFixIts())1313OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));1314
1315return OutDiag;1316}
1317
1318/// Attempt to build or re-use a precompiled preamble when (re-)parsing
1319/// the source file.
1320///
1321/// This routine will compute the preamble of the main source file. If a
1322/// non-trivial preamble is found, it will precompile that preamble into a
1323/// precompiled header so that the precompiled preamble can be used to reduce
1324/// reparsing time. If a precompiled preamble has already been constructed,
1325/// this routine will determine if it is still valid and, if so, avoid
1326/// rebuilding the precompiled preamble.
1327///
1328/// \param AllowRebuild When true (the default), this routine is
1329/// allowed to rebuild the precompiled preamble if it is found to be
1330/// out-of-date.
1331///
1332/// \param MaxLines When non-zero, the maximum number of lines that
1333/// can occur within the preamble.
1334///
1335/// \returns If the precompiled preamble can be used, returns a newly-allocated
1336/// buffer that should be used in place of the main file when doing so.
1337/// Otherwise, returns a NULL pointer.
1338std::unique_ptr<llvm::MemoryBuffer>1339ASTUnit::getMainBufferWithPrecompiledPreamble(1340std::shared_ptr<PCHContainerOperations> PCHContainerOps,1341CompilerInvocation &PreambleInvocationIn,1342IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,1343unsigned MaxLines) {1344auto MainFilePath =1345PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();1346std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =1347getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),1348MainFilePath, UserFilesAreVolatile);1349if (!MainFileBuffer)1350return nullptr;1351
1352PreambleBounds Bounds = ComputePreambleBounds(1353PreambleInvocationIn.getLangOpts(), *MainFileBuffer, MaxLines);1354if (!Bounds.Size)1355return nullptr;1356
1357if (Preamble) {1358if (Preamble->CanReuse(PreambleInvocationIn, *MainFileBuffer, Bounds,1359*VFS)) {1360// Okay! We can re-use the precompiled preamble.1361
1362// Set the state of the diagnostic object to mimic its state1363// after parsing the preamble.1364getDiagnostics().Reset();1365ProcessWarningOptions(getDiagnostics(),1366PreambleInvocationIn.getDiagnosticOpts());1367getDiagnostics().setNumWarnings(NumWarningsInPreamble);1368
1369PreambleRebuildCountdown = 1;1370return MainFileBuffer;1371} else {1372Preamble.reset();1373PreambleDiagnostics.clear();1374TopLevelDeclsInPreamble.clear();1375PreambleSrcLocCache.clear();1376PreambleRebuildCountdown = 1;1377}1378}1379
1380// If the preamble rebuild counter > 1, it's because we previously1381// failed to build a preamble and we're not yet ready to try1382// again. Decrement the counter and return a failure.1383if (PreambleRebuildCountdown > 1) {1384--PreambleRebuildCountdown;1385return nullptr;1386}1387
1388assert(!Preamble && "No Preamble should be stored at that point");1389// If we aren't allowed to rebuild the precompiled preamble, just1390// return now.1391if (!AllowRebuild)1392return nullptr;1393
1394++PreambleCounter;1395
1396SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone;1397SmallVector<StoredDiagnostic, 4> NewPreambleDiags;1398ASTUnitPreambleCallbacks Callbacks;1399{1400std::optional<CaptureDroppedDiagnostics> Capture;1401if (CaptureDiagnostics != CaptureDiagsKind::None)1402Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags,1403&NewPreambleDiagsStandalone);1404
1405// We did not previously compute a preamble, or it can't be reused anyway.1406SimpleTimer PreambleTimer(WantTiming);1407PreambleTimer.setOutput("Precompiling preamble");1408
1409const bool PreviousSkipFunctionBodies =1410PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;1411if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)1412PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;1413
1414llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(1415PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,1416PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath,1417Callbacks);1418
1419PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =1420PreviousSkipFunctionBodies;1421
1422if (NewPreamble) {1423Preamble = std::move(*NewPreamble);1424PreambleRebuildCountdown = 1;1425} else {1426switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {1427case BuildPreambleError::CouldntCreateTempFile:1428// Try again next time.1429PreambleRebuildCountdown = 1;1430return nullptr;1431case BuildPreambleError::CouldntCreateTargetInfo:1432case BuildPreambleError::BeginSourceFileFailed:1433case BuildPreambleError::CouldntEmitPCH:1434case BuildPreambleError::BadInputs:1435// These erros are more likely to repeat, retry after some period.1436PreambleRebuildCountdown = DefaultPreambleRebuildInterval;1437return nullptr;1438}1439llvm_unreachable("unexpected BuildPreambleError");1440}1441}1442
1443assert(Preamble && "Preamble wasn't built");1444
1445TopLevelDecls.clear();1446TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs();1447PreambleTopLevelHashValue = Callbacks.getHash();1448
1449NumWarningsInPreamble = getDiagnostics().getNumWarnings();1450
1451checkAndRemoveNonDriverDiags(NewPreambleDiags);1452StoredDiagnostics = std::move(NewPreambleDiags);1453PreambleDiagnostics = std::move(NewPreambleDiagsStandalone);1454
1455// If the hash of top-level entities differs from the hash of the top-level1456// entities the last time we rebuilt the preamble, clear out the completion1457// cache.1458if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {1459CompletionCacheTopLevelHashValue = 0;1460PreambleTopLevelHashValue = CurrentTopLevelHashValue;1461}1462
1463return MainFileBuffer;1464}
1465
1466void ASTUnit::RealizeTopLevelDeclsFromPreamble() {1467assert(Preamble && "Should only be called when preamble was built");1468
1469std::vector<Decl *> Resolved;1470Resolved.reserve(TopLevelDeclsInPreamble.size());1471// The module file of the preamble.1472serialization::ModuleFile &MF = Reader->getModuleManager().getPrimaryModule();1473for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {1474// Resolve the declaration ID to an actual declaration, possibly1475// deserializing the declaration in the process.1476if (Decl *D = Reader->GetLocalDecl(MF, TopLevelDecl))1477Resolved.push_back(D);1478}1479TopLevelDeclsInPreamble.clear();1480TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());1481}
1482
1483void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {1484// Steal the created target, context, and preprocessor if they have been1485// created.1486assert(CI.hasInvocation() && "missing invocation");1487LangOpts = CI.getInvocation().LangOpts;1488TheSema = CI.takeSema();1489Consumer = CI.takeASTConsumer();1490if (CI.hasASTContext())1491Ctx = &CI.getASTContext();1492if (CI.hasPreprocessor())1493PP = CI.getPreprocessorPtr();1494CI.setSourceManager(nullptr);1495CI.setFileManager(nullptr);1496if (CI.hasTarget())1497Target = &CI.getTarget();1498Reader = CI.getASTReader();1499HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();1500}
1501
1502StringRef ASTUnit::getMainFileName() const {1503if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) {1504const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0];1505if (Input.isFile())1506return Input.getFile();1507else1508return Input.getBuffer().getBufferIdentifier();1509}1510
1511if (SourceMgr) {1512if (OptionalFileEntryRef FE =1513SourceMgr->getFileEntryRefForID(SourceMgr->getMainFileID()))1514return FE->getName();1515}1516
1517return {};1518}
1519
1520StringRef ASTUnit::getASTFileName() const {1521if (!isMainFileAST())1522return {};1523
1524serialization::ModuleFile &1525Mod = Reader->getModuleManager().getPrimaryModule();1526return Mod.FileName;1527}
1528
1529std::unique_ptr<ASTUnit>1530ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,1531IntrusiveRefCntPtr<DiagnosticsEngine> Diags,1532CaptureDiagsKind CaptureDiagnostics,1533bool UserFilesAreVolatile) {1534std::unique_ptr<ASTUnit> AST(new ASTUnit(false));1535ConfigureDiags(Diags, *AST, CaptureDiagnostics);1536IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =1537createVFSFromCompilerInvocation(*CI, *Diags);1538AST->Diagnostics = Diags;1539AST->FileSystemOpts = CI->getFileSystemOpts();1540AST->Invocation = std::move(CI);1541AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);1542AST->UserFilesAreVolatile = UserFilesAreVolatile;1543AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,1544UserFilesAreVolatile);1545AST->ModuleCache = new InMemoryModuleCache;1546
1547return AST;1548}
1549
1550ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(1551std::shared_ptr<CompilerInvocation> CI,1552std::shared_ptr<PCHContainerOperations> PCHContainerOps,1553IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action,1554ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,1555bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1556unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,1557bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {1558assert(CI && "A CompilerInvocation is required");1559
1560std::unique_ptr<ASTUnit> OwnAST;1561ASTUnit *AST = Unit;1562if (!AST) {1563// Create the AST unit.1564OwnAST = create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile);1565AST = OwnAST.get();1566if (!AST)1567return nullptr;1568}1569
1570if (!ResourceFilesPath.empty()) {1571// Override the resources path.1572CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);1573}1574AST->OnlyLocalDecls = OnlyLocalDecls;1575AST->CaptureDiagnostics = CaptureDiagnostics;1576if (PrecompilePreambleAfterNParses > 0)1577AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses;1578AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;1579AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1580AST->IncludeBriefCommentsInCodeCompletion = false;1581
1582// Recover resources if we crash before exiting this method.1583llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1584ASTUnitCleanup(OwnAST.get());1585llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,1586llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>1587DiagCleanup(Diags.get());1588
1589// We'll manage file buffers ourselves.1590CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;1591CI->getFrontendOpts().DisableFree = false;1592ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());1593
1594// Create the compiler instance to use for building the AST.1595std::unique_ptr<CompilerInstance> Clang(1596new CompilerInstance(std::move(PCHContainerOps)));1597
1598// Recover resources if we crash before exiting this method.1599llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>1600CICleanup(Clang.get());1601
1602Clang->setInvocation(std::move(CI));1603AST->OriginalSourceFile =1604std::string(Clang->getFrontendOpts().Inputs[0].getFile());1605
1606// Set up diagnostics, capturing any diagnostics that would1607// otherwise be dropped.1608Clang->setDiagnostics(&AST->getDiagnostics());1609
1610// Create the target instance.1611if (!Clang->createTarget())1612return nullptr;1613
1614assert(Clang->getFrontendOpts().Inputs.size() == 1 &&1615"Invocation must have exactly one source file!");1616assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==1617InputKind::Source &&1618"FIXME: AST inputs not yet supported here!");1619assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=1620Language::LLVM_IR &&1621"IR inputs not support here!");1622
1623// Configure the various subsystems.1624AST->TheSema.reset();1625AST->Ctx = nullptr;1626AST->PP = nullptr;1627AST->Reader = nullptr;1628
1629// Create a file manager object to provide access to and cache the filesystem.1630Clang->setFileManager(&AST->getFileManager());1631
1632// Create the source manager.1633Clang->setSourceManager(&AST->getSourceManager());1634
1635FrontendAction *Act = Action;1636
1637std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct;1638if (!Act) {1639TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));1640Act = TrackerAct.get();1641}1642
1643// Recover resources if we crash before exiting this method.1644llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>1645ActCleanup(TrackerAct.get());1646
1647if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {1648AST->transferASTDataFromCompilerInstance(*Clang);1649if (OwnAST && ErrAST)1650ErrAST->swap(OwnAST);1651
1652return nullptr;1653}1654
1655if (Persistent && !TrackerAct) {1656Clang->getPreprocessor().addPPCallbacks(1657std::make_unique<MacroDefinitionTrackerPPCallbacks>(1658AST->getCurrentTopLevelHashValue()));1659std::vector<std::unique_ptr<ASTConsumer>> Consumers;1660if (Clang->hasASTConsumer())1661Consumers.push_back(Clang->takeASTConsumer());1662Consumers.push_back(std::make_unique<TopLevelDeclTrackerConsumer>(1663*AST, AST->getCurrentTopLevelHashValue()));1664Clang->setASTConsumer(1665std::make_unique<MultiplexConsumer>(std::move(Consumers)));1666}1667if (llvm::Error Err = Act->Execute()) {1668consumeError(std::move(Err)); // FIXME this drops errors on the floor.1669AST->transferASTDataFromCompilerInstance(*Clang);1670if (OwnAST && ErrAST)1671ErrAST->swap(OwnAST);1672
1673return nullptr;1674}1675
1676// Steal the created target, context, and preprocessor.1677AST->transferASTDataFromCompilerInstance(*Clang);1678
1679Act->EndSourceFile();1680
1681if (OwnAST)1682return OwnAST.release();1683else1684return AST;1685}
1686
1687bool ASTUnit::LoadFromCompilerInvocation(1688std::shared_ptr<PCHContainerOperations> PCHContainerOps,1689unsigned PrecompilePreambleAfterNParses,1690IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1691if (!Invocation)1692return true;1693
1694assert(VFS && "VFS is null");1695
1696// We'll manage file buffers ourselves.1697Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;1698Invocation->getFrontendOpts().DisableFree = false;1699getDiagnostics().Reset();1700ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());1701
1702std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;1703if (PrecompilePreambleAfterNParses > 0) {1704PreambleRebuildCountdown = PrecompilePreambleAfterNParses;1705OverrideMainBuffer =1706getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);1707getDiagnostics().Reset();1708ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());1709}1710
1711SimpleTimer ParsingTimer(WantTiming);1712ParsingTimer.setOutput("Parsing " + getMainFileName());1713
1714// Recover resources if we crash before exiting this method.1715llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>1716MemBufferCleanup(OverrideMainBuffer.get());1717
1718return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);1719}
1720
1721std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(1722std::shared_ptr<CompilerInvocation> CI,1723std::shared_ptr<PCHContainerOperations> PCHContainerOps,1724IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,1725bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1726unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,1727bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,1728bool UserFilesAreVolatile) {1729// Create the AST unit.1730std::unique_ptr<ASTUnit> AST(new ASTUnit(false));1731ConfigureDiags(Diags, *AST, CaptureDiagnostics);1732AST->Diagnostics = Diags;1733AST->OnlyLocalDecls = OnlyLocalDecls;1734AST->CaptureDiagnostics = CaptureDiagnostics;1735AST->TUKind = TUKind;1736AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1737AST->IncludeBriefCommentsInCodeCompletion1738= IncludeBriefCommentsInCodeCompletion;1739AST->Invocation = std::move(CI);1740AST->FileSystemOpts = FileMgr->getFileSystemOpts();1741AST->FileMgr = FileMgr;1742AST->UserFilesAreVolatile = UserFilesAreVolatile;1743
1744// Recover resources if we crash before exiting this method.1745llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1746ASTUnitCleanup(AST.get());1747llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,1748llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>1749DiagCleanup(Diags.get());1750
1751if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),1752PrecompilePreambleAfterNParses,1753&AST->FileMgr->getVirtualFileSystem()))1754return nullptr;1755return AST;1756}
1757
1758std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(1759const char **ArgBegin, const char **ArgEnd,1760std::shared_ptr<PCHContainerOperations> PCHContainerOps,1761IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,1762bool StorePreamblesInMemory, StringRef PreambleStoragePath,1763bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1764ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,1765unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,1766bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,1767bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,1768bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,1769bool RetainExcludedConditionalBlocks, std::optional<StringRef> ModuleFormat,1770std::unique_ptr<ASTUnit> *ErrAST,1771IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1772assert(Diags.get() && "no DiagnosticsEngine was provided");1773
1774// If no VFS was provided, create one that tracks the physical file system.1775// If '-working-directory' was passed as an argument, 'createInvocation' will1776// set this as the current working directory of the VFS.1777if (!VFS)1778VFS = llvm::vfs::createPhysicalFileSystem();1779
1780SmallVector<StoredDiagnostic, 4> StoredDiagnostics;1781
1782std::shared_ptr<CompilerInvocation> CI;1783
1784{1785CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,1786&StoredDiagnostics, nullptr);1787
1788CreateInvocationOptions CIOpts;1789CIOpts.VFS = VFS;1790CIOpts.Diags = Diags;1791CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?1792CI = createInvocation(llvm::ArrayRef(ArgBegin, ArgEnd), std::move(CIOpts));1793if (!CI)1794return nullptr;1795}1796
1797// Override any files that need remapping1798for (const auto &RemappedFile : RemappedFiles) {1799CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,1800RemappedFile.second);1801}1802PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();1803PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;1804PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;1805PPOpts.SingleFileParseMode = SingleFileParse;1806PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;1807
1808// Override the resources path.1809CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);1810
1811CI->getFrontendOpts().SkipFunctionBodies =1812SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;1813
1814if (ModuleFormat)1815CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat);1816
1817// Create the AST unit.1818std::unique_ptr<ASTUnit> AST;1819AST.reset(new ASTUnit(false));1820AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();1821AST->StoredDiagnostics.swap(StoredDiagnostics);1822ConfigureDiags(Diags, *AST, CaptureDiagnostics);1823AST->Diagnostics = Diags;1824AST->FileSystemOpts = CI->getFileSystemOpts();1825VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);1826AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);1827AST->StorePreamblesInMemory = StorePreamblesInMemory;1828AST->PreambleStoragePath = PreambleStoragePath;1829AST->ModuleCache = new InMemoryModuleCache;1830AST->OnlyLocalDecls = OnlyLocalDecls;1831AST->CaptureDiagnostics = CaptureDiagnostics;1832AST->TUKind = TUKind;1833AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1834AST->IncludeBriefCommentsInCodeCompletion1835= IncludeBriefCommentsInCodeCompletion;1836AST->UserFilesAreVolatile = UserFilesAreVolatile;1837AST->Invocation = CI;1838AST->SkipFunctionBodies = SkipFunctionBodies;1839if (ForSerialization)1840AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache));1841// Zero out now to ease cleanup during crash recovery.1842CI = nullptr;1843Diags = nullptr;1844
1845// Recover resources if we crash before exiting this method.1846llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1847ASTUnitCleanup(AST.get());1848
1849if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),1850PrecompilePreambleAfterNParses,1851VFS)) {1852// Some error occurred, if caller wants to examine diagnostics, pass it the1853// ASTUnit.1854if (ErrAST) {1855AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);1856ErrAST->swap(AST);1857}1858return nullptr;1859}1860
1861return AST;1862}
1863
1864bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,1865ArrayRef<RemappedFile> RemappedFiles,1866IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1867if (!Invocation)1868return true;1869
1870if (!VFS) {1871assert(FileMgr && "FileMgr is null on Reparse call");1872VFS = &FileMgr->getVirtualFileSystem();1873}1874
1875clearFileLevelDecls();1876
1877SimpleTimer ParsingTimer(WantTiming);1878ParsingTimer.setOutput("Reparsing " + getMainFileName());1879
1880// Remap files.1881PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();1882for (const auto &RB : PPOpts.RemappedFileBuffers)1883delete RB.second;1884
1885Invocation->getPreprocessorOpts().clearRemappedFiles();1886for (const auto &RemappedFile : RemappedFiles) {1887Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first,1888RemappedFile.second);1889}1890
1891// If we have a preamble file lying around, or if we might try to1892// build a precompiled preamble, do so now.1893std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;1894if (Preamble || PreambleRebuildCountdown > 0)1895OverrideMainBuffer =1896getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);1897
1898// Clear out the diagnostics state.1899FileMgr.reset();1900getDiagnostics().Reset();1901ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());1902if (OverrideMainBuffer)1903getDiagnostics().setNumWarnings(NumWarningsInPreamble);1904
1905// Parse the sources1906bool Result =1907Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);1908
1909// If we're caching global code-completion results, and the top-level1910// declarations have changed, clear out the code-completion cache.1911if (!Result && ShouldCacheCodeCompletionResults &&1912CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)1913CacheCodeCompletionResults();1914
1915// We now need to clear out the completion info related to this translation1916// unit; it'll be recreated if necessary.1917CCTUInfo.reset();1918
1919return Result;1920}
1921
1922void ASTUnit::ResetForParse() {1923SavedMainFileBuffer.reset();1924
1925SourceMgr.reset();1926TheSema.reset();1927Ctx.reset();1928PP.reset();1929Reader.reset();1930
1931TopLevelDecls.clear();1932clearFileLevelDecls();1933}
1934
1935//----------------------------------------------------------------------------//
1936// Code completion
1937//----------------------------------------------------------------------------//
1938
1939namespace {1940
1941/// Code completion consumer that combines the cached code-completion1942/// results from an ASTUnit with the code-completion results provided to it,1943/// then passes the result on to1944class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {1945uint64_t NormalContexts;1946ASTUnit &AST;1947CodeCompleteConsumer &Next;1948
1949public:1950AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,1951const CodeCompleteOptions &CodeCompleteOpts)1952: CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) {1953// Compute the set of contexts in which we will look when we don't have1954// any information about the specific context.1955NormalContexts
1956= (1LL << CodeCompletionContext::CCC_TopLevel)1957| (1LL << CodeCompletionContext::CCC_ObjCInterface)1958| (1LL << CodeCompletionContext::CCC_ObjCImplementation)1959| (1LL << CodeCompletionContext::CCC_ObjCIvarList)1960| (1LL << CodeCompletionContext::CCC_Statement)1961| (1LL << CodeCompletionContext::CCC_Expression)1962| (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)1963| (1LL << CodeCompletionContext::CCC_DotMemberAccess)1964| (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)1965| (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)1966| (1LL << CodeCompletionContext::CCC_ObjCProtocolName)1967| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)1968| (1LL << CodeCompletionContext::CCC_Recovery);1969
1970if (AST.getASTContext().getLangOpts().CPlusPlus)1971NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)1972| (1LL << CodeCompletionContext::CCC_UnionTag)1973| (1LL << CodeCompletionContext::CCC_ClassOrStructTag);1974}1975
1976void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,1977CodeCompletionResult *Results,1978unsigned NumResults) override;1979
1980void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,1981OverloadCandidate *Candidates,1982unsigned NumCandidates,1983SourceLocation OpenParLoc,1984bool Braced) override {1985Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,1986OpenParLoc, Braced);1987}1988
1989CodeCompletionAllocator &getAllocator() override {1990return Next.getAllocator();1991}1992
1993CodeCompletionTUInfo &getCodeCompletionTUInfo() override {1994return Next.getCodeCompletionTUInfo();1995}1996};1997
1998} // namespace1999
2000/// Helper function that computes which global names are hidden by the
2001/// local code-completion results.
2002static void CalculateHiddenNames(const CodeCompletionContext &Context,2003CodeCompletionResult *Results,2004unsigned NumResults,2005ASTContext &Ctx,2006llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){2007bool OnlyTagNames = false;2008switch (Context.getKind()) {2009case CodeCompletionContext::CCC_Recovery:2010case CodeCompletionContext::CCC_TopLevel:2011case CodeCompletionContext::CCC_ObjCInterface:2012case CodeCompletionContext::CCC_ObjCImplementation:2013case CodeCompletionContext::CCC_ObjCIvarList:2014case CodeCompletionContext::CCC_ClassStructUnion:2015case CodeCompletionContext::CCC_Statement:2016case CodeCompletionContext::CCC_Expression:2017case CodeCompletionContext::CCC_ObjCMessageReceiver:2018case CodeCompletionContext::CCC_DotMemberAccess:2019case CodeCompletionContext::CCC_ArrowMemberAccess:2020case CodeCompletionContext::CCC_ObjCPropertyAccess:2021case CodeCompletionContext::CCC_Namespace:2022case CodeCompletionContext::CCC_Type:2023case CodeCompletionContext::CCC_Symbol:2024case CodeCompletionContext::CCC_SymbolOrNewName:2025case CodeCompletionContext::CCC_ParenthesizedExpression:2026case CodeCompletionContext::CCC_ObjCInterfaceName:2027case CodeCompletionContext::CCC_TopLevelOrExpression:2028break;2029
2030case CodeCompletionContext::CCC_EnumTag:2031case CodeCompletionContext::CCC_UnionTag:2032case CodeCompletionContext::CCC_ClassOrStructTag:2033OnlyTagNames = true;2034break;2035
2036case CodeCompletionContext::CCC_ObjCProtocolName:2037case CodeCompletionContext::CCC_MacroName:2038case CodeCompletionContext::CCC_MacroNameUse:2039case CodeCompletionContext::CCC_PreprocessorExpression:2040case CodeCompletionContext::CCC_PreprocessorDirective:2041case CodeCompletionContext::CCC_NaturalLanguage:2042case CodeCompletionContext::CCC_SelectorName:2043case CodeCompletionContext::CCC_TypeQualifiers:2044case CodeCompletionContext::CCC_Other:2045case CodeCompletionContext::CCC_OtherWithMacros:2046case CodeCompletionContext::CCC_ObjCInstanceMessage:2047case CodeCompletionContext::CCC_ObjCClassMessage:2048case CodeCompletionContext::CCC_ObjCCategoryName:2049case CodeCompletionContext::CCC_IncludedFile:2050case CodeCompletionContext::CCC_Attribute:2051case CodeCompletionContext::CCC_NewName:2052case CodeCompletionContext::CCC_ObjCClassForwardDecl:2053// We're looking for nothing, or we're looking for names that cannot2054// be hidden.2055return;2056}2057
2058using Result = CodeCompletionResult;2059for (unsigned I = 0; I != NumResults; ++I) {2060if (Results[I].Kind != Result::RK_Declaration)2061continue;2062
2063unsigned IDNS2064= Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();2065
2066bool Hiding = false;2067if (OnlyTagNames)2068Hiding = (IDNS & Decl::IDNS_Tag);2069else {2070unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |2071Decl::IDNS_Namespace | Decl::IDNS_Ordinary |2072Decl::IDNS_NonMemberOperator);2073if (Ctx.getLangOpts().CPlusPlus)2074HiddenIDNS |= Decl::IDNS_Tag;2075Hiding = (IDNS & HiddenIDNS);2076}2077
2078if (!Hiding)2079continue;2080
2081DeclarationName Name = Results[I].Declaration->getDeclName();2082if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())2083HiddenNames.insert(Identifier->getName());2084else2085HiddenNames.insert(Name.getAsString());2086}2087}
2088
2089void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,2090CodeCompletionContext Context,2091CodeCompletionResult *Results,2092unsigned NumResults) {2093// Merge the results we were given with the results we cached.2094bool AddedResult = false;2095uint64_t InContexts =2096Context.getKind() == CodeCompletionContext::CCC_Recovery2097? NormalContexts : (1LL << Context.getKind());2098// Contains the set of names that are hidden by "local" completion results.2099llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;2100using Result = CodeCompletionResult;2101SmallVector<Result, 8> AllResults;2102for (ASTUnit::cached_completion_iterator2103C = AST.cached_completion_begin(),2104CEnd = AST.cached_completion_end();2105C != CEnd; ++C) {2106// If the context we are in matches any of the contexts we are2107// interested in, we'll add this result.2108if ((C->ShowInContexts & InContexts) == 0)2109continue;2110
2111// If we haven't added any results previously, do so now.2112if (!AddedResult) {2113CalculateHiddenNames(Context, Results, NumResults, S.Context,2114HiddenNames);2115AllResults.insert(AllResults.end(), Results, Results + NumResults);2116AddedResult = true;2117}2118
2119// Determine whether this global completion result is hidden by a local2120// completion result. If so, skip it.2121if (C->Kind != CXCursor_MacroDefinition &&2122HiddenNames.count(C->Completion->getTypedText()))2123continue;2124
2125// Adjust priority based on similar type classes.2126unsigned Priority = C->Priority;2127CodeCompletionString *Completion = C->Completion;2128if (!Context.getPreferredType().isNull()) {2129if (C->Kind == CXCursor_MacroDefinition) {2130Priority = getMacroUsagePriority(C->Completion->getTypedText(),2131S.getLangOpts(),2132Context.getPreferredType()->isAnyPointerType());2133} else if (C->Type) {2134CanQualType Expected
2135= S.Context.getCanonicalType(2136Context.getPreferredType().getUnqualifiedType());2137SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);2138if (ExpectedSTC == C->TypeClass) {2139// We know this type is similar; check for an exact match.2140llvm::StringMap<unsigned> &CachedCompletionTypes2141= AST.getCachedCompletionTypes();2142llvm::StringMap<unsigned>::iterator Pos2143= CachedCompletionTypes.find(QualType(Expected).getAsString());2144if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)2145Priority /= CCF_ExactTypeMatch;2146else2147Priority /= CCF_SimilarTypeMatch;2148}2149}2150}2151
2152// Adjust the completion string, if required.2153if (C->Kind == CXCursor_MacroDefinition &&2154Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {2155// Create a new code-completion string that just contains the2156// macro name, without its arguments.2157CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),2158CCP_CodePattern, C->Availability);2159Builder.AddTypedTextChunk(C->Completion->getTypedText());2160Priority = CCP_CodePattern;2161Completion = Builder.TakeString();2162}2163
2164AllResults.push_back(Result(Completion, Priority, C->Kind,2165C->Availability));2166}2167
2168// If we did not add any cached completion results, just forward the2169// results we were given to the next consumer.2170if (!AddedResult) {2171Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);2172return;2173}2174
2175Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),2176AllResults.size());2177}
2178
2179void ASTUnit::CodeComplete(2180StringRef File, unsigned Line, unsigned Column,2181ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,2182bool IncludeCodePatterns, bool IncludeBriefComments,2183CodeCompleteConsumer &Consumer,2184std::shared_ptr<PCHContainerOperations> PCHContainerOps,2185DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,2186FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,2187SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers,2188std::unique_ptr<SyntaxOnlyAction> Act) {2189if (!Invocation)2190return;2191
2192SimpleTimer CompletionTimer(WantTiming);2193CompletionTimer.setOutput("Code completion @ " + File + ":" +2194Twine(Line) + ":" + Twine(Column));2195
2196auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);2197
2198FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();2199CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;2200PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();2201
2202CodeCompleteOpts.IncludeMacros = IncludeMacros &&2203CachedCompletionResults.empty();2204CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;2205CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();2206CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;2207CodeCompleteOpts.LoadExternal = Consumer.loadExternal();2208CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts();2209
2210assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);2211
2212FrontendOpts.CodeCompletionAt.FileName = std::string(File);2213FrontendOpts.CodeCompletionAt.Line = Line;2214FrontendOpts.CodeCompletionAt.Column = Column;2215
2216// Set the language options appropriately.2217LangOpts = CCInvocation->getLangOpts();2218
2219// Spell-checking and warnings are wasteful during code-completion.2220LangOpts.SpellChecking = false;2221CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;2222
2223std::unique_ptr<CompilerInstance> Clang(2224new CompilerInstance(PCHContainerOps));2225
2226// Recover resources if we crash before exiting this method.2227llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>2228CICleanup(Clang.get());2229
2230auto &Inv = *CCInvocation;2231Clang->setInvocation(std::move(CCInvocation));2232OriginalSourceFile =2233std::string(Clang->getFrontendOpts().Inputs[0].getFile());2234
2235// Set up diagnostics, capturing any diagnostics produced.2236Clang->setDiagnostics(&Diag);2237CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All,2238Clang->getDiagnostics(),2239&StoredDiagnostics, nullptr);2240ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());2241
2242// Create the target instance.2243if (!Clang->createTarget()) {2244Clang->setInvocation(nullptr);2245return;2246}2247
2248assert(Clang->getFrontendOpts().Inputs.size() == 1 &&2249"Invocation must have exactly one source file!");2250assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==2251InputKind::Source &&2252"FIXME: AST inputs not yet supported here!");2253assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=2254Language::LLVM_IR &&2255"IR inputs not support here!");2256
2257// Use the source and file managers that we were given.2258Clang->setFileManager(&FileMgr);2259Clang->setSourceManager(&SourceMgr);2260
2261// Remap files.2262PreprocessorOpts.clearRemappedFiles();2263PreprocessorOpts.RetainRemappedFileBuffers = true;2264for (const auto &RemappedFile : RemappedFiles) {2265PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second);2266OwnedBuffers.push_back(RemappedFile.second);2267}2268
2269// Use the code completion consumer we were given, but adding any cached2270// code-completion results.2271AugmentedCodeCompleteConsumer *AugmentedConsumer2272= new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);2273Clang->setCodeCompletionConsumer(AugmentedConsumer);2274
2275auto getUniqueID =2276[&FileMgr](StringRef Filename) -> std::optional<llvm::sys::fs::UniqueID> {2277if (auto Status = FileMgr.getVirtualFileSystem().status(Filename))2278return Status->getUniqueID();2279return std::nullopt;2280};2281
2282auto hasSameUniqueID = [getUniqueID](StringRef LHS, StringRef RHS) {2283if (LHS == RHS)2284return true;2285if (auto LHSID = getUniqueID(LHS))2286if (auto RHSID = getUniqueID(RHS))2287return *LHSID == *RHSID;2288return false;2289};2290
2291// If we have a precompiled preamble, try to use it. We only allow2292// the use of the precompiled preamble if we're if the completion2293// point is within the main file, after the end of the precompiled2294// preamble.2295std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;2296if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) {2297OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(2298PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1);2299}2300
2301// If the main file has been overridden due to the use of a preamble,2302// make that override happen and introduce the preamble.2303if (OverrideMainBuffer) {2304assert(Preamble &&2305"No preamble was built, but OverrideMainBuffer is not null");2306
2307IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =2308&FileMgr.getVirtualFileSystem();2309Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,2310OverrideMainBuffer.get());2311// FIXME: there is no way to update VFS if it was changed by2312// AddImplicitPreamble as FileMgr is accepted as a parameter by this method.2313// We use on-disk preambles instead and rely on FileMgr's VFS to ensure the2314// PCH files are always readable.2315OwnedBuffers.push_back(OverrideMainBuffer.release());2316} else {2317PreprocessorOpts.PrecompiledPreambleBytes.first = 0;2318PreprocessorOpts.PrecompiledPreambleBytes.second = false;2319}2320
2321// Disable the preprocessing record if modules are not enabled.2322if (!Clang->getLangOpts().Modules)2323PreprocessorOpts.DetailedRecord = false;2324
2325if (!Act)2326Act.reset(new SyntaxOnlyAction);2327
2328if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {2329if (llvm::Error Err = Act->Execute()) {2330consumeError(std::move(Err)); // FIXME this drops errors on the floor.2331}2332Act->EndSourceFile();2333}2334}
2335
2336bool ASTUnit::Save(StringRef File) {2337if (HadModuleLoaderFatalFailure)2338return true;2339
2340// FIXME: Can we somehow regenerate the stat cache here, or do we need to2341// unconditionally create a stat cache when we parse the file?2342
2343if (llvm::Error Err = llvm::writeToOutput(2344File, [this](llvm::raw_ostream &Out) {2345return serialize(Out) ? llvm::make_error<llvm::StringError>(2346"ASTUnit serialization failed",2347llvm::inconvertibleErrorCode())2348: llvm::Error::success();2349})) {2350consumeError(std::move(Err));2351return true;2352}2353return false;2354}
2355
2356static bool serializeUnit(ASTWriter &Writer, SmallVectorImpl<char> &Buffer,2357Sema &S, raw_ostream &OS) {2358Writer.WriteAST(S, std::string(), nullptr, "");2359
2360// Write the generated bitstream to "Out".2361if (!Buffer.empty())2362OS.write(Buffer.data(), Buffer.size());2363
2364return false;2365}
2366
2367bool ASTUnit::serialize(raw_ostream &OS) {2368if (WriterData)2369return serializeUnit(WriterData->Writer, WriterData->Buffer, getSema(), OS);2370
2371SmallString<128> Buffer;2372llvm::BitstreamWriter Stream(Buffer);2373InMemoryModuleCache ModuleCache;2374ASTWriter Writer(Stream, Buffer, ModuleCache, {});2375return serializeUnit(Writer, Buffer, getSema(), OS);2376}
2377
2378void ASTUnit::TranslateStoredDiagnostics(2379FileManager &FileMgr,2380SourceManager &SrcMgr,2381const SmallVectorImpl<StandaloneDiagnostic> &Diags,2382SmallVectorImpl<StoredDiagnostic> &Out) {2383// Map the standalone diagnostic into the new source manager. We also need to2384// remap all the locations to the new view. This includes the diag location,2385// any associated source ranges, and the source ranges of associated fix-its.2386// FIXME: There should be a cleaner way to do this.2387SmallVector<StoredDiagnostic, 4> Result;2388Result.reserve(Diags.size());2389
2390for (const auto &SD : Diags) {2391// Rebuild the StoredDiagnostic.2392if (SD.Filename.empty())2393continue;2394auto FE = FileMgr.getFile(SD.Filename);2395if (!FE)2396continue;2397SourceLocation FileLoc;2398auto ItFileID = PreambleSrcLocCache.find(SD.Filename);2399if (ItFileID == PreambleSrcLocCache.end()) {2400FileID FID = SrcMgr.translateFile(*FE);2401FileLoc = SrcMgr.getLocForStartOfFile(FID);2402PreambleSrcLocCache[SD.Filename] = FileLoc;2403} else {2404FileLoc = ItFileID->getValue();2405}2406
2407if (FileLoc.isInvalid())2408continue;2409SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);2410FullSourceLoc Loc(L, SrcMgr);2411
2412SmallVector<CharSourceRange, 4> Ranges;2413Ranges.reserve(SD.Ranges.size());2414for (const auto &Range : SD.Ranges) {2415SourceLocation BL = FileLoc.getLocWithOffset(Range.first);2416SourceLocation EL = FileLoc.getLocWithOffset(Range.second);2417Ranges.push_back(CharSourceRange::getCharRange(BL, EL));2418}2419
2420SmallVector<FixItHint, 2> FixIts;2421FixIts.reserve(SD.FixIts.size());2422for (const auto &FixIt : SD.FixIts) {2423FixIts.push_back(FixItHint());2424FixItHint &FH = FixIts.back();2425FH.CodeToInsert = FixIt.CodeToInsert;2426SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first);2427SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second);2428FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);2429}2430
2431Result.push_back(StoredDiagnostic(SD.Level, SD.ID,2432SD.Message, Loc, Ranges, FixIts));2433}2434Result.swap(Out);2435}
2436
2437void ASTUnit::addFileLevelDecl(Decl *D) {2438assert(D);2439
2440// We only care about local declarations.2441if (D->isFromASTFile())2442return;2443
2444SourceManager &SM = *SourceMgr;2445SourceLocation Loc = D->getLocation();2446if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc))2447return;2448
2449// We only keep track of the file-level declarations of each file.2450if (!D->getLexicalDeclContext()->isFileContext())2451return;2452
2453SourceLocation FileLoc = SM.getFileLoc(Loc);2454assert(SM.isLocalSourceLocation(FileLoc));2455FileID FID;2456unsigned Offset;2457std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);2458if (FID.isInvalid())2459return;2460
2461std::unique_ptr<LocDeclsTy> &Decls = FileDecls[FID];2462if (!Decls)2463Decls = std::make_unique<LocDeclsTy>();2464
2465std::pair<unsigned, Decl *> LocDecl(Offset, D);2466
2467if (Decls->empty() || Decls->back().first <= Offset) {2468Decls->push_back(LocDecl);2469return;2470}2471
2472LocDeclsTy::iterator I =2473llvm::upper_bound(*Decls, LocDecl, llvm::less_first());2474
2475Decls->insert(I, LocDecl);2476}
2477
2478void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,2479SmallVectorImpl<Decl *> &Decls) {2480if (File.isInvalid())2481return;2482
2483if (SourceMgr->isLoadedFileID(File)) {2484assert(Ctx->getExternalSource() && "No external source!");2485return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length,2486Decls);2487}2488
2489FileDeclsTy::iterator I = FileDecls.find(File);2490if (I == FileDecls.end())2491return;2492
2493LocDeclsTy &LocDecls = *I->second;2494if (LocDecls.empty())2495return;2496
2497LocDeclsTy::iterator BeginIt =2498llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) {2499return LD.first < Offset;2500});2501if (BeginIt != LocDecls.begin())2502--BeginIt;2503
2504// If we are pointing at a top-level decl inside an objc container, we need2505// to backtrack until we find it otherwise we will fail to report that the2506// region overlaps with an objc container.2507while (BeginIt != LocDecls.begin() &&2508BeginIt->second->isTopLevelDeclInObjCContainer())2509--BeginIt;2510
2511LocDeclsTy::iterator EndIt = llvm::upper_bound(2512LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr),2513llvm::less_first());2514if (EndIt != LocDecls.end())2515++EndIt;2516
2517for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)2518Decls.push_back(DIt->second);2519}
2520
2521SourceLocation ASTUnit::getLocation(const FileEntry *File,2522unsigned Line, unsigned Col) const {2523const SourceManager &SM = getSourceManager();2524SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);2525return SM.getMacroArgExpandedLocation(Loc);2526}
2527
2528SourceLocation ASTUnit::getLocation(const FileEntry *File,2529unsigned Offset) const {2530const SourceManager &SM = getSourceManager();2531SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);2532return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));2533}
2534
2535/// If \arg Loc is a loaded location from the preamble, returns
2536/// the corresponding local location of the main file, otherwise it returns
2537/// \arg Loc.
2538SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {2539FileID PreambleID;2540if (SourceMgr)2541PreambleID = SourceMgr->getPreambleFileID();2542
2543if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())2544return Loc;2545
2546unsigned Offs;2547if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) {2548SourceLocation FileLoc
2549= SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());2550return FileLoc.getLocWithOffset(Offs);2551}2552
2553return Loc;2554}
2555
2556/// If \arg Loc is a local location of the main file but inside the
2557/// preamble chunk, returns the corresponding loaded location from the
2558/// preamble, otherwise it returns \arg Loc.
2559SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {2560FileID PreambleID;2561if (SourceMgr)2562PreambleID = SourceMgr->getPreambleFileID();2563
2564if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())2565return Loc;2566
2567unsigned Offs;2568if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&2569Offs < Preamble->getBounds().Size) {2570SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);2571return FileLoc.getLocWithOffset(Offs);2572}2573
2574return Loc;2575}
2576
2577bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {2578FileID FID;2579if (SourceMgr)2580FID = SourceMgr->getPreambleFileID();2581
2582if (Loc.isInvalid() || FID.isInvalid())2583return false;2584
2585return SourceMgr->isInFileID(Loc, FID);2586}
2587
2588bool ASTUnit::isInMainFileID(SourceLocation Loc) const {2589FileID FID;2590if (SourceMgr)2591FID = SourceMgr->getMainFileID();2592
2593if (Loc.isInvalid() || FID.isInvalid())2594return false;2595
2596return SourceMgr->isInFileID(Loc, FID);2597}
2598
2599SourceLocation ASTUnit::getEndOfPreambleFileID() const {2600FileID FID;2601if (SourceMgr)2602FID = SourceMgr->getPreambleFileID();2603
2604if (FID.isInvalid())2605return {};2606
2607return SourceMgr->getLocForEndOfFile(FID);2608}
2609
2610SourceLocation ASTUnit::getStartOfMainFileID() const {2611FileID FID;2612if (SourceMgr)2613FID = SourceMgr->getMainFileID();2614
2615if (FID.isInvalid())2616return {};2617
2618return SourceMgr->getLocForStartOfFile(FID);2619}
2620
2621llvm::iterator_range<PreprocessingRecord::iterator>2622ASTUnit::getLocalPreprocessingEntities() const {2623if (isMainFileAST()) {2624serialization::ModuleFile &2625Mod = Reader->getModuleManager().getPrimaryModule();2626return Reader->getModulePreprocessedEntities(Mod);2627}2628
2629if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())2630return llvm::make_range(PPRec->local_begin(), PPRec->local_end());2631
2632return llvm::make_range(PreprocessingRecord::iterator(),2633PreprocessingRecord::iterator());2634}
2635
2636bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {2637if (isMainFileAST()) {2638serialization::ModuleFile &2639Mod = Reader->getModuleManager().getPrimaryModule();2640for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {2641if (!Fn(context, D))2642return false;2643}2644
2645return true;2646}2647
2648for (ASTUnit::top_level_iterator TL = top_level_begin(),2649TLEnd = top_level_end();2650TL != TLEnd; ++TL) {2651if (!Fn(context, *TL))2652return false;2653}2654
2655return true;2656}
2657
2658OptionalFileEntryRef ASTUnit::getPCHFile() {2659if (!Reader)2660return std::nullopt;2661
2662serialization::ModuleFile *Mod = nullptr;2663Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) {2664switch (M.Kind) {2665case serialization::MK_ImplicitModule:2666case serialization::MK_ExplicitModule:2667case serialization::MK_PrebuiltModule:2668return true; // skip dependencies.2669case serialization::MK_PCH:2670Mod = &M;2671return true; // found it.2672case serialization::MK_Preamble:2673return false; // look in dependencies.2674case serialization::MK_MainFile:2675return false; // look in dependencies.2676}2677
2678return true;2679});2680if (Mod)2681return Mod->File;2682
2683return std::nullopt;2684}
2685
2686bool ASTUnit::isModuleFile() const {2687return isMainFileAST() && getLangOpts().isCompilingModule();2688}
2689
2690InputKind ASTUnit::getInputKind() const {2691auto &LangOpts = getLangOpts();2692
2693Language Lang;2694if (LangOpts.OpenCL)2695Lang = Language::OpenCL;2696else if (LangOpts.CUDA)2697Lang = Language::CUDA;2698else if (LangOpts.RenderScript)2699Lang = Language::RenderScript;2700else if (LangOpts.CPlusPlus)2701Lang = LangOpts.ObjC ? Language::ObjCXX : Language::CXX;2702else2703Lang = LangOpts.ObjC ? Language::ObjC : Language::C;2704
2705InputKind::Format Fmt = InputKind::Source;2706if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)2707Fmt = InputKind::ModuleMap;2708
2709// We don't know if input was preprocessed. Assume not.2710bool PP = false;2711
2712return InputKind(Lang, Fmt, PP);2713}
2714
2715#ifndef NDEBUG2716ASTUnit::ConcurrencyState::ConcurrencyState() {2717Mutex = new std::recursive_mutex;2718}
2719
2720ASTUnit::ConcurrencyState::~ConcurrencyState() {2721delete static_cast<std::recursive_mutex *>(Mutex);2722}
2723
2724void ASTUnit::ConcurrencyState::start() {2725bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock();2726assert(acquired && "Concurrent access to ASTUnit!");2727}
2728
2729void ASTUnit::ConcurrencyState::finish() {2730static_cast<std::recursive_mutex *>(Mutex)->unlock();2731}
2732
2733#else // NDEBUG2734
2735ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; }2736ASTUnit::ConcurrencyState::~ConcurrencyState() {}2737void ASTUnit::ConcurrencyState::start() {}2738void ASTUnit::ConcurrencyState::finish() {}2739
2740#endif // NDEBUG2741