2526 lines · cpp
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-exception6//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/DiagnosticFrontend.h"30#include "clang/Basic/FileManager.h"31#include "clang/Basic/IdentifierTable.h"32#include "clang/Basic/LLVM.h"33#include "clang/Basic/LangOptions.h"34#include "clang/Basic/LangStandard.h"35#include "clang/Basic/Module.h"36#include "clang/Basic/SourceLocation.h"37#include "clang/Basic/SourceManager.h"38#include "clang/Basic/TargetInfo.h"39#include "clang/Basic/TargetOptions.h"40#include "clang/Frontend/CompilerInstance.h"41#include "clang/Frontend/CompilerInvocation.h"42#include "clang/Frontend/FrontendAction.h"43#include "clang/Frontend/FrontendActions.h"44#include "clang/Frontend/FrontendOptions.h"45#include "clang/Frontend/MultiplexConsumer.h"46#include "clang/Frontend/PrecompiledPreamble.h"47#include "clang/Frontend/StandaloneDiagnostic.h"48#include "clang/Frontend/Utils.h"49#include "clang/Lex/HeaderSearch.h"50#include "clang/Lex/HeaderSearchOptions.h"51#include "clang/Lex/Lexer.h"52#include "clang/Lex/PPCallbacks.h"53#include "clang/Lex/PreprocessingRecord.h"54#include "clang/Lex/Preprocessor.h"55#include "clang/Lex/PreprocessorOptions.h"56#include "clang/Lex/Token.h"57#include "clang/Sema/CodeCompleteConsumer.h"58#include "clang/Sema/CodeCompleteOptions.h"59#include "clang/Sema/Sema.h"60#include "clang/Sema/SemaCodeCompletion.h"61#include "clang/Serialization/ASTReader.h"62#include "clang/Serialization/ASTWriter.h"63#include "clang/Serialization/ModuleCache.h"64#include "clang/Serialization/ModuleFile.h"65#include "clang/Serialization/PCHContainerOperations.h"66#include "llvm/ADT/ArrayRef.h"67#include "llvm/ADT/DenseMap.h"68#include "llvm/ADT/IntrusiveRefCntPtr.h"69#include "llvm/ADT/STLExtras.h"70#include "llvm/ADT/ScopeExit.h"71#include "llvm/ADT/SmallVector.h"72#include "llvm/ADT/StringMap.h"73#include "llvm/ADT/StringRef.h"74#include "llvm/ADT/StringSet.h"75#include "llvm/ADT/Twine.h"76#include "llvm/ADT/iterator_range.h"77#include "llvm/Bitstream/BitstreamWriter.h"78#include "llvm/Support/Allocator.h"79#include "llvm/Support/CrashRecoveryContext.h"80#include "llvm/Support/DJB.h"81#include "llvm/Support/ErrorHandling.h"82#include "llvm/Support/ErrorOr.h"83#include "llvm/Support/MemoryBuffer.h"84#include "llvm/Support/SaveAndRestore.h"85#include "llvm/Support/Timer.h"86#include "llvm/Support/VirtualFileSystem.h"87#include "llvm/Support/raw_ostream.h"88#include <algorithm>89#include <atomic>90#include <cassert>91#include <cstdint>92#include <cstdio>93#include <cstdlib>94#include <memory>95#include <mutex>96#include <optional>97#include <string>98#include <tuple>99#include <utility>100#include <vector>101 102using namespace clang;103 104using llvm::TimeRecord;105 106namespace {107 108 class SimpleTimer {109 bool WantTiming;110 TimeRecord Start;111 std::string Output;112 113 public:114 explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {115 if (WantTiming)116 Start = TimeRecord::getCurrentTime();117 }118 119 ~SimpleTimer() {120 if (WantTiming) {121 TimeRecord Elapsed = TimeRecord::getCurrentTime();122 Elapsed -= Start;123 llvm::errs() << Output << ':';124 Elapsed.print(Elapsed, llvm::errs());125 llvm::errs() << '\n';126 }127 }128 129 void setOutput(const Twine &Output) {130 if (WantTiming)131 this->Output = Output.str();132 }133 };134 135} // namespace136 137template <class T>138static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {139 if (!Val)140 return nullptr;141 return std::move(*Val);142}143 144template <class T>145static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {146 if (!Val)147 return false;148 Output = std::move(*Val);149 return true;150}151 152/// Get a source buffer for \p MainFilePath, handling all file-to-file153/// and file-to-buffer remappings inside \p Invocation.154static std::unique_ptr<llvm::MemoryBuffer>155getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,156 llvm::vfs::FileSystem *VFS,157 StringRef FilePath, bool isVolatile) {158 const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();159 160 // Try to determine if the main file has been remapped, either from the161 // command line (to another file) or directly through the compiler162 // invocation (to a memory buffer).163 llvm::MemoryBuffer *Buffer = nullptr;164 std::unique_ptr<llvm::MemoryBuffer> BufferOwner;165 auto FileStatus = VFS->status(FilePath);166 if (FileStatus) {167 llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID();168 169 // Check whether there is a file-file remapping of the main file170 for (const auto &RF : PreprocessorOpts.RemappedFiles) {171 std::string MPath(RF.first);172 auto MPathStatus = VFS->status(MPath);173 if (MPathStatus) {174 llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();175 if (MainFileID == MID) {176 // We found a remapping. Try to load the resulting, remapped source.177 BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));178 if (!BufferOwner)179 return nullptr;180 }181 }182 }183 184 // Check whether there is a file-buffer remapping. It supercedes the185 // file-file remapping.186 for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {187 std::string MPath(RB.first);188 auto MPathStatus = VFS->status(MPath);189 if (MPathStatus) {190 llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();191 if (MainFileID == MID) {192 // We found a remapping.193 BufferOwner.reset();194 Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);195 }196 }197 }198 }199 200 // If the main source file was not remapped, load it now.201 if (!Buffer && !BufferOwner) {202 BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));203 if (!BufferOwner)204 return nullptr;205 }206 207 if (BufferOwner)208 return BufferOwner;209 if (!Buffer)210 return nullptr;211 return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);212}213 214void ASTUnit::clearFileLevelDecls() {215 FileDecls.clear();216}217 218/// After failing to build a precompiled preamble (due to219/// errors in the source that occurs in the preamble), the number of220/// reparses during which we'll skip even trying to precompile the221/// preamble.222const unsigned DefaultPreambleRebuildInterval = 5;223 224/// Tracks the number of ASTUnit objects that are currently active.225///226/// Used for debugging purposes only.227static std::atomic<unsigned> ActiveASTUnitObjects;228 229ASTUnit::ASTUnit(bool _MainFileIsAST)230 : CodeGenOpts(std::make_unique<CodeGenOptions>()),231 MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),232 ShouldCacheCodeCompletionResults(false),233 IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),234 UnsafeToFree(false) {235 if (getenv("LIBCLANG_OBJTRACKING"))236 fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);237}238 239ASTUnit::~ASTUnit() {240 // If we loaded from an AST file, balance out the BeginSourceFile call.241 if (MainFileIsAST && getDiagnostics().getClient()) {242 getDiagnostics().getClient()->EndSourceFile();243 }244 245 clearFileLevelDecls();246 247 // Free the buffers associated with remapped files. We are required to248 // perform this operation here because we explicitly request that the249 // compiler instance *not* free these buffers for each invocation of the250 // parser.251 if (Invocation && OwnsRemappedFileBuffers) {252 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();253 for (const auto &RB : PPOpts.RemappedFileBuffers)254 delete RB.second;255 }256 257 ClearCachedCompletionResults();258 259 if (getenv("LIBCLANG_OBJTRACKING"))260 fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);261}262 263void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {264 this->PP = std::move(PP);265}266 267void ASTUnit::enableSourceFileDiagnostics() {268 assert(getDiagnostics().getClient() && Ctx &&269 "Bad context for source file");270 getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());271}272 273/// Determine the set of code-completion contexts in which this274/// declaration should be shown.275static uint64_t getDeclShowContexts(const NamedDecl *ND,276 const LangOptions &LangOpts,277 bool &IsNestedNameSpecifier) {278 IsNestedNameSpecifier = false;279 280 if (isa<UsingShadowDecl>(ND))281 ND = ND->getUnderlyingDecl();282 if (!ND)283 return 0;284 285 uint64_t Contexts = 0;286 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||287 isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||288 isa<TypeAliasTemplateDecl>(ND)) {289 // Types can appear in these contexts.290 if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))291 Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)292 | (1LL << CodeCompletionContext::CCC_ObjCIvarList)293 | (1LL << CodeCompletionContext::CCC_ClassStructUnion)294 | (1LL << CodeCompletionContext::CCC_Statement)295 | (1LL << CodeCompletionContext::CCC_Type)296 | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);297 298 // In C++, types can appear in expressions contexts (for functional casts).299 if (LangOpts.CPlusPlus)300 Contexts |= (1LL << CodeCompletionContext::CCC_Expression);301 302 // In Objective-C, message sends can send interfaces. In Objective-C++,303 // all types are available due to functional casts.304 if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))305 Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);306 307 // In Objective-C, you can only be a subclass of another Objective-C class308 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {309 // Objective-C interfaces can be used in a class property expression.310 if (ID->getDefinition())311 Contexts |= (1LL << CodeCompletionContext::CCC_Expression);312 Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);313 Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);314 }315 316 // Deal with tag names.317 if (isa<EnumDecl>(ND)) {318 Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);319 320 // Part of the nested-name-specifier in C++0x.321 if (LangOpts.CPlusPlus11)322 IsNestedNameSpecifier = true;323 } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {324 if (Record->isUnion())325 Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);326 else327 Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);328 329 if (LangOpts.CPlusPlus)330 IsNestedNameSpecifier = true;331 } else if (isa<ClassTemplateDecl>(ND))332 IsNestedNameSpecifier = true;333 } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {334 // Values can appear in these contexts.335 Contexts = (1LL << CodeCompletionContext::CCC_Statement)336 | (1LL << CodeCompletionContext::CCC_Expression)337 | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)338 | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);339 } else if (isa<ObjCProtocolDecl>(ND)) {340 Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);341 } else if (isa<ObjCCategoryDecl>(ND)) {342 Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);343 } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {344 Contexts = (1LL << CodeCompletionContext::CCC_Namespace);345 346 // Part of the nested-name-specifier.347 IsNestedNameSpecifier = true;348 }349 350 return Contexts;351}352 353void ASTUnit::CacheCodeCompletionResults() {354 if (!TheSema)355 return;356 357 SimpleTimer Timer(WantTiming);358 Timer.setOutput("Cache global code completions for " + getMainFileName());359 360 // Clear out the previous results.361 ClearCachedCompletionResults();362 363 // Gather the set of global code completions.364 using Result = CodeCompletionResult;365 SmallVector<Result, 8> Results;366 CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();367 CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);368 TheSema->CodeCompletion().GatherGlobalCodeCompletions(369 *CachedCompletionAllocator, CCTUInfo, Results);370 371 // Translate global code completions into cached completions.372 llvm::DenseMap<CanQualType, unsigned> CompletionTypes;373 CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);374 375 for (auto &R : Results) {376 switch (R.Kind) {377 case Result::RK_Declaration: {378 bool IsNestedNameSpecifier = false;379 CachedCodeCompletionResult CachedResult;380 CachedResult.Completion = R.CreateCodeCompletionString(381 *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,382 IncludeBriefCommentsInCodeCompletion);383 CachedResult.ShowInContexts = getDeclShowContexts(384 R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);385 CachedResult.Priority = R.Priority;386 CachedResult.Kind = R.CursorKind;387 CachedResult.Availability = R.Availability;388 389 // Keep track of the type of this completion in an ASTContext-agnostic390 // way.391 QualType UsageType = getDeclUsageType(*Ctx, R.Qualifier, R.Declaration);392 if (UsageType.isNull()) {393 CachedResult.TypeClass = STC_Void;394 CachedResult.Type = 0;395 } else {396 CanQualType CanUsageType397 = Ctx->getCanonicalType(UsageType.getUnqualifiedType());398 CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);399 400 // Determine whether we have already seen this type. If so, we save401 // ourselves the work of formatting the type string by using the402 // temporary, CanQualType-based hash table to find the associated value.403 unsigned &TypeValue = CompletionTypes[CanUsageType];404 if (TypeValue == 0) {405 TypeValue = CompletionTypes.size();406 CachedCompletionTypes[QualType(CanUsageType).getAsString()]407 = TypeValue;408 }409 410 CachedResult.Type = TypeValue;411 }412 413 CachedCompletionResults.push_back(CachedResult);414 415 /// Handle nested-name-specifiers in C++.416 if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&417 !R.StartsNestedNameSpecifier) {418 // The contexts in which a nested-name-specifier can appear in C++.419 uint64_t NNSContexts420 = (1LL << CodeCompletionContext::CCC_TopLevel)421 | (1LL << CodeCompletionContext::CCC_ObjCIvarList)422 | (1LL << CodeCompletionContext::CCC_ClassStructUnion)423 | (1LL << CodeCompletionContext::CCC_Statement)424 | (1LL << CodeCompletionContext::CCC_Expression)425 | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)426 | (1LL << CodeCompletionContext::CCC_EnumTag)427 | (1LL << CodeCompletionContext::CCC_UnionTag)428 | (1LL << CodeCompletionContext::CCC_ClassOrStructTag)429 | (1LL << CodeCompletionContext::CCC_Type)430 | (1LL << CodeCompletionContext::CCC_SymbolOrNewName)431 | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);432 433 if (isa<NamespaceDecl>(R.Declaration) ||434 isa<NamespaceAliasDecl>(R.Declaration))435 NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);436 437 if (uint64_t RemainingContexts438 = NNSContexts & ~CachedResult.ShowInContexts) {439 // If there any contexts where this completion can be a440 // nested-name-specifier but isn't already an option, create a441 // nested-name-specifier completion.442 R.StartsNestedNameSpecifier = true;443 CachedResult.Completion = R.CreateCodeCompletionString(444 *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,445 IncludeBriefCommentsInCodeCompletion);446 CachedResult.ShowInContexts = RemainingContexts;447 CachedResult.Priority = CCP_NestedNameSpecifier;448 CachedResult.TypeClass = STC_Void;449 CachedResult.Type = 0;450 CachedCompletionResults.push_back(CachedResult);451 }452 }453 break;454 }455 456 case Result::RK_Keyword:457 case Result::RK_Pattern:458 // Ignore keywords and patterns; we don't care, since they are so459 // easily regenerated.460 break;461 462 case Result::RK_Macro: {463 CachedCodeCompletionResult CachedResult;464 CachedResult.Completion = R.CreateCodeCompletionString(465 *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,466 IncludeBriefCommentsInCodeCompletion);467 CachedResult.ShowInContexts468 = (1LL << CodeCompletionContext::CCC_TopLevel)469 | (1LL << CodeCompletionContext::CCC_ObjCInterface)470 | (1LL << CodeCompletionContext::CCC_ObjCImplementation)471 | (1LL << CodeCompletionContext::CCC_ObjCIvarList)472 | (1LL << CodeCompletionContext::CCC_ClassStructUnion)473 | (1LL << CodeCompletionContext::CCC_Statement)474 | (1LL << CodeCompletionContext::CCC_Expression)475 | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)476 | (1LL << CodeCompletionContext::CCC_MacroNameUse)477 | (1LL << CodeCompletionContext::CCC_PreprocessorExpression)478 | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)479 | (1LL << CodeCompletionContext::CCC_OtherWithMacros);480 481 CachedResult.Priority = R.Priority;482 CachedResult.Kind = R.CursorKind;483 CachedResult.Availability = R.Availability;484 CachedResult.TypeClass = STC_Void;485 CachedResult.Type = 0;486 CachedCompletionResults.push_back(CachedResult);487 break;488 }489 }490 }491 492 // Save the current top-level hash value.493 CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;494}495 496void ASTUnit::ClearCachedCompletionResults() {497 CachedCompletionResults.clear();498 CachedCompletionTypes.clear();499 CachedCompletionAllocator = nullptr;500}501 502namespace {503 504/// Gathers information from ASTReader that will be used to initialize505/// a Preprocessor.506class ASTInfoCollector : public ASTReaderListener {507 HeaderSearchOptions &HSOpts;508 std::string &SpecificModuleCachePath;509 PreprocessorOptions &PPOpts;510 LangOptions &LangOpts;511 CodeGenOptions &CodeGenOpts;512 TargetOptions &TargetOpts;513 uint32_t &Counter;514 515public:516 ASTInfoCollector(HeaderSearchOptions &HSOpts,517 std::string &SpecificModuleCachePath,518 PreprocessorOptions &PPOpts, LangOptions &LangOpts,519 CodeGenOptions &CodeGenOpts, TargetOptions &TargetOpts,520 uint32_t &Counter)521 : HSOpts(HSOpts), SpecificModuleCachePath(SpecificModuleCachePath),522 PPOpts(PPOpts), LangOpts(LangOpts), CodeGenOpts(CodeGenOpts),523 TargetOpts(TargetOpts), Counter(Counter) {}524 525 bool ReadLanguageOptions(const LangOptions &NewLangOpts,526 StringRef ModuleFilename, bool Complain,527 bool AllowCompatibleDifferences) override {528 LangOpts = NewLangOpts;529 return false;530 }531 532 bool ReadCodeGenOptions(const CodeGenOptions &NewCodeGenOpts,533 StringRef ModuleFilename, bool Complain,534 bool AllowCompatibleDifferences) override {535 CodeGenOpts = NewCodeGenOpts;536 return false;537 }538 539 bool ReadHeaderSearchOptions(const HeaderSearchOptions &NewHSOpts,540 StringRef ModuleFilename,541 StringRef NewSpecificModuleCachePath,542 bool Complain) override {543 HSOpts = NewHSOpts;544 SpecificModuleCachePath = NewSpecificModuleCachePath;545 return false;546 }547 548 bool ReadHeaderSearchPaths(const HeaderSearchOptions &NewHSOpts,549 bool Complain) override {550 HSOpts.UserEntries = NewHSOpts.UserEntries;551 HSOpts.SystemHeaderPrefixes = NewHSOpts.SystemHeaderPrefixes;552 HSOpts.VFSOverlayFiles = NewHSOpts.VFSOverlayFiles;553 return false;554 }555 556 bool ReadPreprocessorOptions(const PreprocessorOptions &NewPPOpts,557 StringRef ModuleFilename, bool ReadMacros,558 bool Complain,559 std::string &SuggestedPredefines) override {560 PPOpts = NewPPOpts;561 return false;562 }563 564 bool ReadTargetOptions(const TargetOptions &NewTargetOpts,565 StringRef ModuleFilename, bool Complain,566 bool AllowCompatibleDifferences) override {567 TargetOpts = NewTargetOpts;568 return false;569 }570 571 void ReadCounter(const serialization::ModuleFile &M,572 uint32_t NewCounter) override {573 Counter = NewCounter;574 }575};576} // anonymous namespace577 578FilterAndStoreDiagnosticConsumer::FilterAndStoreDiagnosticConsumer(579 SmallVectorImpl<StoredDiagnostic> *StoredDiags,580 SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags,581 bool CaptureNonErrorsFromIncludes)582 : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),583 CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {584 assert((StoredDiags || StandaloneDiags) &&585 "No output collections were passed to StoredDiagnosticConsumer.");586}587 588void FilterAndStoreDiagnosticConsumer::BeginSourceFile(589 const LangOptions &LangOpts, const Preprocessor *PP) {590 this->LangOpts = &LangOpts;591 if (PP)592 SourceMgr = &PP->getSourceManager();593}594 595static bool isInMainFile(const clang::Diagnostic &D) {596 if (!D.hasSourceManager() || !D.getLocation().isValid())597 return false;598 599 auto &M = D.getSourceManager();600 return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation()));601}602 603void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(604 DiagnosticsEngine::Level Level, const Diagnostic &Info) {605 // Default implementation (Warnings/errors count).606 DiagnosticConsumer::HandleDiagnostic(Level, Info);607 608 // Only record the diagnostic if it's part of the source manager we know609 // about. This effectively drops diagnostics from modules we're building.610 // FIXME: In the long run, ee don't want to drop source managers from modules.611 if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) {612 if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning &&613 !isInMainFile(Info)) {614 return;615 }616 617 StoredDiagnostic *ResultDiag = nullptr;618 if (StoredDiags) {619 StoredDiags->emplace_back(Level, Info);620 ResultDiag = &StoredDiags->back();621 }622 623 if (StandaloneDiags) {624 std::optional<StoredDiagnostic> StoredDiag;625 if (!ResultDiag) {626 StoredDiag.emplace(Level, Info);627 ResultDiag = &*StoredDiag;628 }629 StandaloneDiags->emplace_back(*LangOpts, *ResultDiag);630 }631 }632}633 634CaptureDroppedDiagnostics::CaptureDroppedDiagnostics(635 CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,636 SmallVectorImpl<StoredDiagnostic> *StoredDiags,637 SmallVectorImpl<StandaloneDiagnostic> *StandaloneDiags)638 : Diags(Diags),639 Client(StoredDiags, StandaloneDiags,640 CaptureDiagnostics !=641 CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {642 if (CaptureDiagnostics != CaptureDiagsKind::None ||643 Diags.getClient() == nullptr) {644 OwningPreviousClient = Diags.takeClient();645 PreviousClient = Diags.getClient();646 Diags.setClient(&Client, false);647 }648}649 650CaptureDroppedDiagnostics::~CaptureDroppedDiagnostics() {651 if (Diags.getClient() == &Client)652 Diags.setClient(PreviousClient, !!OwningPreviousClient.release());653}654 655IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {656 return Reader;657}658 659ASTMutationListener *ASTUnit::getASTMutationListener() {660 if (WriterData)661 return &WriterData->Writer;662 return nullptr;663}664 665ASTDeserializationListener *ASTUnit::getDeserializationListener() {666 if (WriterData)667 return &WriterData->Writer;668 return nullptr;669}670 671std::unique_ptr<llvm::MemoryBuffer>672ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {673 assert(FileMgr);674 auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);675 if (Buffer)676 return std::move(*Buffer);677 if (ErrorStr)678 *ErrorStr = Buffer.getError().message();679 return nullptr;680}681 682/// Configure the diagnostics object for use with ASTUnit.683void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,684 ASTUnit &AST,685 CaptureDiagsKind CaptureDiagnostics) {686 assert(Diags.get() && "no DiagnosticsEngine was provided");687 if (CaptureDiagnostics != CaptureDiagsKind::None)688 Diags->setClient(new FilterAndStoreDiagnosticConsumer(689 &AST.StoredDiagnostics, nullptr,690 CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes));691}692 693std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(694 StringRef Filename, const PCHContainerReader &PCHContainerRdr,695 WhatToLoad ToLoad, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,696 std::shared_ptr<DiagnosticOptions> DiagOpts,697 IntrusiveRefCntPtr<DiagnosticsEngine> Diags,698 const FileSystemOptions &FileSystemOpts, const HeaderSearchOptions &HSOpts,699 const LangOptions *ProvidedLangOpts, bool OnlyLocalDecls,700 CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,701 bool UserFilesAreVolatile) {702 std::unique_ptr<ASTUnit> AST(new ASTUnit(true));703 704 // Recover resources if we crash before exiting this method.705 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>706 ASTUnitCleanup(AST.get());707 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,708 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>709 DiagCleanup(Diags.get());710 711 ConfigureDiags(Diags, *AST, CaptureDiagnostics);712 713 std::unique_ptr<LangOptions> LocalLangOpts;714 const LangOptions &LangOpts = [&]() -> const LangOptions & {715 if (ProvidedLangOpts)716 return *ProvidedLangOpts;717 LocalLangOpts = std::make_unique<LangOptions>();718 return *LocalLangOpts;719 }();720 721 AST->LangOpts = std::make_unique<LangOptions>(LangOpts);722 AST->OnlyLocalDecls = OnlyLocalDecls;723 AST->CaptureDiagnostics = CaptureDiagnostics;724 AST->DiagOpts = DiagOpts;725 AST->Diagnostics = Diags;726 AST->UserFilesAreVolatile = UserFilesAreVolatile;727 AST->HSOpts = std::make_unique<HeaderSearchOptions>(HSOpts);728 AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front());729 AST->PPOpts = std::make_shared<PreprocessorOptions>();730 AST->CodeGenOpts = std::make_unique<CodeGenOptions>();731 AST->TargetOpts = std::make_shared<TargetOptions>();732 733 AST->ModCache = createCrossProcessModuleCache();734 735 // Gather info for preprocessor construction later on.736 std::string SpecificModuleCachePath;737 unsigned Counter = 0;738 // Using a temporary FileManager since the AST file might specify custom739 // HeaderSearchOptions::VFSOverlayFiles that affect the underlying VFS.740 FileManager TmpFileMgr(FileSystemOpts, VFS);741 ASTInfoCollector Collector(*AST->HSOpts, SpecificModuleCachePath,742 *AST->PPOpts, *AST->LangOpts, *AST->CodeGenOpts,743 *AST->TargetOpts, Counter);744 if (ASTReader::readASTFileControlBlock(745 Filename, TmpFileMgr, *AST->ModCache, PCHContainerRdr,746 /*FindModuleFileExtensions=*/true, Collector,747 /*ValidateDiagnosticOptions=*/true, ASTReader::ARR_None)) {748 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);749 return nullptr;750 }751 752 VFS = createVFSFromOverlayFiles(AST->HSOpts->VFSOverlayFiles,753 *AST->Diagnostics, std::move(VFS));754 755 AST->FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOpts, VFS);756 757 AST->SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(758 AST->getDiagnostics(), AST->getFileManager(), UserFilesAreVolatile);759 760 AST->HSOpts->PrebuiltModuleFiles = HSOpts.PrebuiltModuleFiles;761 AST->HSOpts->PrebuiltModulePaths = HSOpts.PrebuiltModulePaths;762 AST->HeaderInfo = std::make_unique<HeaderSearch>(763 AST->getHeaderSearchOpts(), AST->getSourceManager(),764 AST->getDiagnostics(), AST->getLangOpts(),765 /*Target=*/nullptr);766 AST->HeaderInfo->setModuleCachePath(SpecificModuleCachePath);767 768 AST->PP = std::make_shared<Preprocessor>(769 *AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts,770 AST->getSourceManager(), *AST->HeaderInfo, AST->ModuleLoader,771 /*IILookup=*/nullptr,772 /*OwnsHeaderSearch=*/false);773 774 if (ToLoad >= LoadASTOnly)775 AST->Ctx = llvm::makeIntrusiveRefCnt<ASTContext>(776 *AST->LangOpts, AST->getSourceManager(), AST->PP->getIdentifierTable(),777 AST->PP->getSelectorTable(), AST->PP->getBuiltinInfo(),778 AST->getTranslationUnitKind());779 780 DisableValidationForModuleKind disableValid =781 DisableValidationForModuleKind::None;782 if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))783 disableValid = DisableValidationForModuleKind::All;784 AST->Reader = llvm::makeIntrusiveRefCnt<ASTReader>(785 *AST->PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr,786 *AST->CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>>(),787 /*isysroot=*/"",788 /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);789 790 // Attach the AST reader to the AST context as an external AST source, so that791 // declarations will be deserialized from the AST file as needed.792 // We need the external source to be set up before we read the AST, because793 // eagerly-deserialized declarations may use it.794 if (AST->Ctx)795 AST->Ctx->setExternalSource(AST->Reader);796 797 AST->Target =798 TargetInfo::CreateTargetInfo(AST->PP->getDiagnostics(), *AST->TargetOpts);799 // Inform the target of the language options.800 //801 // FIXME: We shouldn't need to do this, the target should be immutable once802 // created. This complexity should be lifted elsewhere.803 AST->Target->adjust(AST->PP->getDiagnostics(), *AST->LangOpts,804 /*AuxTarget=*/nullptr);805 806 // Initialize the preprocessor.807 AST->PP->Initialize(*AST->Target);808 809 AST->PP->setCounterValue(Counter);810 811 if (AST->Ctx) {812 // Initialize the ASTContext813 AST->Ctx->InitBuiltinTypes(*AST->Target);814 815 // Adjust printing policy based on language options.816 AST->Ctx->setPrintingPolicy(PrintingPolicy(*AST->LangOpts));817 818 // We didn't have access to the comment options when the ASTContext was819 // constructed, so register them now.820 AST->Ctx->getCommentCommandTraits().registerCommentOptions(821 AST->LangOpts->CommentOpts);822 }823 824 // The temporary FileManager we used for ASTReader::readASTFileControlBlock()825 // might have already read stdin, and reading it again will fail. Let's826 // explicitly forward the buffer.827 if (Filename == "-")828 if (auto FE = llvm::expectedToOptional(TmpFileMgr.getSTDIN()))829 if (auto BufRef = TmpFileMgr.getBufferForFile(*FE)) {830 auto Buf = llvm::MemoryBuffer::getMemBufferCopy(831 (*BufRef)->getBuffer(), (*BufRef)->getBufferIdentifier());832 AST->Reader->getModuleManager().addInMemoryBuffer("-", std::move(Buf));833 }834 835 // Reinstate the provided options that are relevant for reading AST files.836 AST->HSOpts->ForceCheckCXX20ModulesInputFiles =837 HSOpts.ForceCheckCXX20ModulesInputFiles;838 839 switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,840 SourceLocation(), ASTReader::ARR_None)) {841 case ASTReader::Success:842 break;843 844 case ASTReader::Failure:845 case ASTReader::Missing:846 case ASTReader::OutOfDate:847 case ASTReader::VersionMismatch:848 case ASTReader::ConfigurationMismatch:849 case ASTReader::HadErrors:850 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);851 return nullptr;852 }853 854 // Now that we have successfully loaded the AST file, we can reinstate some855 // options that the clients expect us to preserve (but would trip AST file856 // validation, so we couldn't set them earlier).857 AST->HSOpts->UserEntries = HSOpts.UserEntries;858 AST->HSOpts->SystemHeaderPrefixes = HSOpts.SystemHeaderPrefixes;859 AST->HSOpts->VFSOverlayFiles = HSOpts.VFSOverlayFiles;860 AST->LangOpts->PICLevel = LangOpts.PICLevel;861 AST->LangOpts->PIE = LangOpts.PIE;862 863 AST->OriginalSourceFile = std::string(AST->Reader->getOriginalSourceFile());864 865 Module *M = AST->HeaderInfo->lookupModule(AST->getLangOpts().CurrentModule);866 if (M && AST->getLangOpts().isCompilingModule() && M->isNamedModule())867 AST->Ctx->setCurrentNamedModule(M);868 869 // Create an AST consumer, even though it isn't used.870 if (ToLoad >= LoadASTOnly)871 AST->Consumer.reset(new ASTConsumer);872 873 // Create a semantic analysis object and tell the AST reader about it.874 if (ToLoad >= LoadEverything) {875 AST->TheSema = std::make_unique<Sema>(*AST->PP, *AST->Ctx, *AST->Consumer);876 AST->TheSema->Initialize();877 AST->Reader->InitializeSema(*AST->TheSema);878 }879 880 // Tell the diagnostic client that we have started a source file.881 AST->getDiagnostics().getClient()->BeginSourceFile(AST->PP->getLangOpts(),882 AST->PP.get());883 884 return AST;885}886 887/// Add the given macro to the hash of all top-level entities.888static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {889 Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);890}891 892namespace {893 894/// Preprocessor callback class that updates a hash value with the names895/// of all macros that have been defined by the translation unit.896class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {897 unsigned &Hash;898 899public:900 explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}901 902 void MacroDefined(const Token &MacroNameTok,903 const MacroDirective *MD) override {904 AddDefinedMacroToHash(MacroNameTok, Hash);905 }906};907 908} // namespace909 910/// Add the given declaration to the hash of all top-level entities.911static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {912 if (!D)913 return;914 915 DeclContext *DC = D->getDeclContext();916 if (!DC)917 return;918 919 if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))920 return;921 922 if (const auto *ND = dyn_cast<NamedDecl>(D)) {923 if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {924 // For an unscoped enum include the enumerators in the hash since they925 // enter the top-level namespace.926 if (!EnumD->isScoped()) {927 for (const auto *EI : EnumD->enumerators()) {928 if (EI->getIdentifier())929 Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);930 }931 }932 }933 934 if (ND->getIdentifier())935 Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);936 else if (DeclarationName Name = ND->getDeclName()) {937 std::string NameStr = Name.getAsString();938 Hash = llvm::djbHash(NameStr, Hash);939 }940 return;941 }942 943 if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {944 if (const Module *Mod = ImportD->getImportedModule()) {945 std::string ModName = Mod->getFullModuleName();946 Hash = llvm::djbHash(ModName, Hash);947 }948 return;949 }950}951 952namespace {953 954class TopLevelDeclTrackerConsumer : public ASTConsumer {955 ASTUnit &Unit;956 unsigned &Hash;957 958public:959 TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)960 : Unit(_Unit), Hash(Hash) {961 Hash = 0;962 }963 964 void handleTopLevelDecl(Decl *D) {965 if (!D)966 return;967 968 // FIXME: Currently ObjC method declarations are incorrectly being969 // reported as top-level declarations, even though their DeclContext970 // is the containing ObjC @interface/@implementation. This is a971 // fundamental problem in the parser right now.972 if (isa<ObjCMethodDecl>(D))973 return;974 975 AddTopLevelDeclarationToHash(D, Hash);976 Unit.addTopLevelDecl(D);977 978 handleFileLevelDecl(D);979 }980 981 void handleFileLevelDecl(Decl *D) {982 Unit.addFileLevelDecl(D);983 if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {984 for (auto *I : NSD->decls())985 handleFileLevelDecl(I);986 }987 }988 989 bool HandleTopLevelDecl(DeclGroupRef D) override {990 for (auto *TopLevelDecl : D)991 handleTopLevelDecl(TopLevelDecl);992 return true;993 }994 995 // We're not interested in "interesting" decls.996 void HandleInterestingDecl(DeclGroupRef) override {}997 998 void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {999 for (auto *TopLevelDecl : D)1000 handleTopLevelDecl(TopLevelDecl);1001 }1002 1003 ASTMutationListener *GetASTMutationListener() override {1004 return Unit.getASTMutationListener();1005 }1006 1007 ASTDeserializationListener *GetASTDeserializationListener() override {1008 return Unit.getDeserializationListener();1009 }1010};1011 1012class TopLevelDeclTrackerAction : public ASTFrontendAction {1013public:1014 ASTUnit &Unit;1015 1016 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,1017 StringRef InFile) override {1018 CI.getPreprocessor().addPPCallbacks(1019 std::make_unique<MacroDefinitionTrackerPPCallbacks>(1020 Unit.getCurrentTopLevelHashValue()));1021 return std::make_unique<TopLevelDeclTrackerConsumer>(1022 Unit, Unit.getCurrentTopLevelHashValue());1023 }1024 1025public:1026 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}1027 1028 bool hasCodeCompletionSupport() const override { return false; }1029 1030 TranslationUnitKind getTranslationUnitKind() override {1031 return Unit.getTranslationUnitKind();1032 }1033};1034 1035class ASTUnitPreambleCallbacks : public PreambleCallbacks {1036public:1037 unsigned getHash() const { return Hash; }1038 1039 std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }1040 1041 std::vector<LocalDeclID> takeTopLevelDeclIDs() {1042 return std::move(TopLevelDeclIDs);1043 }1044 1045 void AfterPCHEmitted(ASTWriter &Writer) override {1046 TopLevelDeclIDs.reserve(TopLevelDecls.size());1047 for (const auto *D : TopLevelDecls) {1048 // Invalid top-level decls may not have been serialized.1049 if (D->isInvalidDecl())1050 continue;1051 TopLevelDeclIDs.push_back(Writer.getDeclID(D));1052 }1053 }1054 1055 void HandleTopLevelDecl(DeclGroupRef DG) override {1056 for (auto *D : DG) {1057 // FIXME: Currently ObjC method declarations are incorrectly being1058 // reported as top-level declarations, even though their DeclContext1059 // is the containing ObjC @interface/@implementation. This is a1060 // fundamental problem in the parser right now.1061 if (isa<ObjCMethodDecl>(D))1062 continue;1063 AddTopLevelDeclarationToHash(D, Hash);1064 TopLevelDecls.push_back(D);1065 }1066 }1067 1068 std::unique_ptr<PPCallbacks> createPPCallbacks() override {1069 return std::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash);1070 }1071 1072private:1073 unsigned Hash = 0;1074 std::vector<Decl *> TopLevelDecls;1075 std::vector<LocalDeclID> TopLevelDeclIDs;1076 llvm::SmallVector<StandaloneDiagnostic, 4> PreambleDiags;1077};1078 1079} // namespace1080 1081static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {1082 return StoredDiag.getLocation().isValid();1083}1084 1085static void1086checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {1087 // Get rid of stored diagnostics except the ones from the driver which do not1088 // have a source location.1089 llvm::erase_if(StoredDiags, isNonDriverDiag);1090}1091 1092static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &1093 StoredDiagnostics,1094 SourceManager &SM) {1095 // The stored diagnostic has the old source manager in it; update1096 // the locations to refer into the new source manager. Since we've1097 // been careful to make sure that the source manager's state1098 // before and after are identical, so that we can reuse the source1099 // location itself.1100 for (auto &SD : StoredDiagnostics) {1101 if (SD.getLocation().isValid()) {1102 FullSourceLoc Loc(SD.getLocation(), SM);1103 SD.setLocation(Loc);1104 }1105 }1106}1107 1108/// Parse the source file into a translation unit using the given compiler1109/// invocation, replacing the current translation unit.1110///1111/// \returns True if a failure occurred that causes the ASTUnit not to1112/// contain any translation-unit information, false otherwise.1113bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,1114 std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,1115 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1116 if (!Invocation)1117 return true;1118 1119 if (VFS && FileMgr)1120 assert(VFS == &FileMgr->getVirtualFileSystem() &&1121 "VFS passed to Parse and VFS in FileMgr are different");1122 1123 CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);1124 if (OverrideMainBuffer) {1125 assert(Preamble &&1126 "No preamble was built, but OverrideMainBuffer is not null");1127 Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());1128 // VFS may have changed...1129 }1130 1131 // Create the compiler instance to use for building the AST.1132 auto Clang = std::make_unique<CompilerInstance>(CCInvocation,1133 std::move(PCHContainerOps));1134 1135 // Clean up on error, disengage it if the function returns successfully.1136 auto CleanOnError = llvm::make_scope_exit([&]() {1137 // Remove the overridden buffer we used for the preamble.1138 SavedMainFileBuffer = nullptr;1139 1140 // Keep the ownership of the data in the ASTUnit because the client may1141 // want to see the diagnostics.1142 transferASTDataFromCompilerInstance(*Clang);1143 FailedParseDiagnostics.swap(StoredDiagnostics);1144 StoredDiagnostics.clear();1145 NumStoredDiagnosticsFromDriver = 0;1146 });1147 1148 // Ensure that Clang has a FileManager with the right VFS, which may have1149 // changed above in AddImplicitPreamble. If VFS is nullptr, rely on1150 // createFileManager to create one.1151 if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) {1152 Clang->setVirtualFileSystem(std::move(VFS));1153 Clang->setFileManager(FileMgr);1154 } else {1155 Clang->setVirtualFileSystem(std::move(VFS));1156 Clang->createFileManager();1157 FileMgr = Clang->getFileManagerPtr();1158 }1159 1160 // Recover resources if we crash before exiting this method.1161 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>1162 CICleanup(Clang.get());1163 1164 OriginalSourceFile =1165 std::string(Clang->getFrontendOpts().Inputs[0].getFile());1166 1167 // Set up diagnostics, capturing any diagnostics that would1168 // otherwise be dropped.1169 Clang->setDiagnostics(getDiagnosticsPtr());1170 1171 // Create the target instance.1172 if (!Clang->createTarget())1173 return true;1174 1175 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&1176 "Invocation must have exactly one source file!");1177 assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==1178 InputKind::Source &&1179 "FIXME: AST inputs not yet supported here!");1180 assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=1181 Language::LLVM_IR &&1182 "IR inputs not support here!");1183 1184 // Configure the various subsystems.1185 LangOpts =1186 std::make_unique<LangOptions>(Clang->getInvocation().getLangOpts());1187 FileSystemOpts = Clang->getFileSystemOpts();1188 1189 ResetForParse();1190 1191 SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(1192 getDiagnostics(), *FileMgr, +UserFilesAreVolatile);1193 if (!OverrideMainBuffer) {1194 checkAndRemoveNonDriverDiags(StoredDiagnostics);1195 TopLevelDeclsInPreamble.clear();1196 }1197 1198 // Create the source manager.1199 Clang->setSourceManager(getSourceManagerPtr());1200 1201 // If the main file has been overridden due to the use of a preamble,1202 // make that override happen and introduce the preamble.1203 if (OverrideMainBuffer) {1204 // The stored diagnostic has the old source manager in it; update1205 // the locations to refer into the new source manager. Since we've1206 // been careful to make sure that the source manager's state1207 // before and after are identical, so that we can reuse the source1208 // location itself.1209 checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());1210 1211 // Keep track of the override buffer;1212 SavedMainFileBuffer = std::move(OverrideMainBuffer);1213 }1214 1215 std::unique_ptr<TopLevelDeclTrackerAction> Act(1216 new TopLevelDeclTrackerAction(*this));1217 1218 // Recover resources if we crash before exiting this method.1219 llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>1220 ActCleanup(Act.get());1221 1222 if (!Act->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))1223 return true;1224 1225 if (SavedMainFileBuffer) {1226 StoredDiagnostics.clear();1227 StoredDiagnostics.reserve(PreambleDiagnostics.size());1228 llvm::transform(std::move(PreambleDiagnostics),1229 std::back_inserter(StoredDiagnostics),1230 [&](auto &&StandaloneDiag) {1231 return translateStandaloneDiag(1232 getFileManager(), getSourceManager(),1233 std::move(StandaloneDiag), PreambleSrcLocCache);1234 });1235 } else1236 PreambleSrcLocCache.clear();1237 1238 if (llvm::Error Err = Act->Execute()) {1239 consumeError(std::move(Err)); // FIXME this drops errors on the floor.1240 return true;1241 }1242 1243 transferASTDataFromCompilerInstance(*Clang);1244 1245 Act->EndSourceFile();1246 1247 FailedParseDiagnostics.clear();1248 1249 CleanOnError.release();1250 1251 return false;1252}1253 1254/// Attempt to build or re-use a precompiled preamble when (re-)parsing1255/// the source file.1256///1257/// This routine will compute the preamble of the main source file. If a1258/// non-trivial preamble is found, it will precompile that preamble into a1259/// precompiled header so that the precompiled preamble can be used to reduce1260/// reparsing time. If a precompiled preamble has already been constructed,1261/// this routine will determine if it is still valid and, if so, avoid1262/// rebuilding the precompiled preamble.1263///1264/// \param AllowRebuild When true (the default), this routine is1265/// allowed to rebuild the precompiled preamble if it is found to be1266/// out-of-date.1267///1268/// \param MaxLines When non-zero, the maximum number of lines that1269/// can occur within the preamble.1270///1271/// \returns If the precompiled preamble can be used, returns a newly-allocated1272/// buffer that should be used in place of the main file when doing so.1273/// Otherwise, returns a NULL pointer.1274std::unique_ptr<llvm::MemoryBuffer>1275ASTUnit::getMainBufferWithPrecompiledPreamble(1276 std::shared_ptr<PCHContainerOperations> PCHContainerOps,1277 CompilerInvocation &PreambleInvocationIn,1278 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,1279 unsigned MaxLines) {1280 auto MainFilePath =1281 PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();1282 std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =1283 getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),1284 MainFilePath, UserFilesAreVolatile);1285 if (!MainFileBuffer)1286 return nullptr;1287 1288 PreambleBounds Bounds = ComputePreambleBounds(1289 PreambleInvocationIn.getLangOpts(), *MainFileBuffer, MaxLines);1290 if (!Bounds.Size)1291 return nullptr;1292 1293 if (Preamble) {1294 if (Preamble->CanReuse(PreambleInvocationIn, *MainFileBuffer, Bounds,1295 *VFS)) {1296 // Okay! We can re-use the precompiled preamble.1297 1298 // Set the state of the diagnostic object to mimic its state1299 // after parsing the preamble.1300 getDiagnostics().Reset();1301 ProcessWarningOptions(getDiagnostics(),1302 PreambleInvocationIn.getDiagnosticOpts(), *VFS);1303 getDiagnostics().setNumWarnings(NumWarningsInPreamble);1304 1305 PreambleRebuildCountdown = 1;1306 return MainFileBuffer;1307 } else {1308 Preamble.reset();1309 PreambleDiagnostics.clear();1310 TopLevelDeclsInPreamble.clear();1311 PreambleSrcLocCache.clear();1312 PreambleRebuildCountdown = 1;1313 }1314 }1315 1316 // If the preamble rebuild counter > 1, it's because we previously1317 // failed to build a preamble and we're not yet ready to try1318 // again. Decrement the counter and return a failure.1319 if (PreambleRebuildCountdown > 1) {1320 --PreambleRebuildCountdown;1321 return nullptr;1322 }1323 1324 assert(!Preamble && "No Preamble should be stored at that point");1325 // If we aren't allowed to rebuild the precompiled preamble, just1326 // return now.1327 if (!AllowRebuild)1328 return nullptr;1329 1330 ++PreambleCounter;1331 1332 SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone;1333 SmallVector<StoredDiagnostic, 4> NewPreambleDiags;1334 ASTUnitPreambleCallbacks Callbacks;1335 {1336 std::optional<CaptureDroppedDiagnostics> Capture;1337 if (CaptureDiagnostics != CaptureDiagsKind::None)1338 Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags,1339 &NewPreambleDiagsStandalone);1340 1341 // We did not previously compute a preamble, or it can't be reused anyway.1342 SimpleTimer PreambleTimer(WantTiming);1343 PreambleTimer.setOutput("Precompiling preamble");1344 1345 const bool PreviousSkipFunctionBodies =1346 PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;1347 if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)1348 PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;1349 1350 llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(1351 PreambleInvocationIn, MainFileBuffer.get(), Bounds, Diagnostics, VFS,1352 PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath,1353 Callbacks);1354 1355 PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =1356 PreviousSkipFunctionBodies;1357 1358 if (NewPreamble) {1359 Preamble = std::move(*NewPreamble);1360 PreambleRebuildCountdown = 1;1361 } else {1362 switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {1363 case BuildPreambleError::CouldntCreateTempFile:1364 // Try again next time.1365 PreambleRebuildCountdown = 1;1366 return nullptr;1367 case BuildPreambleError::CouldntCreateTargetInfo:1368 case BuildPreambleError::BeginSourceFileFailed:1369 case BuildPreambleError::CouldntEmitPCH:1370 case BuildPreambleError::BadInputs:1371 // These erros are more likely to repeat, retry after some period.1372 PreambleRebuildCountdown = DefaultPreambleRebuildInterval;1373 return nullptr;1374 }1375 llvm_unreachable("unexpected BuildPreambleError");1376 }1377 }1378 1379 assert(Preamble && "Preamble wasn't built");1380 1381 TopLevelDecls.clear();1382 TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs();1383 PreambleTopLevelHashValue = Callbacks.getHash();1384 1385 NumWarningsInPreamble = getDiagnostics().getNumWarnings();1386 1387 checkAndRemoveNonDriverDiags(NewPreambleDiags);1388 StoredDiagnostics = std::move(NewPreambleDiags);1389 PreambleDiagnostics = std::move(NewPreambleDiagsStandalone);1390 1391 // If the hash of top-level entities differs from the hash of the top-level1392 // entities the last time we rebuilt the preamble, clear out the completion1393 // cache.1394 if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {1395 CompletionCacheTopLevelHashValue = 0;1396 PreambleTopLevelHashValue = CurrentTopLevelHashValue;1397 }1398 1399 return MainFileBuffer;1400}1401 1402void ASTUnit::RealizeTopLevelDeclsFromPreamble() {1403 assert(Preamble && "Should only be called when preamble was built");1404 1405 std::vector<Decl *> Resolved;1406 Resolved.reserve(TopLevelDeclsInPreamble.size());1407 // The module file of the preamble.1408 serialization::ModuleFile &MF = Reader->getModuleManager().getPrimaryModule();1409 for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {1410 // Resolve the declaration ID to an actual declaration, possibly1411 // deserializing the declaration in the process.1412 if (Decl *D = Reader->GetLocalDecl(MF, TopLevelDecl))1413 Resolved.push_back(D);1414 }1415 TopLevelDeclsInPreamble.clear();1416 TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());1417}1418 1419void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {1420 // Steal the created target, context, and preprocessor if they have been1421 // created.1422 LangOpts = std::make_unique<LangOptions>(CI.getInvocation().getLangOpts());1423 TheSema = CI.takeSema();1424 Consumer = CI.takeASTConsumer();1425 if (CI.hasASTContext())1426 Ctx = CI.getASTContextPtr();1427 if (CI.hasPreprocessor())1428 PP = CI.getPreprocessorPtr();1429 CI.setSourceManager(nullptr);1430 CI.setFileManager(nullptr);1431 if (CI.hasTarget())1432 Target = CI.getTargetPtr();1433 Reader = CI.getASTReader();1434 HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();1435 if (Invocation != CI.getInvocationPtr()) {1436 // This happens when Parse creates a copy of \c Invocation to modify.1437 ModifiedInvocation = CI.getInvocationPtr();1438 }1439}1440 1441StringRef ASTUnit::getMainFileName() const {1442 if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) {1443 const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0];1444 if (Input.isFile())1445 return Input.getFile();1446 else1447 return Input.getBuffer().getBufferIdentifier();1448 }1449 1450 if (SourceMgr) {1451 if (OptionalFileEntryRef FE =1452 SourceMgr->getFileEntryRefForID(SourceMgr->getMainFileID()))1453 return FE->getName();1454 }1455 1456 return {};1457}1458 1459StringRef ASTUnit::getASTFileName() const {1460 if (!isMainFileAST())1461 return {};1462 1463 serialization::ModuleFile &1464 Mod = Reader->getModuleManager().getPrimaryModule();1465 return Mod.FileName;1466}1467 1468std::unique_ptr<ASTUnit>1469ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,1470 std::shared_ptr<DiagnosticOptions> DiagOpts,1471 IntrusiveRefCntPtr<DiagnosticsEngine> Diags,1472 CaptureDiagsKind CaptureDiagnostics,1473 bool UserFilesAreVolatile) {1474 std::unique_ptr<ASTUnit> AST(new ASTUnit(false));1475 ConfigureDiags(Diags, *AST, CaptureDiagnostics);1476 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =1477 createVFSFromCompilerInvocation(*CI, *Diags);1478 AST->DiagOpts = DiagOpts;1479 AST->Diagnostics = Diags;1480 AST->FileSystemOpts = CI->getFileSystemOpts();1481 AST->Invocation = std::move(CI);1482 AST->FileMgr =1483 llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);1484 AST->UserFilesAreVolatile = UserFilesAreVolatile;1485 AST->SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(1486 AST->getDiagnostics(), *AST->FileMgr, UserFilesAreVolatile);1487 AST->ModCache = createCrossProcessModuleCache();1488 1489 return AST;1490}1491 1492ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(1493 std::shared_ptr<CompilerInvocation> CI,1494 std::shared_ptr<PCHContainerOperations> PCHContainerOps,1495 std::shared_ptr<DiagnosticOptions> DiagOpts,1496 IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action,1497 ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,1498 bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,1499 unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,1500 bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {1501 assert(CI && "A CompilerInvocation is required");1502 1503 std::unique_ptr<ASTUnit> OwnAST;1504 ASTUnit *AST = Unit;1505 if (!AST) {1506 // Create the AST unit.1507 OwnAST =1508 create(CI, DiagOpts, Diags, CaptureDiagnostics, UserFilesAreVolatile);1509 AST = OwnAST.get();1510 if (!AST)1511 return nullptr;1512 }1513 1514 if (!ResourceFilesPath.empty()) {1515 // Override the resources path.1516 CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);1517 }1518 AST->OnlyLocalDecls = OnlyLocalDecls;1519 AST->CaptureDiagnostics = CaptureDiagnostics;1520 if (PrecompilePreambleAfterNParses > 0)1521 AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses;1522 AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;1523 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1524 AST->IncludeBriefCommentsInCodeCompletion = false;1525 1526 // Recover resources if we crash before exiting this method.1527 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1528 ASTUnitCleanup(OwnAST.get());1529 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,1530 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>1531 DiagCleanup(Diags.get());1532 1533 // We'll manage file buffers ourselves.1534 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;1535 CI->getFrontendOpts().DisableFree = false;1536 ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts(),1537 AST->getFileManager().getVirtualFileSystem());1538 1539 // Create the compiler instance to use for building the AST.1540 auto Clang = std::make_unique<CompilerInstance>(std::move(CI),1541 std::move(PCHContainerOps));1542 1543 // Recover resources if we crash before exiting this method.1544 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>1545 CICleanup(Clang.get());1546 1547 AST->OriginalSourceFile =1548 std::string(Clang->getFrontendOpts().Inputs[0].getFile());1549 1550 // Set up diagnostics, capturing any diagnostics that would1551 // otherwise be dropped.1552 Clang->setDiagnostics(AST->getDiagnosticsPtr());1553 1554 // Create the target instance.1555 if (!Clang->createTarget())1556 return nullptr;1557 1558 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&1559 "Invocation must have exactly one source file!");1560 assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==1561 InputKind::Source &&1562 "FIXME: AST inputs not yet supported here!");1563 assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=1564 Language::LLVM_IR &&1565 "IR inputs not support here!");1566 1567 // Configure the various subsystems.1568 AST->TheSema.reset();1569 AST->Ctx = nullptr;1570 AST->PP = nullptr;1571 AST->Reader = nullptr;1572 1573 // Create a file manager object to provide access to and cache the filesystem.1574 Clang->setVirtualFileSystem(AST->getVirtualFileSystemPtr());1575 Clang->setFileManager(AST->getFileManagerPtr());1576 1577 // Create the source manager.1578 Clang->setSourceManager(AST->getSourceManagerPtr());1579 1580 FrontendAction *Act = Action;1581 1582 std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct;1583 if (!Act) {1584 TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));1585 Act = TrackerAct.get();1586 }1587 1588 // Recover resources if we crash before exiting this method.1589 llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>1590 ActCleanup(TrackerAct.get());1591 1592 if (!Act->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {1593 AST->transferASTDataFromCompilerInstance(*Clang);1594 if (OwnAST && ErrAST)1595 ErrAST->swap(OwnAST);1596 1597 return nullptr;1598 }1599 1600 if (Persistent && !TrackerAct) {1601 Clang->getPreprocessor().addPPCallbacks(1602 std::make_unique<MacroDefinitionTrackerPPCallbacks>(1603 AST->getCurrentTopLevelHashValue()));1604 std::vector<std::unique_ptr<ASTConsumer>> Consumers;1605 if (Clang->hasASTConsumer())1606 Consumers.push_back(Clang->takeASTConsumer());1607 Consumers.push_back(std::make_unique<TopLevelDeclTrackerConsumer>(1608 *AST, AST->getCurrentTopLevelHashValue()));1609 Clang->setASTConsumer(1610 std::make_unique<MultiplexConsumer>(std::move(Consumers)));1611 }1612 if (llvm::Error Err = Act->Execute()) {1613 consumeError(std::move(Err)); // FIXME this drops errors on the floor.1614 AST->transferASTDataFromCompilerInstance(*Clang);1615 if (OwnAST && ErrAST)1616 ErrAST->swap(OwnAST);1617 1618 return nullptr;1619 }1620 1621 // Steal the created target, context, and preprocessor.1622 AST->transferASTDataFromCompilerInstance(*Clang);1623 1624 Act->EndSourceFile();1625 1626 if (OwnAST)1627 return OwnAST.release();1628 else1629 return AST;1630}1631 1632bool ASTUnit::LoadFromCompilerInvocation(1633 std::shared_ptr<PCHContainerOperations> PCHContainerOps,1634 unsigned PrecompilePreambleAfterNParses,1635 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1636 if (!Invocation)1637 return true;1638 1639 assert(VFS && "VFS is null");1640 1641 // We'll manage file buffers ourselves.1642 Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;1643 Invocation->getFrontendOpts().DisableFree = false;1644 getDiagnostics().Reset();1645 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(),1646 *VFS);1647 1648 std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;1649 if (PrecompilePreambleAfterNParses > 0) {1650 PreambleRebuildCountdown = PrecompilePreambleAfterNParses;1651 OverrideMainBuffer =1652 getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);1653 getDiagnostics().Reset();1654 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(),1655 *VFS);1656 }1657 1658 SimpleTimer ParsingTimer(WantTiming);1659 ParsingTimer.setOutput("Parsing " + getMainFileName());1660 1661 // Recover resources if we crash before exiting this method.1662 llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>1663 MemBufferCleanup(OverrideMainBuffer.get());1664 1665 return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);1666}1667 1668std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(1669 std::shared_ptr<CompilerInvocation> CI,1670 std::shared_ptr<PCHContainerOperations> PCHContainerOps,1671 std::shared_ptr<DiagnosticOptions> DiagOpts,1672 IntrusiveRefCntPtr<DiagnosticsEngine> Diags,1673 IntrusiveRefCntPtr<FileManager> FileMgr, bool OnlyLocalDecls,1674 CaptureDiagsKind CaptureDiagnostics,1675 unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,1676 bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,1677 bool UserFilesAreVolatile) {1678 // Create the AST unit.1679 std::unique_ptr<ASTUnit> AST(new ASTUnit(false));1680 ConfigureDiags(Diags, *AST, CaptureDiagnostics);1681 AST->DiagOpts = DiagOpts;1682 AST->Diagnostics = Diags;1683 AST->OnlyLocalDecls = OnlyLocalDecls;1684 AST->CaptureDiagnostics = CaptureDiagnostics;1685 AST->TUKind = TUKind;1686 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;1687 AST->IncludeBriefCommentsInCodeCompletion1688 = IncludeBriefCommentsInCodeCompletion;1689 AST->Invocation = std::move(CI);1690 AST->FileSystemOpts = FileMgr->getFileSystemOpts();1691 AST->FileMgr = FileMgr;1692 AST->UserFilesAreVolatile = UserFilesAreVolatile;1693 1694 // Recover resources if we crash before exiting this method.1695 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>1696 ASTUnitCleanup(AST.get());1697 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,1698 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>1699 DiagCleanup(Diags.get());1700 1701 if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),1702 PrecompilePreambleAfterNParses,1703 AST->FileMgr->getVirtualFileSystemPtr()))1704 return nullptr;1705 return AST;1706}1707 1708bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,1709 ArrayRef<RemappedFile> RemappedFiles,1710 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {1711 if (!Invocation)1712 return true;1713 1714 if (!VFS) {1715 assert(FileMgr && "FileMgr is null on Reparse call");1716 VFS = FileMgr->getVirtualFileSystemPtr();1717 }1718 1719 clearFileLevelDecls();1720 1721 SimpleTimer ParsingTimer(WantTiming);1722 ParsingTimer.setOutput("Reparsing " + getMainFileName());1723 1724 // Remap files.1725 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();1726 for (const auto &RB : PPOpts.RemappedFileBuffers)1727 delete RB.second;1728 1729 Invocation->getPreprocessorOpts().clearRemappedFiles();1730 for (const auto &RemappedFile : RemappedFiles) {1731 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first,1732 RemappedFile.second);1733 }1734 1735 // If we have a preamble file lying around, or if we might try to1736 // build a precompiled preamble, do so now.1737 std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;1738 if (Preamble || PreambleRebuildCountdown > 0)1739 OverrideMainBuffer =1740 getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);1741 1742 // Clear out the diagnostics state.1743 FileMgr.reset();1744 getDiagnostics().Reset();1745 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(),1746 *VFS);1747 if (OverrideMainBuffer)1748 getDiagnostics().setNumWarnings(NumWarningsInPreamble);1749 1750 // Parse the sources1751 bool Result =1752 Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);1753 1754 // If we're caching global code-completion results, and the top-level1755 // declarations have changed, clear out the code-completion cache.1756 if (!Result && ShouldCacheCodeCompletionResults &&1757 CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)1758 CacheCodeCompletionResults();1759 1760 // We now need to clear out the completion info related to this translation1761 // unit; it'll be recreated if necessary.1762 CCTUInfo.reset();1763 1764 return Result;1765}1766 1767void ASTUnit::ResetForParse() {1768 SavedMainFileBuffer.reset();1769 1770 SourceMgr.reset();1771 TheSema.reset();1772 Ctx.reset();1773 PP.reset();1774 Reader.reset();1775 1776 TopLevelDecls.clear();1777 clearFileLevelDecls();1778}1779 1780//----------------------------------------------------------------------------//1781// Code completion1782//----------------------------------------------------------------------------//1783 1784namespace {1785 1786 /// Code completion consumer that combines the cached code-completion1787 /// results from an ASTUnit with the code-completion results provided to it,1788 /// then passes the result on to1789 class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {1790 uint64_t NormalContexts;1791 ASTUnit &AST;1792 CodeCompleteConsumer &Next;1793 1794 public:1795 AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,1796 const CodeCompleteOptions &CodeCompleteOpts)1797 : CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) {1798 // Compute the set of contexts in which we will look when we don't have1799 // any information about the specific context.1800 NormalContexts1801 = (1LL << CodeCompletionContext::CCC_TopLevel)1802 | (1LL << CodeCompletionContext::CCC_ObjCInterface)1803 | (1LL << CodeCompletionContext::CCC_ObjCImplementation)1804 | (1LL << CodeCompletionContext::CCC_ObjCIvarList)1805 | (1LL << CodeCompletionContext::CCC_Statement)1806 | (1LL << CodeCompletionContext::CCC_Expression)1807 | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)1808 | (1LL << CodeCompletionContext::CCC_DotMemberAccess)1809 | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)1810 | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)1811 | (1LL << CodeCompletionContext::CCC_ObjCProtocolName)1812 | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)1813 | (1LL << CodeCompletionContext::CCC_Recovery);1814 1815 if (AST.getASTContext().getLangOpts().CPlusPlus)1816 NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)1817 | (1LL << CodeCompletionContext::CCC_UnionTag)1818 | (1LL << CodeCompletionContext::CCC_ClassOrStructTag);1819 }1820 1821 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,1822 CodeCompletionResult *Results,1823 unsigned NumResults) override;1824 1825 void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,1826 OverloadCandidate *Candidates,1827 unsigned NumCandidates,1828 SourceLocation OpenParLoc,1829 bool Braced) override {1830 Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,1831 OpenParLoc, Braced);1832 }1833 1834 CodeCompletionAllocator &getAllocator() override {1835 return Next.getAllocator();1836 }1837 1838 CodeCompletionTUInfo &getCodeCompletionTUInfo() override {1839 return Next.getCodeCompletionTUInfo();1840 }1841 };1842 1843} // namespace1844 1845/// Helper function that computes which global names are hidden by the1846/// local code-completion results.1847static void CalculateHiddenNames(const CodeCompletionContext &Context,1848 CodeCompletionResult *Results,1849 unsigned NumResults,1850 ASTContext &Ctx,1851 llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){1852 bool OnlyTagNames = false;1853 switch (Context.getKind()) {1854 case CodeCompletionContext::CCC_Recovery:1855 case CodeCompletionContext::CCC_TopLevel:1856 case CodeCompletionContext::CCC_ObjCInterface:1857 case CodeCompletionContext::CCC_ObjCImplementation:1858 case CodeCompletionContext::CCC_ObjCIvarList:1859 case CodeCompletionContext::CCC_ClassStructUnion:1860 case CodeCompletionContext::CCC_Statement:1861 case CodeCompletionContext::CCC_Expression:1862 case CodeCompletionContext::CCC_ObjCMessageReceiver:1863 case CodeCompletionContext::CCC_DotMemberAccess:1864 case CodeCompletionContext::CCC_ArrowMemberAccess:1865 case CodeCompletionContext::CCC_ObjCPropertyAccess:1866 case CodeCompletionContext::CCC_Namespace:1867 case CodeCompletionContext::CCC_Type:1868 case CodeCompletionContext::CCC_Symbol:1869 case CodeCompletionContext::CCC_SymbolOrNewName:1870 case CodeCompletionContext::CCC_ParenthesizedExpression:1871 case CodeCompletionContext::CCC_ObjCInterfaceName:1872 case CodeCompletionContext::CCC_TopLevelOrExpression:1873 break;1874 1875 case CodeCompletionContext::CCC_EnumTag:1876 case CodeCompletionContext::CCC_UnionTag:1877 case CodeCompletionContext::CCC_ClassOrStructTag:1878 OnlyTagNames = true;1879 break;1880 1881 case CodeCompletionContext::CCC_ObjCProtocolName:1882 case CodeCompletionContext::CCC_MacroName:1883 case CodeCompletionContext::CCC_MacroNameUse:1884 case CodeCompletionContext::CCC_PreprocessorExpression:1885 case CodeCompletionContext::CCC_PreprocessorDirective:1886 case CodeCompletionContext::CCC_NaturalLanguage:1887 case CodeCompletionContext::CCC_SelectorName:1888 case CodeCompletionContext::CCC_TypeQualifiers:1889 case CodeCompletionContext::CCC_Other:1890 case CodeCompletionContext::CCC_OtherWithMacros:1891 case CodeCompletionContext::CCC_ObjCInstanceMessage:1892 case CodeCompletionContext::CCC_ObjCClassMessage:1893 case CodeCompletionContext::CCC_ObjCCategoryName:1894 case CodeCompletionContext::CCC_IncludedFile:1895 case CodeCompletionContext::CCC_Attribute:1896 case CodeCompletionContext::CCC_NewName:1897 case CodeCompletionContext::CCC_ObjCClassForwardDecl:1898 // We're looking for nothing, or we're looking for names that cannot1899 // be hidden.1900 return;1901 }1902 1903 using Result = CodeCompletionResult;1904 for (unsigned I = 0; I != NumResults; ++I) {1905 if (Results[I].Kind != Result::RK_Declaration)1906 continue;1907 1908 unsigned IDNS1909 = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();1910 1911 bool Hiding = false;1912 if (OnlyTagNames)1913 Hiding = (IDNS & Decl::IDNS_Tag);1914 else {1915 unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |1916 Decl::IDNS_Namespace | Decl::IDNS_Ordinary |1917 Decl::IDNS_NonMemberOperator);1918 if (Ctx.getLangOpts().CPlusPlus)1919 HiddenIDNS |= Decl::IDNS_Tag;1920 Hiding = (IDNS & HiddenIDNS);1921 }1922 1923 if (!Hiding)1924 continue;1925 1926 DeclarationName Name = Results[I].Declaration->getDeclName();1927 if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())1928 HiddenNames.insert(Identifier->getName());1929 else1930 HiddenNames.insert(Name.getAsString());1931 }1932}1933 1934void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,1935 CodeCompletionContext Context,1936 CodeCompletionResult *Results,1937 unsigned NumResults) {1938 // Merge the results we were given with the results we cached.1939 bool AddedResult = false;1940 uint64_t InContexts =1941 Context.getKind() == CodeCompletionContext::CCC_Recovery1942 ? NormalContexts : (1LL << Context.getKind());1943 // Contains the set of names that are hidden by "local" completion results.1944 llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;1945 using Result = CodeCompletionResult;1946 SmallVector<Result, 8> AllResults;1947 for (ASTUnit::cached_completion_iterator1948 C = AST.cached_completion_begin(),1949 CEnd = AST.cached_completion_end();1950 C != CEnd; ++C) {1951 // If the context we are in matches any of the contexts we are1952 // interested in, we'll add this result.1953 if ((C->ShowInContexts & InContexts) == 0)1954 continue;1955 1956 // If we haven't added any results previously, do so now.1957 if (!AddedResult) {1958 CalculateHiddenNames(Context, Results, NumResults, S.Context,1959 HiddenNames);1960 AllResults.insert(AllResults.end(), Results, Results + NumResults);1961 AddedResult = true;1962 }1963 1964 // Determine whether this global completion result is hidden by a local1965 // completion result. If so, skip it.1966 if (C->Kind != CXCursor_MacroDefinition &&1967 HiddenNames.count(C->Completion->getTypedText()))1968 continue;1969 1970 // Adjust priority based on similar type classes.1971 unsigned Priority = C->Priority;1972 CodeCompletionString *Completion = C->Completion;1973 if (!Context.getPreferredType().isNull()) {1974 if (C->Kind == CXCursor_MacroDefinition) {1975 Priority = getMacroUsagePriority(C->Completion->getTypedText(),1976 S.getLangOpts(),1977 Context.getPreferredType()->isAnyPointerType());1978 } else if (C->Type) {1979 CanQualType Expected1980 = S.Context.getCanonicalType(1981 Context.getPreferredType().getUnqualifiedType());1982 SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);1983 if (ExpectedSTC == C->TypeClass) {1984 // We know this type is similar; check for an exact match.1985 llvm::StringMap<unsigned> &CachedCompletionTypes1986 = AST.getCachedCompletionTypes();1987 llvm::StringMap<unsigned>::iterator Pos1988 = CachedCompletionTypes.find(QualType(Expected).getAsString());1989 if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)1990 Priority /= CCF_ExactTypeMatch;1991 else1992 Priority /= CCF_SimilarTypeMatch;1993 }1994 }1995 }1996 1997 // Adjust the completion string, if required.1998 if (C->Kind == CXCursor_MacroDefinition &&1999 Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {2000 // Create a new code-completion string that just contains the2001 // macro name, without its arguments.2002 CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),2003 CCP_CodePattern, C->Availability);2004 Builder.AddTypedTextChunk(C->Completion->getTypedText());2005 Priority = CCP_CodePattern;2006 Completion = Builder.TakeString();2007 }2008 2009 AllResults.push_back(Result(Completion, Priority, C->Kind,2010 C->Availability));2011 }2012 2013 // If we did not add any cached completion results, just forward the2014 // results we were given to the next consumer.2015 if (!AddedResult) {2016 Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);2017 return;2018 }2019 2020 Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),2021 AllResults.size());2022}2023 2024void ASTUnit::CodeComplete(2025 StringRef File, unsigned Line, unsigned Column,2026 ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,2027 bool IncludeCodePatterns, bool IncludeBriefComments,2028 CodeCompleteConsumer &Consumer,2029 std::shared_ptr<PCHContainerOperations> PCHContainerOps,2030 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diag, LangOptions &LangOpts,2031 llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr,2032 llvm::IntrusiveRefCntPtr<FileManager> FileMgr,2033 SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,2034 SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers,2035 std::unique_ptr<SyntaxOnlyAction> Act) {2036 if (!Invocation)2037 return;2038 2039 SimpleTimer CompletionTimer(WantTiming);2040 CompletionTimer.setOutput("Code completion @ " + File + ":" +2041 Twine(Line) + ":" + Twine(Column));2042 2043 auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);2044 2045 FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();2046 CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;2047 PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();2048 2049 CodeCompleteOpts.IncludeMacros = IncludeMacros &&2050 CachedCompletionResults.empty();2051 CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;2052 CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();2053 CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;2054 CodeCompleteOpts.LoadExternal = Consumer.loadExternal();2055 CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts();2056 2057 assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);2058 2059 FrontendOpts.CodeCompletionAt.FileName = std::string(File);2060 FrontendOpts.CodeCompletionAt.Line = Line;2061 FrontendOpts.CodeCompletionAt.Column = Column;2062 2063 // Set the language options appropriately.2064 LangOpts = CCInvocation->getLangOpts();2065 2066 // Spell-checking and warnings are wasteful during code-completion.2067 LangOpts.SpellChecking = false;2068 CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;2069 2070 auto Clang = std::make_unique<CompilerInstance>(std::move(CCInvocation),2071 PCHContainerOps);2072 2073 // Recover resources if we crash before exiting this method.2074 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>2075 CICleanup(Clang.get());2076 2077 auto &Inv = Clang->getInvocation();2078 OriginalSourceFile =2079 std::string(Clang->getFrontendOpts().Inputs[0].getFile());2080 2081 // Set up diagnostics, capturing any diagnostics produced.2082 Clang->setDiagnostics(Diag);2083 CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All,2084 Clang->getDiagnostics(),2085 &StoredDiagnostics, nullptr);2086 ProcessWarningOptions(*Diag, Inv.getDiagnosticOpts(),2087 FileMgr->getVirtualFileSystem());2088 2089 // Create the target instance.2090 if (!Clang->createTarget()) {2091 return;2092 }2093 2094 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&2095 "Invocation must have exactly one source file!");2096 assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==2097 InputKind::Source &&2098 "FIXME: AST inputs not yet supported here!");2099 assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=2100 Language::LLVM_IR &&2101 "IR inputs not support here!");2102 2103 // Use the source and file managers that we were given.2104 Clang->setVirtualFileSystem(FileMgr->getVirtualFileSystemPtr());2105 Clang->setFileManager(FileMgr);2106 Clang->setSourceManager(SourceMgr);2107 2108 // Remap files.2109 PreprocessorOpts.clearRemappedFiles();2110 PreprocessorOpts.RetainRemappedFileBuffers = true;2111 for (const auto &RemappedFile : RemappedFiles) {2112 PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second);2113 OwnedBuffers.push_back(RemappedFile.second);2114 }2115 2116 // Use the code completion consumer we were given, but adding any cached2117 // code-completion results.2118 AugmentedCodeCompleteConsumer *AugmentedConsumer2119 = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);2120 Clang->setCodeCompletionConsumer(AugmentedConsumer);2121 2122 auto getUniqueID =2123 [&FileMgr](StringRef Filename) -> std::optional<llvm::sys::fs::UniqueID> {2124 if (auto Status = FileMgr->getVirtualFileSystem().status(Filename))2125 return Status->getUniqueID();2126 return std::nullopt;2127 };2128 2129 auto hasSameUniqueID = [getUniqueID](StringRef LHS, StringRef RHS) {2130 if (LHS == RHS)2131 return true;2132 if (auto LHSID = getUniqueID(LHS))2133 if (auto RHSID = getUniqueID(RHS))2134 return *LHSID == *RHSID;2135 return false;2136 };2137 2138 // If we have a precompiled preamble, try to use it. We only allow2139 // the use of the precompiled preamble if we're if the completion2140 // point is within the main file, after the end of the precompiled2141 // preamble.2142 std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;2143 if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) {2144 OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(2145 PCHContainerOps, Inv, FileMgr->getVirtualFileSystemPtr(), false,2146 Line - 1);2147 }2148 2149 // If the main file has been overridden due to the use of a preamble,2150 // make that override happen and introduce the preamble.2151 if (OverrideMainBuffer) {2152 assert(Preamble &&2153 "No preamble was built, but OverrideMainBuffer is not null");2154 2155 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =2156 FileMgr->getVirtualFileSystemPtr();2157 Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,2158 OverrideMainBuffer.get());2159 // FIXME: there is no way to update VFS if it was changed by2160 // AddImplicitPreamble as FileMgr is accepted as a parameter by this method.2161 // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the2162 // PCH files are always readable.2163 OwnedBuffers.push_back(OverrideMainBuffer.release());2164 } else {2165 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;2166 PreprocessorOpts.PrecompiledPreambleBytes.second = false;2167 }2168 2169 // Disable the preprocessing record if modules are not enabled.2170 if (!Clang->getLangOpts().Modules)2171 PreprocessorOpts.DetailedRecord = false;2172 2173 if (!Act)2174 Act.reset(new SyntaxOnlyAction);2175 2176 if (Act->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {2177 if (llvm::Error Err = Act->Execute()) {2178 consumeError(std::move(Err)); // FIXME this drops errors on the floor.2179 }2180 Act->EndSourceFile();2181 }2182}2183 2184bool ASTUnit::Save(StringRef File) {2185 if (HadModuleLoaderFatalFailure)2186 return true;2187 2188 // FIXME: Can we somehow regenerate the stat cache here, or do we need to2189 // unconditionally create a stat cache when we parse the file?2190 2191 if (llvm::Error Err = llvm::writeToOutput(2192 File, [this](llvm::raw_ostream &Out) {2193 return serialize(Out) ? llvm::make_error<llvm::StringError>(2194 "ASTUnit serialization failed",2195 llvm::inconvertibleErrorCode())2196 : llvm::Error::success();2197 })) {2198 consumeError(std::move(Err));2199 return true;2200 }2201 return false;2202}2203 2204static bool serializeUnit(ASTWriter &Writer, SmallVectorImpl<char> &Buffer,2205 Sema &S, raw_ostream &OS) {2206 Writer.WriteAST(&S, std::string(), nullptr, "");2207 2208 // Write the generated bitstream to "Out".2209 if (!Buffer.empty())2210 OS.write(Buffer.data(), Buffer.size());2211 2212 return false;2213}2214 2215bool ASTUnit::serialize(raw_ostream &OS) {2216 if (WriterData)2217 return serializeUnit(WriterData->Writer, WriterData->Buffer, getSema(), OS);2218 2219 SmallString<128> Buffer;2220 llvm::BitstreamWriter Stream(Buffer);2221 IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();2222 ASTWriter Writer(Stream, Buffer, *ModCache, *CodeGenOpts, {});2223 return serializeUnit(Writer, Buffer, getSema(), OS);2224}2225 2226void ASTUnit::addFileLevelDecl(Decl *D) {2227 assert(D);2228 2229 // We only care about local declarations.2230 if (D->isFromASTFile())2231 return;2232 2233 SourceManager &SM = *SourceMgr;2234 SourceLocation Loc = D->getLocation();2235 if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc))2236 return;2237 2238 // We only keep track of the file-level declarations of each file.2239 if (!D->getLexicalDeclContext()->isFileContext())2240 return;2241 2242 SourceLocation FileLoc = SM.getFileLoc(Loc);2243 assert(SM.isLocalSourceLocation(FileLoc));2244 auto [FID, Offset] = SM.getDecomposedLoc(FileLoc);2245 if (FID.isInvalid())2246 return;2247 2248 std::unique_ptr<LocDeclsTy> &Decls = FileDecls[FID];2249 if (!Decls)2250 Decls = std::make_unique<LocDeclsTy>();2251 2252 std::pair<unsigned, Decl *> LocDecl(Offset, D);2253 2254 if (Decls->empty() || Decls->back().first <= Offset) {2255 Decls->push_back(LocDecl);2256 return;2257 }2258 2259 LocDeclsTy::iterator I =2260 llvm::upper_bound(*Decls, LocDecl, llvm::less_first());2261 2262 Decls->insert(I, LocDecl);2263}2264 2265void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,2266 SmallVectorImpl<Decl *> &Decls) {2267 if (File.isInvalid())2268 return;2269 2270 if (SourceMgr->isLoadedFileID(File)) {2271 assert(Ctx->getExternalSource() && "No external source!");2272 return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length,2273 Decls);2274 }2275 2276 FileDeclsTy::iterator I = FileDecls.find(File);2277 if (I == FileDecls.end())2278 return;2279 2280 LocDeclsTy &LocDecls = *I->second;2281 if (LocDecls.empty())2282 return;2283 2284 LocDeclsTy::iterator BeginIt =2285 llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) {2286 return LD.first < Offset;2287 });2288 if (BeginIt != LocDecls.begin())2289 --BeginIt;2290 2291 // If we are pointing at a top-level decl inside an objc container, we need2292 // to backtrack until we find it otherwise we will fail to report that the2293 // region overlaps with an objc container.2294 while (BeginIt != LocDecls.begin() &&2295 BeginIt->second->isTopLevelDeclInObjCContainer())2296 --BeginIt;2297 2298 LocDeclsTy::iterator EndIt = llvm::upper_bound(2299 LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr),2300 llvm::less_first());2301 if (EndIt != LocDecls.end())2302 ++EndIt;2303 2304 for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)2305 Decls.push_back(DIt->second);2306}2307 2308SourceLocation ASTUnit::getLocation(const FileEntry *File,2309 unsigned Line, unsigned Col) const {2310 const SourceManager &SM = getSourceManager();2311 SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);2312 return SM.getMacroArgExpandedLocation(Loc);2313}2314 2315SourceLocation ASTUnit::getLocation(const FileEntry *File,2316 unsigned Offset) const {2317 const SourceManager &SM = getSourceManager();2318 SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);2319 return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));2320}2321 2322/// If \arg Loc is a loaded location from the preamble, returns2323/// the corresponding local location of the main file, otherwise it returns2324/// \arg Loc.2325SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {2326 FileID PreambleID;2327 if (SourceMgr)2328 PreambleID = SourceMgr->getPreambleFileID();2329 2330 if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())2331 return Loc;2332 2333 unsigned Offs;2334 if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) {2335 SourceLocation FileLoc2336 = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());2337 return FileLoc.getLocWithOffset(Offs);2338 }2339 2340 return Loc;2341}2342 2343/// If \arg Loc is a local location of the main file but inside the2344/// preamble chunk, returns the corresponding loaded location from the2345/// preamble, otherwise it returns \arg Loc.2346SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {2347 FileID PreambleID;2348 if (SourceMgr)2349 PreambleID = SourceMgr->getPreambleFileID();2350 2351 if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())2352 return Loc;2353 2354 unsigned Offs;2355 if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&2356 Offs < Preamble->getBounds().Size) {2357 SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);2358 return FileLoc.getLocWithOffset(Offs);2359 }2360 2361 return Loc;2362}2363 2364bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {2365 FileID FID;2366 if (SourceMgr)2367 FID = SourceMgr->getPreambleFileID();2368 2369 if (Loc.isInvalid() || FID.isInvalid())2370 return false;2371 2372 return SourceMgr->isInFileID(Loc, FID);2373}2374 2375bool ASTUnit::isInMainFileID(SourceLocation Loc) const {2376 FileID FID;2377 if (SourceMgr)2378 FID = SourceMgr->getMainFileID();2379 2380 if (Loc.isInvalid() || FID.isInvalid())2381 return false;2382 2383 return SourceMgr->isInFileID(Loc, FID);2384}2385 2386SourceLocation ASTUnit::getEndOfPreambleFileID() const {2387 FileID FID;2388 if (SourceMgr)2389 FID = SourceMgr->getPreambleFileID();2390 2391 if (FID.isInvalid())2392 return {};2393 2394 return SourceMgr->getLocForEndOfFile(FID);2395}2396 2397SourceLocation ASTUnit::getStartOfMainFileID() const {2398 FileID FID;2399 if (SourceMgr)2400 FID = SourceMgr->getMainFileID();2401 2402 if (FID.isInvalid())2403 return {};2404 2405 return SourceMgr->getLocForStartOfFile(FID);2406}2407 2408llvm::iterator_range<PreprocessingRecord::iterator>2409ASTUnit::getLocalPreprocessingEntities() const {2410 if (isMainFileAST()) {2411 serialization::ModuleFile &2412 Mod = Reader->getModuleManager().getPrimaryModule();2413 return Reader->getModulePreprocessedEntities(Mod);2414 }2415 2416 if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())2417 return llvm::make_range(PPRec->local_begin(), PPRec->local_end());2418 2419 return llvm::make_range(PreprocessingRecord::iterator(),2420 PreprocessingRecord::iterator());2421}2422 2423bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {2424 if (isMainFileAST()) {2425 serialization::ModuleFile &2426 Mod = Reader->getModuleManager().getPrimaryModule();2427 for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {2428 if (!Fn(context, D))2429 return false;2430 }2431 2432 return true;2433 }2434 2435 for (ASTUnit::top_level_iterator TL = top_level_begin(),2436 TLEnd = top_level_end();2437 TL != TLEnd; ++TL) {2438 if (!Fn(context, *TL))2439 return false;2440 }2441 2442 return true;2443}2444 2445OptionalFileEntryRef ASTUnit::getPCHFile() {2446 if (!Reader)2447 return std::nullopt;2448 2449 serialization::ModuleFile *Mod = nullptr;2450 Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) {2451 switch (M.Kind) {2452 case serialization::MK_ImplicitModule:2453 case serialization::MK_ExplicitModule:2454 case serialization::MK_PrebuiltModule:2455 return true; // skip dependencies.2456 case serialization::MK_PCH:2457 Mod = &M;2458 return true; // found it.2459 case serialization::MK_Preamble:2460 return false; // look in dependencies.2461 case serialization::MK_MainFile:2462 return false; // look in dependencies.2463 }2464 2465 return true;2466 });2467 if (Mod)2468 return Mod->File;2469 2470 return std::nullopt;2471}2472 2473bool ASTUnit::isModuleFile() const {2474 return isMainFileAST() && getLangOpts().isCompilingModule();2475}2476 2477InputKind ASTUnit::getInputKind() const {2478 auto &LangOpts = getLangOpts();2479 2480 Language Lang;2481 if (LangOpts.OpenCL)2482 Lang = Language::OpenCL;2483 else if (LangOpts.CUDA)2484 Lang = Language::CUDA;2485 else if (LangOpts.CPlusPlus)2486 Lang = LangOpts.ObjC ? Language::ObjCXX : Language::CXX;2487 else2488 Lang = LangOpts.ObjC ? Language::ObjC : Language::C;2489 2490 InputKind::Format Fmt = InputKind::Source;2491 if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)2492 Fmt = InputKind::ModuleMap;2493 2494 // We don't know if input was preprocessed. Assume not.2495 bool PP = false;2496 2497 return InputKind(Lang, Fmt, PP);2498}2499 2500#ifndef NDEBUG2501ASTUnit::ConcurrencyState::ConcurrencyState() {2502 Mutex = new std::recursive_mutex;2503}2504 2505ASTUnit::ConcurrencyState::~ConcurrencyState() {2506 delete static_cast<std::recursive_mutex *>(Mutex);2507}2508 2509void ASTUnit::ConcurrencyState::start() {2510 bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock();2511 assert(acquired && "Concurrent access to ASTUnit!");2512}2513 2514void ASTUnit::ConcurrencyState::finish() {2515 static_cast<std::recursive_mutex *>(Mutex)->unlock();2516}2517 2518#else // NDEBUG2519 2520ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; }2521ASTUnit::ConcurrencyState::~ConcurrencyState() {}2522void ASTUnit::ConcurrencyState::start() {}2523void ASTUnit::ConcurrencyState::finish() {}2524 2525#endif // NDEBUG2526