10b57cec5SDimitry Andric //===- ASTUnit.cpp - ASTUnit utility --------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // ASTUnit Implementation. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Frontend/ASTUnit.h" 140b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h" 150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 160b57cec5SDimitry Andric #include "clang/AST/CommentCommandTraits.h" 170b57cec5SDimitry Andric #include "clang/AST/Decl.h" 180b57cec5SDimitry Andric #include "clang/AST/DeclBase.h" 190b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 200b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h" 210b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 220b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 230b57cec5SDimitry Andric #include "clang/AST/DeclarationName.h" 240b57cec5SDimitry Andric #include "clang/AST/ExternalASTSource.h" 250b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h" 260b57cec5SDimitry Andric #include "clang/AST/Type.h" 270b57cec5SDimitry Andric #include "clang/AST/TypeOrdering.h" 280b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 290b57cec5SDimitry Andric #include "clang/Basic/FileManager.h" 300b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 310b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 320b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 33a7dea167SDimitry Andric #include "clang/Basic/LangStandard.h" 340b57cec5SDimitry Andric #include "clang/Basic/Module.h" 350b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 360b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 370b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 380b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 390b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 400b57cec5SDimitry Andric #include "clang/Frontend/CompilerInvocation.h" 410b57cec5SDimitry Andric #include "clang/Frontend/FrontendAction.h" 420b57cec5SDimitry Andric #include "clang/Frontend/FrontendActions.h" 430b57cec5SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h" 440b57cec5SDimitry Andric #include "clang/Frontend/FrontendOptions.h" 450b57cec5SDimitry Andric #include "clang/Frontend/MultiplexConsumer.h" 460b57cec5SDimitry Andric #include "clang/Frontend/PrecompiledPreamble.h" 470b57cec5SDimitry Andric #include "clang/Frontend/Utils.h" 480b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h" 490b57cec5SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h" 500b57cec5SDimitry Andric #include "clang/Lex/Lexer.h" 510b57cec5SDimitry Andric #include "clang/Lex/PPCallbacks.h" 520b57cec5SDimitry Andric #include "clang/Lex/PreprocessingRecord.h" 530b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 540b57cec5SDimitry Andric #include "clang/Lex/PreprocessorOptions.h" 550b57cec5SDimitry Andric #include "clang/Lex/Token.h" 560b57cec5SDimitry Andric #include "clang/Sema/CodeCompleteConsumer.h" 570b57cec5SDimitry Andric #include "clang/Sema/CodeCompleteOptions.h" 580b57cec5SDimitry Andric #include "clang/Sema/Sema.h" 59*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h" 600b57cec5SDimitry Andric #include "clang/Serialization/ASTBitCodes.h" 610b57cec5SDimitry Andric #include "clang/Serialization/ASTReader.h" 620b57cec5SDimitry Andric #include "clang/Serialization/ASTWriter.h" 630b57cec5SDimitry Andric #include "clang/Serialization/ContinuousRangeMap.h" 640b57cec5SDimitry Andric #include "clang/Serialization/InMemoryModuleCache.h" 65480093f4SDimitry Andric #include "clang/Serialization/ModuleFile.h" 660b57cec5SDimitry Andric #include "clang/Serialization/PCHContainerOperations.h" 670b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 680b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 690b57cec5SDimitry Andric #include "llvm/ADT/IntrusiveRefCntPtr.h" 700b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 71e8d8bef9SDimitry Andric #include "llvm/ADT/ScopeExit.h" 720b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 730b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 740b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 750b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h" 760b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 770b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 780b57cec5SDimitry Andric #include "llvm/Bitstream/BitstreamWriter.h" 790b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 800b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 810b57cec5SDimitry Andric #include "llvm/Support/CrashRecoveryContext.h" 820b57cec5SDimitry Andric #include "llvm/Support/DJB.h" 830b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 840b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 850b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 860b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 87bdd1243dSDimitry Andric #include "llvm/Support/SaveAndRestore.h" 880b57cec5SDimitry Andric #include "llvm/Support/Timer.h" 890b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 900b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 910b57cec5SDimitry Andric #include <algorithm> 920b57cec5SDimitry Andric #include <atomic> 930b57cec5SDimitry Andric #include <cassert> 940b57cec5SDimitry Andric #include <cstdint> 950b57cec5SDimitry Andric #include <cstdio> 960b57cec5SDimitry Andric #include <cstdlib> 970b57cec5SDimitry Andric #include <memory> 98a7dea167SDimitry Andric #include <mutex> 99bdd1243dSDimitry Andric #include <optional> 1000b57cec5SDimitry Andric #include <string> 1010b57cec5SDimitry Andric #include <tuple> 1020b57cec5SDimitry Andric #include <utility> 1030b57cec5SDimitry Andric #include <vector> 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric using namespace clang; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric using llvm::TimeRecord; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric namespace { 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric class SimpleTimer { 1120b57cec5SDimitry Andric bool WantTiming; 1130b57cec5SDimitry Andric TimeRecord Start; 1140b57cec5SDimitry Andric std::string Output; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric public: 1170b57cec5SDimitry Andric explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) { 1180b57cec5SDimitry Andric if (WantTiming) 1190b57cec5SDimitry Andric Start = TimeRecord::getCurrentTime(); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric ~SimpleTimer() { 1230b57cec5SDimitry Andric if (WantTiming) { 1240b57cec5SDimitry Andric TimeRecord Elapsed = TimeRecord::getCurrentTime(); 1250b57cec5SDimitry Andric Elapsed -= Start; 1260b57cec5SDimitry Andric llvm::errs() << Output << ':'; 1270b57cec5SDimitry Andric Elapsed.print(Elapsed, llvm::errs()); 1280b57cec5SDimitry Andric llvm::errs() << '\n'; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric void setOutput(const Twine &Output) { 1330b57cec5SDimitry Andric if (WantTiming) 1340b57cec5SDimitry Andric this->Output = Output.str(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric }; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric } // namespace 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric template <class T> 1410b57cec5SDimitry Andric static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) { 1420b57cec5SDimitry Andric if (!Val) 1430b57cec5SDimitry Andric return nullptr; 1440b57cec5SDimitry Andric return std::move(*Val); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric template <class T> 1480b57cec5SDimitry Andric static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { 1490b57cec5SDimitry Andric if (!Val) 1500b57cec5SDimitry Andric return false; 1510b57cec5SDimitry Andric Output = std::move(*Val); 1520b57cec5SDimitry Andric return true; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// Get a source buffer for \p MainFilePath, handling all file-to-file 1560b57cec5SDimitry Andric /// and file-to-buffer remappings inside \p Invocation. 1570b57cec5SDimitry Andric static std::unique_ptr<llvm::MemoryBuffer> 1580b57cec5SDimitry Andric getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, 1590b57cec5SDimitry Andric llvm::vfs::FileSystem *VFS, 1600b57cec5SDimitry Andric StringRef FilePath, bool isVolatile) { 1610b57cec5SDimitry Andric const auto &PreprocessorOpts = Invocation.getPreprocessorOpts(); 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric // Try to determine if the main file has been remapped, either from the 1640b57cec5SDimitry Andric // command line (to another file) or directly through the compiler 1650b57cec5SDimitry Andric // invocation (to a memory buffer). 1660b57cec5SDimitry Andric llvm::MemoryBuffer *Buffer = nullptr; 1670b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> BufferOwner; 1680b57cec5SDimitry Andric auto FileStatus = VFS->status(FilePath); 1690b57cec5SDimitry Andric if (FileStatus) { 1700b57cec5SDimitry Andric llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID(); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Check whether there is a file-file remapping of the main file 1730b57cec5SDimitry Andric for (const auto &RF : PreprocessorOpts.RemappedFiles) { 1740b57cec5SDimitry Andric std::string MPath(RF.first); 1750b57cec5SDimitry Andric auto MPathStatus = VFS->status(MPath); 1760b57cec5SDimitry Andric if (MPathStatus) { 1770b57cec5SDimitry Andric llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); 1780b57cec5SDimitry Andric if (MainFileID == MID) { 1790b57cec5SDimitry Andric // We found a remapping. Try to load the resulting, remapped source. 1800b57cec5SDimitry Andric BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile)); 1810b57cec5SDimitry Andric if (!BufferOwner) 1820b57cec5SDimitry Andric return nullptr; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // Check whether there is a file-buffer remapping. It supercedes the 1880b57cec5SDimitry Andric // file-file remapping. 1890b57cec5SDimitry Andric for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) { 1900b57cec5SDimitry Andric std::string MPath(RB.first); 1910b57cec5SDimitry Andric auto MPathStatus = VFS->status(MPath); 1920b57cec5SDimitry Andric if (MPathStatus) { 1930b57cec5SDimitry Andric llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); 1940b57cec5SDimitry Andric if (MainFileID == MID) { 1950b57cec5SDimitry Andric // We found a remapping. 1960b57cec5SDimitry Andric BufferOwner.reset(); 1970b57cec5SDimitry Andric Buffer = const_cast<llvm::MemoryBuffer *>(RB.second); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric // If the main source file was not remapped, load it now. 2040b57cec5SDimitry Andric if (!Buffer && !BufferOwner) { 2050b57cec5SDimitry Andric BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile)); 2060b57cec5SDimitry Andric if (!BufferOwner) 2070b57cec5SDimitry Andric return nullptr; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric if (BufferOwner) 2110b57cec5SDimitry Andric return BufferOwner; 2120b57cec5SDimitry Andric if (!Buffer) 2130b57cec5SDimitry Andric return nullptr; 2140b57cec5SDimitry Andric return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric struct ASTUnit::ASTWriterData { 2180b57cec5SDimitry Andric SmallString<128> Buffer; 2190b57cec5SDimitry Andric llvm::BitstreamWriter Stream; 2200b57cec5SDimitry Andric ASTWriter Writer; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric ASTWriterData(InMemoryModuleCache &ModuleCache) 2230b57cec5SDimitry Andric : Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {} 2240b57cec5SDimitry Andric }; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void ASTUnit::clearFileLevelDecls() { 2275ffd83dbSDimitry Andric FileDecls.clear(); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric /// After failing to build a precompiled preamble (due to 2310b57cec5SDimitry Andric /// errors in the source that occurs in the preamble), the number of 2320b57cec5SDimitry Andric /// reparses during which we'll skip even trying to precompile the 2330b57cec5SDimitry Andric /// preamble. 2340b57cec5SDimitry Andric const unsigned DefaultPreambleRebuildInterval = 5; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric /// Tracks the number of ASTUnit objects that are currently active. 2370b57cec5SDimitry Andric /// 2380b57cec5SDimitry Andric /// Used for debugging purposes only. 2390b57cec5SDimitry Andric static std::atomic<unsigned> ActiveASTUnitObjects; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric ASTUnit::ASTUnit(bool _MainFileIsAST) 2420b57cec5SDimitry Andric : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")), 2430b57cec5SDimitry Andric ShouldCacheCodeCompletionResults(false), 2440b57cec5SDimitry Andric IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false), 2450b57cec5SDimitry Andric UnsafeToFree(false) { 2460b57cec5SDimitry Andric if (getenv("LIBCLANG_OBJTRACKING")) 2470b57cec5SDimitry Andric fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric ASTUnit::~ASTUnit() { 2510b57cec5SDimitry Andric // If we loaded from an AST file, balance out the BeginSourceFile call. 2520b57cec5SDimitry Andric if (MainFileIsAST && getDiagnostics().getClient()) { 2530b57cec5SDimitry Andric getDiagnostics().getClient()->EndSourceFile(); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric clearFileLevelDecls(); 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric // Free the buffers associated with remapped files. We are required to 2590b57cec5SDimitry Andric // perform this operation here because we explicitly request that the 2600b57cec5SDimitry Andric // compiler instance *not* free these buffers for each invocation of the 2610b57cec5SDimitry Andric // parser. 2620b57cec5SDimitry Andric if (Invocation && OwnsRemappedFileBuffers) { 2630b57cec5SDimitry Andric PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); 2640b57cec5SDimitry Andric for (const auto &RB : PPOpts.RemappedFileBuffers) 2650b57cec5SDimitry Andric delete RB.second; 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric ClearCachedCompletionResults(); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric if (getenv("LIBCLANG_OBJTRACKING")) 2710b57cec5SDimitry Andric fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) { 2750b57cec5SDimitry Andric this->PP = std::move(PP); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric void ASTUnit::enableSourceFileDiagnostics() { 2790b57cec5SDimitry Andric assert(getDiagnostics().getClient() && Ctx && 2800b57cec5SDimitry Andric "Bad context for source file"); 2810b57cec5SDimitry Andric getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get()); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric /// Determine the set of code-completion contexts in which this 2850b57cec5SDimitry Andric /// declaration should be shown. 2860b57cec5SDimitry Andric static uint64_t getDeclShowContexts(const NamedDecl *ND, 2870b57cec5SDimitry Andric const LangOptions &LangOpts, 2880b57cec5SDimitry Andric bool &IsNestedNameSpecifier) { 2890b57cec5SDimitry Andric IsNestedNameSpecifier = false; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric if (isa<UsingShadowDecl>(ND)) 2920b57cec5SDimitry Andric ND = ND->getUnderlyingDecl(); 2930b57cec5SDimitry Andric if (!ND) 2940b57cec5SDimitry Andric return 0; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric uint64_t Contexts = 0; 2970b57cec5SDimitry Andric if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || 2980b57cec5SDimitry Andric isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) || 2990b57cec5SDimitry Andric isa<TypeAliasTemplateDecl>(ND)) { 3000b57cec5SDimitry Andric // Types can appear in these contexts. 3010b57cec5SDimitry Andric if (LangOpts.CPlusPlus || !isa<TagDecl>(ND)) 3020b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel) 3030b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCIvarList) 3040b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ClassStructUnion) 3050b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Statement) 3060b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Type) 3070b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric // In C++, types can appear in expressions contexts (for functional casts). 3100b57cec5SDimitry Andric if (LangOpts.CPlusPlus) 3110b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_Expression); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // In Objective-C, message sends can send interfaces. In Objective-C++, 3140b57cec5SDimitry Andric // all types are available due to functional casts. 3150b57cec5SDimitry Andric if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) 3160b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric // In Objective-C, you can only be a subclass of another Objective-C class 3190b57cec5SDimitry Andric if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { 3200b57cec5SDimitry Andric // Objective-C interfaces can be used in a class property expression. 3210b57cec5SDimitry Andric if (ID->getDefinition()) 3220b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_Expression); 3230b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName); 32406c3fb27SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric // Deal with tag names. 3280b57cec5SDimitry Andric if (isa<EnumDecl>(ND)) { 3290b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag); 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric // Part of the nested-name-specifier in C++0x. 3320b57cec5SDimitry Andric if (LangOpts.CPlusPlus11) 3330b57cec5SDimitry Andric IsNestedNameSpecifier = true; 3340b57cec5SDimitry Andric } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) { 3350b57cec5SDimitry Andric if (Record->isUnion()) 3360b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag); 3370b57cec5SDimitry Andric else 3380b57cec5SDimitry Andric Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric if (LangOpts.CPlusPlus) 3410b57cec5SDimitry Andric IsNestedNameSpecifier = true; 3420b57cec5SDimitry Andric } else if (isa<ClassTemplateDecl>(ND)) 3430b57cec5SDimitry Andric IsNestedNameSpecifier = true; 3440b57cec5SDimitry Andric } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { 3450b57cec5SDimitry Andric // Values can appear in these contexts. 3460b57cec5SDimitry Andric Contexts = (1LL << CodeCompletionContext::CCC_Statement) 3470b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Expression) 3480b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression) 3490b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); 3500b57cec5SDimitry Andric } else if (isa<ObjCProtocolDecl>(ND)) { 3510b57cec5SDimitry Andric Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName); 3520b57cec5SDimitry Andric } else if (isa<ObjCCategoryDecl>(ND)) { 3530b57cec5SDimitry Andric Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName); 3540b57cec5SDimitry Andric } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { 3550b57cec5SDimitry Andric Contexts = (1LL << CodeCompletionContext::CCC_Namespace); 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric // Part of the nested-name-specifier. 3580b57cec5SDimitry Andric IsNestedNameSpecifier = true; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric return Contexts; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric void ASTUnit::CacheCodeCompletionResults() { 3650b57cec5SDimitry Andric if (!TheSema) 3660b57cec5SDimitry Andric return; 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric SimpleTimer Timer(WantTiming); 3690b57cec5SDimitry Andric Timer.setOutput("Cache global code completions for " + getMainFileName()); 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric // Clear out the previous results. 3720b57cec5SDimitry Andric ClearCachedCompletionResults(); 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric // Gather the set of global code completions. 3750b57cec5SDimitry Andric using Result = CodeCompletionResult; 3760b57cec5SDimitry Andric SmallVector<Result, 8> Results; 3770b57cec5SDimitry Andric CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>(); 3780b57cec5SDimitry Andric CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator); 379*0fca6ea1SDimitry Andric TheSema->CodeCompletion().GatherGlobalCodeCompletions( 380*0fca6ea1SDimitry Andric *CachedCompletionAllocator, CCTUInfo, Results); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric // Translate global code completions into cached completions. 3830b57cec5SDimitry Andric llvm::DenseMap<CanQualType, unsigned> CompletionTypes; 3840b57cec5SDimitry Andric CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel); 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric for (auto &R : Results) { 3870b57cec5SDimitry Andric switch (R.Kind) { 3880b57cec5SDimitry Andric case Result::RK_Declaration: { 3890b57cec5SDimitry Andric bool IsNestedNameSpecifier = false; 3900b57cec5SDimitry Andric CachedCodeCompletionResult CachedResult; 3910b57cec5SDimitry Andric CachedResult.Completion = R.CreateCodeCompletionString( 3920b57cec5SDimitry Andric *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo, 3930b57cec5SDimitry Andric IncludeBriefCommentsInCodeCompletion); 3940b57cec5SDimitry Andric CachedResult.ShowInContexts = getDeclShowContexts( 3950b57cec5SDimitry Andric R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier); 3960b57cec5SDimitry Andric CachedResult.Priority = R.Priority; 3970b57cec5SDimitry Andric CachedResult.Kind = R.CursorKind; 3980b57cec5SDimitry Andric CachedResult.Availability = R.Availability; 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric // Keep track of the type of this completion in an ASTContext-agnostic 4010b57cec5SDimitry Andric // way. 4020b57cec5SDimitry Andric QualType UsageType = getDeclUsageType(*Ctx, R.Declaration); 4030b57cec5SDimitry Andric if (UsageType.isNull()) { 4040b57cec5SDimitry Andric CachedResult.TypeClass = STC_Void; 4050b57cec5SDimitry Andric CachedResult.Type = 0; 4060b57cec5SDimitry Andric } else { 4070b57cec5SDimitry Andric CanQualType CanUsageType 4080b57cec5SDimitry Andric = Ctx->getCanonicalType(UsageType.getUnqualifiedType()); 4090b57cec5SDimitry Andric CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType); 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric // Determine whether we have already seen this type. If so, we save 4120b57cec5SDimitry Andric // ourselves the work of formatting the type string by using the 4130b57cec5SDimitry Andric // temporary, CanQualType-based hash table to find the associated value. 4140b57cec5SDimitry Andric unsigned &TypeValue = CompletionTypes[CanUsageType]; 4150b57cec5SDimitry Andric if (TypeValue == 0) { 4160b57cec5SDimitry Andric TypeValue = CompletionTypes.size(); 4170b57cec5SDimitry Andric CachedCompletionTypes[QualType(CanUsageType).getAsString()] 4180b57cec5SDimitry Andric = TypeValue; 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric CachedResult.Type = TypeValue; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric CachedCompletionResults.push_back(CachedResult); 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric /// Handle nested-name-specifiers in C++. 4270b57cec5SDimitry Andric if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier && 4280b57cec5SDimitry Andric !R.StartsNestedNameSpecifier) { 4290b57cec5SDimitry Andric // The contexts in which a nested-name-specifier can appear in C++. 4300b57cec5SDimitry Andric uint64_t NNSContexts 4310b57cec5SDimitry Andric = (1LL << CodeCompletionContext::CCC_TopLevel) 4320b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCIvarList) 4330b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ClassStructUnion) 4340b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Statement) 4350b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Expression) 4360b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver) 4370b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_EnumTag) 4380b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_UnionTag) 4390b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ClassOrStructTag) 4400b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Type) 4410b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_SymbolOrNewName) 4420b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression); 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric if (isa<NamespaceDecl>(R.Declaration) || 4450b57cec5SDimitry Andric isa<NamespaceAliasDecl>(R.Declaration)) 4460b57cec5SDimitry Andric NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (uint64_t RemainingContexts 4490b57cec5SDimitry Andric = NNSContexts & ~CachedResult.ShowInContexts) { 4500b57cec5SDimitry Andric // If there any contexts where this completion can be a 4510b57cec5SDimitry Andric // nested-name-specifier but isn't already an option, create a 4520b57cec5SDimitry Andric // nested-name-specifier completion. 4530b57cec5SDimitry Andric R.StartsNestedNameSpecifier = true; 4540b57cec5SDimitry Andric CachedResult.Completion = R.CreateCodeCompletionString( 4550b57cec5SDimitry Andric *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo, 4560b57cec5SDimitry Andric IncludeBriefCommentsInCodeCompletion); 4570b57cec5SDimitry Andric CachedResult.ShowInContexts = RemainingContexts; 4580b57cec5SDimitry Andric CachedResult.Priority = CCP_NestedNameSpecifier; 4590b57cec5SDimitry Andric CachedResult.TypeClass = STC_Void; 4600b57cec5SDimitry Andric CachedResult.Type = 0; 4610b57cec5SDimitry Andric CachedCompletionResults.push_back(CachedResult); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric break; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric case Result::RK_Keyword: 4680b57cec5SDimitry Andric case Result::RK_Pattern: 4690b57cec5SDimitry Andric // Ignore keywords and patterns; we don't care, since they are so 4700b57cec5SDimitry Andric // easily regenerated. 4710b57cec5SDimitry Andric break; 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric case Result::RK_Macro: { 4740b57cec5SDimitry Andric CachedCodeCompletionResult CachedResult; 4750b57cec5SDimitry Andric CachedResult.Completion = R.CreateCodeCompletionString( 4760b57cec5SDimitry Andric *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo, 4770b57cec5SDimitry Andric IncludeBriefCommentsInCodeCompletion); 4780b57cec5SDimitry Andric CachedResult.ShowInContexts 4790b57cec5SDimitry Andric = (1LL << CodeCompletionContext::CCC_TopLevel) 4800b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCInterface) 4810b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCImplementation) 4820b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCIvarList) 4830b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ClassStructUnion) 4840b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Statement) 4850b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Expression) 4860b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver) 4870b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_MacroNameUse) 4880b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_PreprocessorExpression) 4890b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression) 4900b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_OtherWithMacros); 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric CachedResult.Priority = R.Priority; 4930b57cec5SDimitry Andric CachedResult.Kind = R.CursorKind; 4940b57cec5SDimitry Andric CachedResult.Availability = R.Availability; 4950b57cec5SDimitry Andric CachedResult.TypeClass = STC_Void; 4960b57cec5SDimitry Andric CachedResult.Type = 0; 4970b57cec5SDimitry Andric CachedCompletionResults.push_back(CachedResult); 4980b57cec5SDimitry Andric break; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric // Save the current top-level hash value. 5040b57cec5SDimitry Andric CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric void ASTUnit::ClearCachedCompletionResults() { 5080b57cec5SDimitry Andric CachedCompletionResults.clear(); 5090b57cec5SDimitry Andric CachedCompletionTypes.clear(); 5100b57cec5SDimitry Andric CachedCompletionAllocator = nullptr; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric namespace { 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric /// Gathers information from ASTReader that will be used to initialize 5160b57cec5SDimitry Andric /// a Preprocessor. 5170b57cec5SDimitry Andric class ASTInfoCollector : public ASTReaderListener { 5180b57cec5SDimitry Andric Preprocessor &PP; 5190b57cec5SDimitry Andric ASTContext *Context; 5200b57cec5SDimitry Andric HeaderSearchOptions &HSOpts; 5210b57cec5SDimitry Andric PreprocessorOptions &PPOpts; 5220b57cec5SDimitry Andric LangOptions &LangOpt; 5230b57cec5SDimitry Andric std::shared_ptr<TargetOptions> &TargetOpts; 5240b57cec5SDimitry Andric IntrusiveRefCntPtr<TargetInfo> &Target; 5250b57cec5SDimitry Andric unsigned &Counter; 5260b57cec5SDimitry Andric bool InitializedLanguage = false; 527bdd1243dSDimitry Andric bool InitializedHeaderSearchPaths = false; 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric public: 5300b57cec5SDimitry Andric ASTInfoCollector(Preprocessor &PP, ASTContext *Context, 5310b57cec5SDimitry Andric HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, 5320b57cec5SDimitry Andric LangOptions &LangOpt, 5330b57cec5SDimitry Andric std::shared_ptr<TargetOptions> &TargetOpts, 5340b57cec5SDimitry Andric IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter) 5350b57cec5SDimitry Andric : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), 5360b57cec5SDimitry Andric LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target), 5370b57cec5SDimitry Andric Counter(Counter) {} 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, 5400b57cec5SDimitry Andric bool AllowCompatibleDifferences) override { 5410b57cec5SDimitry Andric if (InitializedLanguage) 5420b57cec5SDimitry Andric return false; 5430b57cec5SDimitry Andric 544*0fca6ea1SDimitry Andric // FIXME: We did similar things in ReadHeaderSearchOptions too. But such 545*0fca6ea1SDimitry Andric // style is not scaling. Probably we need to invite some mechanism to 546*0fca6ea1SDimitry Andric // handle such patterns generally. 547*0fca6ea1SDimitry Andric auto PICLevel = LangOpt.PICLevel; 548*0fca6ea1SDimitry Andric auto PIE = LangOpt.PIE; 549*0fca6ea1SDimitry Andric 5500b57cec5SDimitry Andric LangOpt = LangOpts; 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric LangOpt.PICLevel = PICLevel; 553*0fca6ea1SDimitry Andric LangOpt.PIE = PIE; 554*0fca6ea1SDimitry Andric 5550b57cec5SDimitry Andric InitializedLanguage = true; 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric updated(); 5580b57cec5SDimitry Andric return false; 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, 5620b57cec5SDimitry Andric StringRef SpecificModuleCachePath, 5630b57cec5SDimitry Andric bool Complain) override { 5645f757f3fSDimitry Andric // llvm::SaveAndRestore doesn't support bit field. 5655f757f3fSDimitry Andric auto ForceCheckCXX20ModulesInputFiles = 5665f757f3fSDimitry Andric this->HSOpts.ForceCheckCXX20ModulesInputFiles; 567bdd1243dSDimitry Andric llvm::SaveAndRestore X(this->HSOpts.UserEntries); 568bdd1243dSDimitry Andric llvm::SaveAndRestore Y(this->HSOpts.SystemHeaderPrefixes); 569bdd1243dSDimitry Andric llvm::SaveAndRestore Z(this->HSOpts.VFSOverlayFiles); 570bdd1243dSDimitry Andric 5710b57cec5SDimitry Andric this->HSOpts = HSOpts; 5725f757f3fSDimitry Andric this->HSOpts.ForceCheckCXX20ModulesInputFiles = 5735f757f3fSDimitry Andric ForceCheckCXX20ModulesInputFiles; 574bdd1243dSDimitry Andric 575bdd1243dSDimitry Andric return false; 576bdd1243dSDimitry Andric } 577bdd1243dSDimitry Andric 578bdd1243dSDimitry Andric bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts, 579bdd1243dSDimitry Andric bool Complain) override { 580bdd1243dSDimitry Andric if (InitializedHeaderSearchPaths) 581bdd1243dSDimitry Andric return false; 582bdd1243dSDimitry Andric 583bdd1243dSDimitry Andric this->HSOpts.UserEntries = HSOpts.UserEntries; 584bdd1243dSDimitry Andric this->HSOpts.SystemHeaderPrefixes = HSOpts.SystemHeaderPrefixes; 585bdd1243dSDimitry Andric this->HSOpts.VFSOverlayFiles = HSOpts.VFSOverlayFiles; 586bdd1243dSDimitry Andric 587bdd1243dSDimitry Andric // Initialize the FileManager. We can't do this in update(), since that 588bdd1243dSDimitry Andric // performs the initialization too late (once both target and language 589bdd1243dSDimitry Andric // options are read). 590bdd1243dSDimitry Andric PP.getFileManager().setVirtualFileSystem(createVFSFromOverlayFiles( 591bdd1243dSDimitry Andric HSOpts.VFSOverlayFiles, PP.getDiagnostics(), 592bdd1243dSDimitry Andric PP.getFileManager().getVirtualFileSystemPtr())); 593bdd1243dSDimitry Andric 594bdd1243dSDimitry Andric InitializedHeaderSearchPaths = true; 595bdd1243dSDimitry Andric 5960b57cec5SDimitry Andric return false; 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5995f757f3fSDimitry Andric bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, 6005f757f3fSDimitry Andric bool ReadMacros, bool Complain, 6010b57cec5SDimitry Andric std::string &SuggestedPredefines) override { 6020b57cec5SDimitry Andric this->PPOpts = PPOpts; 6030b57cec5SDimitry Andric return false; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, 6070b57cec5SDimitry Andric bool AllowCompatibleDifferences) override { 6080b57cec5SDimitry Andric // If we've already initialized the target, don't do it again. 6090b57cec5SDimitry Andric if (Target) 6100b57cec5SDimitry Andric return false; 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts); 6130b57cec5SDimitry Andric Target = 6140b57cec5SDimitry Andric TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts); 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric updated(); 6170b57cec5SDimitry Andric return false; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric void ReadCounter(const serialization::ModuleFile &M, 6210b57cec5SDimitry Andric unsigned Value) override { 6220b57cec5SDimitry Andric Counter = Value; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric private: 6260b57cec5SDimitry Andric void updated() { 6270b57cec5SDimitry Andric if (!Target || !InitializedLanguage) 6280b57cec5SDimitry Andric return; 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric // Inform the target of the language options. 6310b57cec5SDimitry Andric // 6320b57cec5SDimitry Andric // FIXME: We shouldn't need to do this, the target should be immutable once 6330b57cec5SDimitry Andric // created. This complexity should be lifted elsewhere. 634fe6060f1SDimitry Andric Target->adjust(PP.getDiagnostics(), LangOpt); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric // Initialize the preprocessor. 6370b57cec5SDimitry Andric PP.Initialize(*Target); 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric if (!Context) 6400b57cec5SDimitry Andric return; 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric // Initialize the ASTContext 6430b57cec5SDimitry Andric Context->InitBuiltinTypes(*Target); 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric // Adjust printing policy based on language options. 6460b57cec5SDimitry Andric Context->setPrintingPolicy(PrintingPolicy(LangOpt)); 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric // We didn't have access to the comment options when the ASTContext was 6490b57cec5SDimitry Andric // constructed, so register them now. 6500b57cec5SDimitry Andric Context->getCommentCommandTraits().registerCommentOptions( 6510b57cec5SDimitry Andric LangOpt.CommentOpts); 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric }; 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric /// Diagnostic consumer that saves each diagnostic it is given. 6560b57cec5SDimitry Andric class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer { 6570b57cec5SDimitry Andric SmallVectorImpl<StoredDiagnostic> *StoredDiags; 6580b57cec5SDimitry Andric SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags; 6590b57cec5SDimitry Andric bool CaptureNonErrorsFromIncludes = true; 6600b57cec5SDimitry Andric const LangOptions *LangOpts = nullptr; 6610b57cec5SDimitry Andric SourceManager *SourceMgr = nullptr; 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric public: 6640b57cec5SDimitry Andric FilterAndStoreDiagnosticConsumer( 6650b57cec5SDimitry Andric SmallVectorImpl<StoredDiagnostic> *StoredDiags, 6660b57cec5SDimitry Andric SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags, 6670b57cec5SDimitry Andric bool CaptureNonErrorsFromIncludes) 6680b57cec5SDimitry Andric : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags), 6690b57cec5SDimitry Andric CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) { 6700b57cec5SDimitry Andric assert((StoredDiags || StandaloneDiags) && 6710b57cec5SDimitry Andric "No output collections were passed to StoredDiagnosticConsumer."); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric void BeginSourceFile(const LangOptions &LangOpts, 6750b57cec5SDimitry Andric const Preprocessor *PP = nullptr) override { 6760b57cec5SDimitry Andric this->LangOpts = &LangOpts; 6770b57cec5SDimitry Andric if (PP) 6780b57cec5SDimitry Andric SourceMgr = &PP->getSourceManager(); 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric void HandleDiagnostic(DiagnosticsEngine::Level Level, 6820b57cec5SDimitry Andric const Diagnostic &Info) override; 6830b57cec5SDimitry Andric }; 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric /// RAII object that optionally captures and filters diagnostics, if 6860b57cec5SDimitry Andric /// there is no diagnostic client to capture them already. 6870b57cec5SDimitry Andric class CaptureDroppedDiagnostics { 6880b57cec5SDimitry Andric DiagnosticsEngine &Diags; 6890b57cec5SDimitry Andric FilterAndStoreDiagnosticConsumer Client; 6900b57cec5SDimitry Andric DiagnosticConsumer *PreviousClient = nullptr; 6910b57cec5SDimitry Andric std::unique_ptr<DiagnosticConsumer> OwningPreviousClient; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric public: 6940b57cec5SDimitry Andric CaptureDroppedDiagnostics( 6950b57cec5SDimitry Andric CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags, 6960b57cec5SDimitry Andric SmallVectorImpl<StoredDiagnostic> *StoredDiags, 6970b57cec5SDimitry Andric SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) 6980b57cec5SDimitry Andric : Diags(Diags), 6990b57cec5SDimitry Andric Client(StoredDiags, StandaloneDiags, 7000b57cec5SDimitry Andric CaptureDiagnostics != 7010b57cec5SDimitry Andric CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) { 7020b57cec5SDimitry Andric if (CaptureDiagnostics != CaptureDiagsKind::None || 7030b57cec5SDimitry Andric Diags.getClient() == nullptr) { 7040b57cec5SDimitry Andric OwningPreviousClient = Diags.takeClient(); 7050b57cec5SDimitry Andric PreviousClient = Diags.getClient(); 7060b57cec5SDimitry Andric Diags.setClient(&Client, false); 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric ~CaptureDroppedDiagnostics() { 7110b57cec5SDimitry Andric if (Diags.getClient() == &Client) 7120b57cec5SDimitry Andric Diags.setClient(PreviousClient, !!OwningPreviousClient.release()); 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric }; 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric } // namespace 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric static ASTUnit::StandaloneDiagnostic 7190b57cec5SDimitry Andric makeStandaloneDiagnostic(const LangOptions &LangOpts, 7200b57cec5SDimitry Andric const StoredDiagnostic &InDiag); 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric static bool isInMainFile(const clang::Diagnostic &D) { 7230b57cec5SDimitry Andric if (!D.hasSourceManager() || !D.getLocation().isValid()) 7240b57cec5SDimitry Andric return false; 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric auto &M = D.getSourceManager(); 7270b57cec5SDimitry Andric return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation())); 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric void FilterAndStoreDiagnosticConsumer::HandleDiagnostic( 7310b57cec5SDimitry Andric DiagnosticsEngine::Level Level, const Diagnostic &Info) { 7320b57cec5SDimitry Andric // Default implementation (Warnings/errors count). 7330b57cec5SDimitry Andric DiagnosticConsumer::HandleDiagnostic(Level, Info); 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric // Only record the diagnostic if it's part of the source manager we know 7360b57cec5SDimitry Andric // about. This effectively drops diagnostics from modules we're building. 7370b57cec5SDimitry Andric // FIXME: In the long run, ee don't want to drop source managers from modules. 7380b57cec5SDimitry Andric if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) { 7390b57cec5SDimitry Andric if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning && 7400b57cec5SDimitry Andric !isInMainFile(Info)) { 7410b57cec5SDimitry Andric return; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric StoredDiagnostic *ResultDiag = nullptr; 7450b57cec5SDimitry Andric if (StoredDiags) { 7460b57cec5SDimitry Andric StoredDiags->emplace_back(Level, Info); 7470b57cec5SDimitry Andric ResultDiag = &StoredDiags->back(); 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric if (StandaloneDiags) { 751bdd1243dSDimitry Andric std::optional<StoredDiagnostic> StoredDiag; 7520b57cec5SDimitry Andric if (!ResultDiag) { 7530b57cec5SDimitry Andric StoredDiag.emplace(Level, Info); 754bdd1243dSDimitry Andric ResultDiag = &*StoredDiag; 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric StandaloneDiags->push_back( 7570b57cec5SDimitry Andric makeStandaloneDiagnostic(*LangOpts, *ResultDiag)); 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric } 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const { 7630b57cec5SDimitry Andric return Reader; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric ASTMutationListener *ASTUnit::getASTMutationListener() { 7670b57cec5SDimitry Andric if (WriterData) 7680b57cec5SDimitry Andric return &WriterData->Writer; 7690b57cec5SDimitry Andric return nullptr; 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric ASTDeserializationListener *ASTUnit::getDeserializationListener() { 7730b57cec5SDimitry Andric if (WriterData) 7740b57cec5SDimitry Andric return &WriterData->Writer; 7750b57cec5SDimitry Andric return nullptr; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> 7790b57cec5SDimitry Andric ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { 7800b57cec5SDimitry Andric assert(FileMgr); 7810b57cec5SDimitry Andric auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile); 7820b57cec5SDimitry Andric if (Buffer) 7830b57cec5SDimitry Andric return std::move(*Buffer); 7840b57cec5SDimitry Andric if (ErrorStr) 7850b57cec5SDimitry Andric *ErrorStr = Buffer.getError().message(); 7860b57cec5SDimitry Andric return nullptr; 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric /// Configure the diagnostics object for use with ASTUnit. 7900b57cec5SDimitry Andric void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, 7910b57cec5SDimitry Andric ASTUnit &AST, 7920b57cec5SDimitry Andric CaptureDiagsKind CaptureDiagnostics) { 7930b57cec5SDimitry Andric assert(Diags.get() && "no DiagnosticsEngine was provided"); 7940b57cec5SDimitry Andric if (CaptureDiagnostics != CaptureDiagsKind::None) 7950b57cec5SDimitry Andric Diags->setClient(new FilterAndStoreDiagnosticConsumer( 7960b57cec5SDimitry Andric &AST.StoredDiagnostics, nullptr, 7970b57cec5SDimitry Andric CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes)); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( 8010b57cec5SDimitry Andric const std::string &Filename, const PCHContainerReader &PCHContainerRdr, 8020b57cec5SDimitry Andric WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, 80306c3fb27SDimitry Andric const FileSystemOptions &FileSystemOpts, 804*0fca6ea1SDimitry Andric std::shared_ptr<HeaderSearchOptions> HSOpts, 805*0fca6ea1SDimitry Andric std::shared_ptr<LangOptions> LangOpts, bool OnlyLocalDecls, 8065f757f3fSDimitry Andric CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors, 8075f757f3fSDimitry Andric bool UserFilesAreVolatile, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { 8080b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST(new ASTUnit(true)); 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 8110b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> 8120b57cec5SDimitry Andric ASTUnitCleanup(AST.get()); 8130b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 8140b57cec5SDimitry Andric llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> 8150b57cec5SDimitry Andric DiagCleanup(Diags.get()); 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric ConfigureDiags(Diags, *AST, CaptureDiagnostics); 8180b57cec5SDimitry Andric 819*0fca6ea1SDimitry Andric AST->LangOpts = LangOpts ? LangOpts : std::make_shared<LangOptions>(); 8200b57cec5SDimitry Andric AST->OnlyLocalDecls = OnlyLocalDecls; 8210b57cec5SDimitry Andric AST->CaptureDiagnostics = CaptureDiagnostics; 8220b57cec5SDimitry Andric AST->Diagnostics = Diags; 8230b57cec5SDimitry Andric AST->FileMgr = new FileManager(FileSystemOpts, VFS); 8240b57cec5SDimitry Andric AST->UserFilesAreVolatile = UserFilesAreVolatile; 8250b57cec5SDimitry Andric AST->SourceMgr = new SourceManager(AST->getDiagnostics(), 8260b57cec5SDimitry Andric AST->getFileManager(), 8270b57cec5SDimitry Andric UserFilesAreVolatile); 8280b57cec5SDimitry Andric AST->ModuleCache = new InMemoryModuleCache; 82906c3fb27SDimitry Andric AST->HSOpts = HSOpts ? HSOpts : std::make_shared<HeaderSearchOptions>(); 83006c3fb27SDimitry Andric AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front()); 8310b57cec5SDimitry Andric AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, 8320b57cec5SDimitry Andric AST->getSourceManager(), 8330b57cec5SDimitry Andric AST->getDiagnostics(), 8340b57cec5SDimitry Andric AST->getLangOpts(), 8350b57cec5SDimitry Andric /*Target=*/nullptr)); 8360b57cec5SDimitry Andric AST->PPOpts = std::make_shared<PreprocessorOptions>(); 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric // Gather Info for preprocessor construction later on. 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric HeaderSearch &HeaderInfo = *AST->HeaderInfo; 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric AST->PP = std::make_shared<Preprocessor>( 8430b57cec5SDimitry Andric AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts, 8440b57cec5SDimitry Andric AST->getSourceManager(), HeaderInfo, AST->ModuleLoader, 8450b57cec5SDimitry Andric /*IILookup=*/nullptr, 8460b57cec5SDimitry Andric /*OwnsHeaderSearch=*/false); 8470b57cec5SDimitry Andric Preprocessor &PP = *AST->PP; 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric if (ToLoad >= LoadASTOnly) 8500b57cec5SDimitry Andric AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), 8510b57cec5SDimitry Andric PP.getIdentifierTable(), PP.getSelectorTable(), 852fe6060f1SDimitry Andric PP.getBuiltinInfo(), 853fe6060f1SDimitry Andric AST->getTranslationUnitKind()); 8540b57cec5SDimitry Andric 855e8d8bef9SDimitry Andric DisableValidationForModuleKind disableValid = 856e8d8bef9SDimitry Andric DisableValidationForModuleKind::None; 8570b57cec5SDimitry Andric if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) 858e8d8bef9SDimitry Andric disableValid = DisableValidationForModuleKind::All; 8590b57cec5SDimitry Andric AST->Reader = new ASTReader( 8600b57cec5SDimitry Andric PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {}, 8610b57cec5SDimitry Andric /*isysroot=*/"", 86204eeddc0SDimitry Andric /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors); 8630b57cec5SDimitry Andric 86406c3fb27SDimitry Andric unsigned Counter = 0; 865a7dea167SDimitry Andric AST->Reader->setListener(std::make_unique<ASTInfoCollector>( 8660b57cec5SDimitry Andric *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, 8670b57cec5SDimitry Andric AST->TargetOpts, AST->Target, Counter)); 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric // Attach the AST reader to the AST context as an external AST 8700b57cec5SDimitry Andric // source, so that declarations will be deserialized from the 8710b57cec5SDimitry Andric // AST file as needed. 8720b57cec5SDimitry Andric // We need the external source to be set up before we read the AST, because 8730b57cec5SDimitry Andric // eagerly-deserialized declarations may use it. 8740b57cec5SDimitry Andric if (AST->Ctx) 8750b57cec5SDimitry Andric AST->Ctx->setExternalSource(AST->Reader); 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile, 8780b57cec5SDimitry Andric SourceLocation(), ASTReader::ARR_None)) { 8790b57cec5SDimitry Andric case ASTReader::Success: 8800b57cec5SDimitry Andric break; 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric case ASTReader::Failure: 8830b57cec5SDimitry Andric case ASTReader::Missing: 8840b57cec5SDimitry Andric case ASTReader::OutOfDate: 8850b57cec5SDimitry Andric case ASTReader::VersionMismatch: 8860b57cec5SDimitry Andric case ASTReader::ConfigurationMismatch: 8870b57cec5SDimitry Andric case ASTReader::HadErrors: 8880b57cec5SDimitry Andric AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch); 8890b57cec5SDimitry Andric return nullptr; 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric 8925ffd83dbSDimitry Andric AST->OriginalSourceFile = std::string(AST->Reader->getOriginalSourceFile()); 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric PP.setCounterValue(Counter); 8950b57cec5SDimitry Andric 89606c3fb27SDimitry Andric Module *M = HeaderInfo.lookupModule(AST->getLangOpts().CurrentModule); 8975f757f3fSDimitry Andric if (M && AST->getLangOpts().isCompilingModule() && M->isNamedModule()) 89806c3fb27SDimitry Andric AST->Ctx->setCurrentNamedModule(M); 89906c3fb27SDimitry Andric 9000b57cec5SDimitry Andric // Create an AST consumer, even though it isn't used. 9010b57cec5SDimitry Andric if (ToLoad >= LoadASTOnly) 9020b57cec5SDimitry Andric AST->Consumer.reset(new ASTConsumer); 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric // Create a semantic analysis object and tell the AST reader about it. 9050b57cec5SDimitry Andric if (ToLoad >= LoadEverything) { 9060b57cec5SDimitry Andric AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer)); 9070b57cec5SDimitry Andric AST->TheSema->Initialize(); 9080b57cec5SDimitry Andric AST->Reader->InitializeSema(*AST->TheSema); 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric // Tell the diagnostic client that we have started a source file. 9120b57cec5SDimitry Andric AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP); 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric return AST; 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric /// Add the given macro to the hash of all top-level entities. 9180b57cec5SDimitry Andric static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) { 9190b57cec5SDimitry Andric Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash); 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric namespace { 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric /// Preprocessor callback class that updates a hash value with the names 9250b57cec5SDimitry Andric /// of all macros that have been defined by the translation unit. 9260b57cec5SDimitry Andric class MacroDefinitionTrackerPPCallbacks : public PPCallbacks { 9270b57cec5SDimitry Andric unsigned &Hash; 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric public: 9300b57cec5SDimitry Andric explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {} 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric void MacroDefined(const Token &MacroNameTok, 9330b57cec5SDimitry Andric const MacroDirective *MD) override { 9340b57cec5SDimitry Andric AddDefinedMacroToHash(MacroNameTok, Hash); 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric }; 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric } // namespace 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric /// Add the given declaration to the hash of all top-level entities. 9410b57cec5SDimitry Andric static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { 9420b57cec5SDimitry Andric if (!D) 9430b57cec5SDimitry Andric return; 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric DeclContext *DC = D->getDeclContext(); 9460b57cec5SDimitry Andric if (!DC) 9470b57cec5SDimitry Andric return; 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit())) 9500b57cec5SDimitry Andric return; 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric if (const auto *ND = dyn_cast<NamedDecl>(D)) { 9530b57cec5SDimitry Andric if (const auto *EnumD = dyn_cast<EnumDecl>(D)) { 9540b57cec5SDimitry Andric // For an unscoped enum include the enumerators in the hash since they 9550b57cec5SDimitry Andric // enter the top-level namespace. 9560b57cec5SDimitry Andric if (!EnumD->isScoped()) { 9570b57cec5SDimitry Andric for (const auto *EI : EnumD->enumerators()) { 9580b57cec5SDimitry Andric if (EI->getIdentifier()) 9590b57cec5SDimitry Andric Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash); 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric if (ND->getIdentifier()) 9650b57cec5SDimitry Andric Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash); 9660b57cec5SDimitry Andric else if (DeclarationName Name = ND->getDeclName()) { 9670b57cec5SDimitry Andric std::string NameStr = Name.getAsString(); 9680b57cec5SDimitry Andric Hash = llvm::djbHash(NameStr, Hash); 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric return; 9710b57cec5SDimitry Andric } 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric if (const auto *ImportD = dyn_cast<ImportDecl>(D)) { 9740b57cec5SDimitry Andric if (const Module *Mod = ImportD->getImportedModule()) { 9750b57cec5SDimitry Andric std::string ModName = Mod->getFullModuleName(); 9760b57cec5SDimitry Andric Hash = llvm::djbHash(ModName, Hash); 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric return; 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric namespace { 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric class TopLevelDeclTrackerConsumer : public ASTConsumer { 9850b57cec5SDimitry Andric ASTUnit &Unit; 9860b57cec5SDimitry Andric unsigned &Hash; 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric public: 9890b57cec5SDimitry Andric TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash) 9900b57cec5SDimitry Andric : Unit(_Unit), Hash(Hash) { 9910b57cec5SDimitry Andric Hash = 0; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric void handleTopLevelDecl(Decl *D) { 9950b57cec5SDimitry Andric if (!D) 9960b57cec5SDimitry Andric return; 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric // FIXME: Currently ObjC method declarations are incorrectly being 9990b57cec5SDimitry Andric // reported as top-level declarations, even though their DeclContext 10000b57cec5SDimitry Andric // is the containing ObjC @interface/@implementation. This is a 10010b57cec5SDimitry Andric // fundamental problem in the parser right now. 10020b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D)) 10030b57cec5SDimitry Andric return; 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric AddTopLevelDeclarationToHash(D, Hash); 10060b57cec5SDimitry Andric Unit.addTopLevelDecl(D); 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric handleFileLevelDecl(D); 10090b57cec5SDimitry Andric } 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric void handleFileLevelDecl(Decl *D) { 10120b57cec5SDimitry Andric Unit.addFileLevelDecl(D); 10130b57cec5SDimitry Andric if (auto *NSD = dyn_cast<NamespaceDecl>(D)) { 10140b57cec5SDimitry Andric for (auto *I : NSD->decls()) 10150b57cec5SDimitry Andric handleFileLevelDecl(I); 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override { 10200b57cec5SDimitry Andric for (auto *TopLevelDecl : D) 10210b57cec5SDimitry Andric handleTopLevelDecl(TopLevelDecl); 10220b57cec5SDimitry Andric return true; 10230b57cec5SDimitry Andric } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric // We're not interested in "interesting" decls. 10260b57cec5SDimitry Andric void HandleInterestingDecl(DeclGroupRef) override {} 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { 10290b57cec5SDimitry Andric for (auto *TopLevelDecl : D) 10300b57cec5SDimitry Andric handleTopLevelDecl(TopLevelDecl); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric ASTMutationListener *GetASTMutationListener() override { 10340b57cec5SDimitry Andric return Unit.getASTMutationListener(); 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric ASTDeserializationListener *GetASTDeserializationListener() override { 10380b57cec5SDimitry Andric return Unit.getDeserializationListener(); 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric }; 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric class TopLevelDeclTrackerAction : public ASTFrontendAction { 10430b57cec5SDimitry Andric public: 10440b57cec5SDimitry Andric ASTUnit &Unit; 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 10470b57cec5SDimitry Andric StringRef InFile) override { 10480b57cec5SDimitry Andric CI.getPreprocessor().addPPCallbacks( 1049a7dea167SDimitry Andric std::make_unique<MacroDefinitionTrackerPPCallbacks>( 10500b57cec5SDimitry Andric Unit.getCurrentTopLevelHashValue())); 1051a7dea167SDimitry Andric return std::make_unique<TopLevelDeclTrackerConsumer>( 10520b57cec5SDimitry Andric Unit, Unit.getCurrentTopLevelHashValue()); 10530b57cec5SDimitry Andric } 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric public: 10560b57cec5SDimitry Andric TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {} 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric bool hasCodeCompletionSupport() const override { return false; } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric TranslationUnitKind getTranslationUnitKind() override { 10610b57cec5SDimitry Andric return Unit.getTranslationUnitKind(); 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric }; 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric class ASTUnitPreambleCallbacks : public PreambleCallbacks { 10660b57cec5SDimitry Andric public: 10670b57cec5SDimitry Andric unsigned getHash() const { return Hash; } 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); } 10700b57cec5SDimitry Andric 1071*0fca6ea1SDimitry Andric std::vector<LocalDeclID> takeTopLevelDeclIDs() { 10720b57cec5SDimitry Andric return std::move(TopLevelDeclIDs); 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric void AfterPCHEmitted(ASTWriter &Writer) override { 10760b57cec5SDimitry Andric TopLevelDeclIDs.reserve(TopLevelDecls.size()); 10770b57cec5SDimitry Andric for (const auto *D : TopLevelDecls) { 10780b57cec5SDimitry Andric // Invalid top-level decls may not have been serialized. 10790b57cec5SDimitry Andric if (D->isInvalidDecl()) 10800b57cec5SDimitry Andric continue; 10810b57cec5SDimitry Andric TopLevelDeclIDs.push_back(Writer.getDeclID(D)); 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric void HandleTopLevelDecl(DeclGroupRef DG) override { 10860b57cec5SDimitry Andric for (auto *D : DG) { 10870b57cec5SDimitry Andric // FIXME: Currently ObjC method declarations are incorrectly being 10880b57cec5SDimitry Andric // reported as top-level declarations, even though their DeclContext 10890b57cec5SDimitry Andric // is the containing ObjC @interface/@implementation. This is a 10900b57cec5SDimitry Andric // fundamental problem in the parser right now. 10910b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D)) 10920b57cec5SDimitry Andric continue; 10930b57cec5SDimitry Andric AddTopLevelDeclarationToHash(D, Hash); 10940b57cec5SDimitry Andric TopLevelDecls.push_back(D); 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric std::unique_ptr<PPCallbacks> createPPCallbacks() override { 1099a7dea167SDimitry Andric return std::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash); 11000b57cec5SDimitry Andric } 11010b57cec5SDimitry Andric 11020b57cec5SDimitry Andric private: 11030b57cec5SDimitry Andric unsigned Hash = 0; 11040b57cec5SDimitry Andric std::vector<Decl *> TopLevelDecls; 1105*0fca6ea1SDimitry Andric std::vector<LocalDeclID> TopLevelDeclIDs; 11060b57cec5SDimitry Andric llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags; 11070b57cec5SDimitry Andric }; 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric } // namespace 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) { 11120b57cec5SDimitry Andric return StoredDiag.getLocation().isValid(); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric static void 11160b57cec5SDimitry Andric checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) { 11170b57cec5SDimitry Andric // Get rid of stored diagnostics except the ones from the driver which do not 11180b57cec5SDimitry Andric // have a source location. 1119349cc55cSDimitry Andric llvm::erase_if(StoredDiags, isNonDriverDiag); 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & 11230b57cec5SDimitry Andric StoredDiagnostics, 11240b57cec5SDimitry Andric SourceManager &SM) { 11250b57cec5SDimitry Andric // The stored diagnostic has the old source manager in it; update 11260b57cec5SDimitry Andric // the locations to refer into the new source manager. Since we've 11270b57cec5SDimitry Andric // been careful to make sure that the source manager's state 11280b57cec5SDimitry Andric // before and after are identical, so that we can reuse the source 11290b57cec5SDimitry Andric // location itself. 11300b57cec5SDimitry Andric for (auto &SD : StoredDiagnostics) { 11310b57cec5SDimitry Andric if (SD.getLocation().isValid()) { 11320b57cec5SDimitry Andric FullSourceLoc Loc(SD.getLocation(), SM); 11330b57cec5SDimitry Andric SD.setLocation(Loc); 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric /// Parse the source file into a translation unit using the given compiler 11390b57cec5SDimitry Andric /// invocation, replacing the current translation unit. 11400b57cec5SDimitry Andric /// 11410b57cec5SDimitry Andric /// \returns True if a failure occurred that causes the ASTUnit not to 11420b57cec5SDimitry Andric /// contain any translation-unit information, false otherwise. 11430b57cec5SDimitry Andric bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, 11440b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer, 11450b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { 11460b57cec5SDimitry Andric if (!Invocation) 11470b57cec5SDimitry Andric return true; 11480b57cec5SDimitry Andric 11490b57cec5SDimitry Andric if (VFS && FileMgr) 11500b57cec5SDimitry Andric assert(VFS == &FileMgr->getVirtualFileSystem() && 11510b57cec5SDimitry Andric "VFS passed to Parse and VFS in FileMgr are different"); 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation); 11540b57cec5SDimitry Andric if (OverrideMainBuffer) { 11550b57cec5SDimitry Andric assert(Preamble && 11560b57cec5SDimitry Andric "No preamble was built, but OverrideMainBuffer is not null"); 11570b57cec5SDimitry Andric Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get()); 11580b57cec5SDimitry Andric // VFS may have changed... 11590b57cec5SDimitry Andric } 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric // Create the compiler instance to use for building the AST. 11620b57cec5SDimitry Andric std::unique_ptr<CompilerInstance> Clang( 11630b57cec5SDimitry Andric new CompilerInstance(std::move(PCHContainerOps))); 116406c3fb27SDimitry Andric Clang->setInvocation(CCInvocation); 11650b57cec5SDimitry Andric 1166e8d8bef9SDimitry Andric // Clean up on error, disengage it if the function returns successfully. 1167e8d8bef9SDimitry Andric auto CleanOnError = llvm::make_scope_exit([&]() { 1168e8d8bef9SDimitry Andric // Remove the overridden buffer we used for the preamble. 1169e8d8bef9SDimitry Andric SavedMainFileBuffer = nullptr; 1170e8d8bef9SDimitry Andric 1171e8d8bef9SDimitry Andric // Keep the ownership of the data in the ASTUnit because the client may 1172e8d8bef9SDimitry Andric // want to see the diagnostics. 1173e8d8bef9SDimitry Andric transferASTDataFromCompilerInstance(*Clang); 1174e8d8bef9SDimitry Andric FailedParseDiagnostics.swap(StoredDiagnostics); 1175e8d8bef9SDimitry Andric StoredDiagnostics.clear(); 1176e8d8bef9SDimitry Andric NumStoredDiagnosticsFromDriver = 0; 1177e8d8bef9SDimitry Andric }); 1178e8d8bef9SDimitry Andric 11790b57cec5SDimitry Andric // Ensure that Clang has a FileManager with the right VFS, which may have 11800b57cec5SDimitry Andric // changed above in AddImplicitPreamble. If VFS is nullptr, rely on 11810b57cec5SDimitry Andric // createFileManager to create one. 11820b57cec5SDimitry Andric if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) 11830b57cec5SDimitry Andric Clang->setFileManager(&*FileMgr); 11840b57cec5SDimitry Andric else 11850b57cec5SDimitry Andric FileMgr = Clang->createFileManager(std::move(VFS)); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 11880b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> 11890b57cec5SDimitry Andric CICleanup(Clang.get()); 11900b57cec5SDimitry Andric 11915ffd83dbSDimitry Andric OriginalSourceFile = 11925ffd83dbSDimitry Andric std::string(Clang->getFrontendOpts().Inputs[0].getFile()); 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric // Set up diagnostics, capturing any diagnostics that would 11950b57cec5SDimitry Andric // otherwise be dropped. 11960b57cec5SDimitry Andric Clang->setDiagnostics(&getDiagnostics()); 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric // Create the target instance. 1199fe6060f1SDimitry Andric if (!Clang->createTarget()) 12000b57cec5SDimitry Andric return true; 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs.size() == 1 && 12030b57cec5SDimitry Andric "Invocation must have exactly one source file!"); 12040b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == 12050b57cec5SDimitry Andric InputKind::Source && 12060b57cec5SDimitry Andric "FIXME: AST inputs not yet supported here!"); 12070b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != 1208a7dea167SDimitry Andric Language::LLVM_IR && 12090b57cec5SDimitry Andric "IR inputs not support here!"); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric // Configure the various subsystems. 12120b57cec5SDimitry Andric LangOpts = Clang->getInvocation().LangOpts; 12130b57cec5SDimitry Andric FileSystemOpts = Clang->getFileSystemOpts(); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric ResetForParse(); 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric SourceMgr = new SourceManager(getDiagnostics(), *FileMgr, 12180b57cec5SDimitry Andric UserFilesAreVolatile); 12190b57cec5SDimitry Andric if (!OverrideMainBuffer) { 12200b57cec5SDimitry Andric checkAndRemoveNonDriverDiags(StoredDiagnostics); 12210b57cec5SDimitry Andric TopLevelDeclsInPreamble.clear(); 12220b57cec5SDimitry Andric } 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric // Create the source manager. 12250b57cec5SDimitry Andric Clang->setSourceManager(&getSourceManager()); 12260b57cec5SDimitry Andric 12270b57cec5SDimitry Andric // If the main file has been overridden due to the use of a preamble, 12280b57cec5SDimitry Andric // make that override happen and introduce the preamble. 12290b57cec5SDimitry Andric if (OverrideMainBuffer) { 12300b57cec5SDimitry Andric // The stored diagnostic has the old source manager in it; update 12310b57cec5SDimitry Andric // the locations to refer into the new source manager. Since we've 12320b57cec5SDimitry Andric // been careful to make sure that the source manager's state 12330b57cec5SDimitry Andric // before and after are identical, so that we can reuse the source 12340b57cec5SDimitry Andric // location itself. 12350b57cec5SDimitry Andric checkAndSanitizeDiags(StoredDiagnostics, getSourceManager()); 12360b57cec5SDimitry Andric 12370b57cec5SDimitry Andric // Keep track of the override buffer; 12380b57cec5SDimitry Andric SavedMainFileBuffer = std::move(OverrideMainBuffer); 12390b57cec5SDimitry Andric } 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric std::unique_ptr<TopLevelDeclTrackerAction> Act( 12420b57cec5SDimitry Andric new TopLevelDeclTrackerAction(*this)); 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 12450b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction> 12460b57cec5SDimitry Andric ActCleanup(Act.get()); 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) 1249e8d8bef9SDimitry Andric return true; 12500b57cec5SDimitry Andric 12510b57cec5SDimitry Andric if (SavedMainFileBuffer) 12520b57cec5SDimitry Andric TranslateStoredDiagnostics(getFileManager(), getSourceManager(), 12530b57cec5SDimitry Andric PreambleDiagnostics, StoredDiagnostics); 12540b57cec5SDimitry Andric else 12550b57cec5SDimitry Andric PreambleSrcLocCache.clear(); 12560b57cec5SDimitry Andric 12570b57cec5SDimitry Andric if (llvm::Error Err = Act->Execute()) { 12580b57cec5SDimitry Andric consumeError(std::move(Err)); // FIXME this drops errors on the floor. 1259e8d8bef9SDimitry Andric return true; 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric transferASTDataFromCompilerInstance(*Clang); 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric Act->EndSourceFile(); 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric FailedParseDiagnostics.clear(); 12670b57cec5SDimitry Andric 1268e8d8bef9SDimitry Andric CleanOnError.release(); 1269e8d8bef9SDimitry Andric 12700b57cec5SDimitry Andric return false; 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 12740b57cec5SDimitry Andric makeStandaloneRange(CharSourceRange Range, const SourceManager &SM, 12750b57cec5SDimitry Andric const LangOptions &LangOpts) { 12760b57cec5SDimitry Andric CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts); 12770b57cec5SDimitry Andric unsigned Offset = SM.getFileOffset(FileRange.getBegin()); 12780b57cec5SDimitry Andric unsigned EndOffset = SM.getFileOffset(FileRange.getEnd()); 12790b57cec5SDimitry Andric return std::make_pair(Offset, EndOffset); 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM, 12830b57cec5SDimitry Andric const LangOptions &LangOpts, 12840b57cec5SDimitry Andric const FixItHint &InFix) { 12850b57cec5SDimitry Andric ASTUnit::StandaloneFixIt OutFix; 12860b57cec5SDimitry Andric OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts); 12870b57cec5SDimitry Andric OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM, 12880b57cec5SDimitry Andric LangOpts); 12890b57cec5SDimitry Andric OutFix.CodeToInsert = InFix.CodeToInsert; 12900b57cec5SDimitry Andric OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions; 12910b57cec5SDimitry Andric return OutFix; 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric static ASTUnit::StandaloneDiagnostic 12950b57cec5SDimitry Andric makeStandaloneDiagnostic(const LangOptions &LangOpts, 12960b57cec5SDimitry Andric const StoredDiagnostic &InDiag) { 12970b57cec5SDimitry Andric ASTUnit::StandaloneDiagnostic OutDiag; 12980b57cec5SDimitry Andric OutDiag.ID = InDiag.getID(); 12990b57cec5SDimitry Andric OutDiag.Level = InDiag.getLevel(); 13005ffd83dbSDimitry Andric OutDiag.Message = std::string(InDiag.getMessage()); 13010b57cec5SDimitry Andric OutDiag.LocOffset = 0; 13020b57cec5SDimitry Andric if (InDiag.getLocation().isInvalid()) 13030b57cec5SDimitry Andric return OutDiag; 13040b57cec5SDimitry Andric const SourceManager &SM = InDiag.getLocation().getManager(); 13050b57cec5SDimitry Andric SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation()); 13065ffd83dbSDimitry Andric OutDiag.Filename = std::string(SM.getFilename(FileLoc)); 13070b57cec5SDimitry Andric if (OutDiag.Filename.empty()) 13080b57cec5SDimitry Andric return OutDiag; 13090b57cec5SDimitry Andric OutDiag.LocOffset = SM.getFileOffset(FileLoc); 13100b57cec5SDimitry Andric for (const auto &Range : InDiag.getRanges()) 13110b57cec5SDimitry Andric OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts)); 13120b57cec5SDimitry Andric for (const auto &FixIt : InDiag.getFixIts()) 13130b57cec5SDimitry Andric OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt)); 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric return OutDiag; 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric /// Attempt to build or re-use a precompiled preamble when (re-)parsing 13190b57cec5SDimitry Andric /// the source file. 13200b57cec5SDimitry Andric /// 13210b57cec5SDimitry Andric /// This routine will compute the preamble of the main source file. If a 13220b57cec5SDimitry Andric /// non-trivial preamble is found, it will precompile that preamble into a 13230b57cec5SDimitry Andric /// precompiled header so that the precompiled preamble can be used to reduce 13240b57cec5SDimitry Andric /// reparsing time. If a precompiled preamble has already been constructed, 13250b57cec5SDimitry Andric /// this routine will determine if it is still valid and, if so, avoid 13260b57cec5SDimitry Andric /// rebuilding the precompiled preamble. 13270b57cec5SDimitry Andric /// 13280b57cec5SDimitry Andric /// \param AllowRebuild When true (the default), this routine is 13290b57cec5SDimitry Andric /// allowed to rebuild the precompiled preamble if it is found to be 13300b57cec5SDimitry Andric /// out-of-date. 13310b57cec5SDimitry Andric /// 13320b57cec5SDimitry Andric /// \param MaxLines When non-zero, the maximum number of lines that 13330b57cec5SDimitry Andric /// can occur within the preamble. 13340b57cec5SDimitry Andric /// 13350b57cec5SDimitry Andric /// \returns If the precompiled preamble can be used, returns a newly-allocated 13360b57cec5SDimitry Andric /// buffer that should be used in place of the main file when doing so. 13370b57cec5SDimitry Andric /// Otherwise, returns a NULL pointer. 13380b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> 13390b57cec5SDimitry Andric ASTUnit::getMainBufferWithPrecompiledPreamble( 13400b57cec5SDimitry Andric std::shared_ptr<PCHContainerOperations> PCHContainerOps, 13410b57cec5SDimitry Andric CompilerInvocation &PreambleInvocationIn, 13420b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild, 13430b57cec5SDimitry Andric unsigned MaxLines) { 13440b57cec5SDimitry Andric auto MainFilePath = 13450b57cec5SDimitry Andric PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile(); 13460b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer = 13470b57cec5SDimitry Andric getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(), 13480b57cec5SDimitry Andric MainFilePath, UserFilesAreVolatile); 13490b57cec5SDimitry Andric if (!MainFileBuffer) 13500b57cec5SDimitry Andric return nullptr; 13510b57cec5SDimitry Andric 1352e8d8bef9SDimitry Andric PreambleBounds Bounds = ComputePreambleBounds( 13535f757f3fSDimitry Andric PreambleInvocationIn.getLangOpts(), *MainFileBuffer, MaxLines); 13540b57cec5SDimitry Andric if (!Bounds.Size) 13550b57cec5SDimitry Andric return nullptr; 13560b57cec5SDimitry Andric 13570b57cec5SDimitry Andric if (Preamble) { 1358e8d8bef9SDimitry Andric if (Preamble->CanReuse(PreambleInvocationIn, *MainFileBuffer, Bounds, 1359e8d8bef9SDimitry Andric *VFS)) { 13600b57cec5SDimitry Andric // Okay! We can re-use the precompiled preamble. 13610b57cec5SDimitry Andric 13620b57cec5SDimitry Andric // Set the state of the diagnostic object to mimic its state 13630b57cec5SDimitry Andric // after parsing the preamble. 13640b57cec5SDimitry Andric getDiagnostics().Reset(); 13650b57cec5SDimitry Andric ProcessWarningOptions(getDiagnostics(), 13660b57cec5SDimitry Andric PreambleInvocationIn.getDiagnosticOpts()); 13670b57cec5SDimitry Andric getDiagnostics().setNumWarnings(NumWarningsInPreamble); 13680b57cec5SDimitry Andric 13690b57cec5SDimitry Andric PreambleRebuildCountdown = 1; 13700b57cec5SDimitry Andric return MainFileBuffer; 13710b57cec5SDimitry Andric } else { 13720b57cec5SDimitry Andric Preamble.reset(); 13730b57cec5SDimitry Andric PreambleDiagnostics.clear(); 13740b57cec5SDimitry Andric TopLevelDeclsInPreamble.clear(); 13750b57cec5SDimitry Andric PreambleSrcLocCache.clear(); 13760b57cec5SDimitry Andric PreambleRebuildCountdown = 1; 13770b57cec5SDimitry Andric } 13780b57cec5SDimitry Andric } 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric // If the preamble rebuild counter > 1, it's because we previously 13810b57cec5SDimitry Andric // failed to build a preamble and we're not yet ready to try 13820b57cec5SDimitry Andric // again. Decrement the counter and return a failure. 13830b57cec5SDimitry Andric if (PreambleRebuildCountdown > 1) { 13840b57cec5SDimitry Andric --PreambleRebuildCountdown; 13850b57cec5SDimitry Andric return nullptr; 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric assert(!Preamble && "No Preamble should be stored at that point"); 13890b57cec5SDimitry Andric // If we aren't allowed to rebuild the precompiled preamble, just 13900b57cec5SDimitry Andric // return now. 13910b57cec5SDimitry Andric if (!AllowRebuild) 13920b57cec5SDimitry Andric return nullptr; 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric ++PreambleCounter; 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone; 13970b57cec5SDimitry Andric SmallVector<StoredDiagnostic, 4> NewPreambleDiags; 13980b57cec5SDimitry Andric ASTUnitPreambleCallbacks Callbacks; 13990b57cec5SDimitry Andric { 1400bdd1243dSDimitry Andric std::optional<CaptureDroppedDiagnostics> Capture; 14010b57cec5SDimitry Andric if (CaptureDiagnostics != CaptureDiagsKind::None) 14020b57cec5SDimitry Andric Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags, 14030b57cec5SDimitry Andric &NewPreambleDiagsStandalone); 14040b57cec5SDimitry Andric 14050b57cec5SDimitry Andric // We did not previously compute a preamble, or it can't be reused anyway. 14060b57cec5SDimitry Andric SimpleTimer PreambleTimer(WantTiming); 14070b57cec5SDimitry Andric PreambleTimer.setOutput("Precompiling preamble"); 14080b57cec5SDimitry Andric 14090b57cec5SDimitry Andric const bool PreviousSkipFunctionBodies = 14100b57cec5SDimitry Andric PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies; 14110b57cec5SDimitry Andric if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble) 14120b57cec5SDimitry Andric PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true; 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build( 14150b57cec5SDimitry Andric PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, 141606c3fb27SDimitry Andric PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath, 141706c3fb27SDimitry Andric Callbacks); 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = 14200b57cec5SDimitry Andric PreviousSkipFunctionBodies; 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric if (NewPreamble) { 14230b57cec5SDimitry Andric Preamble = std::move(*NewPreamble); 14240b57cec5SDimitry Andric PreambleRebuildCountdown = 1; 14250b57cec5SDimitry Andric } else { 14260b57cec5SDimitry Andric switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) { 14270b57cec5SDimitry Andric case BuildPreambleError::CouldntCreateTempFile: 14280b57cec5SDimitry Andric // Try again next time. 14290b57cec5SDimitry Andric PreambleRebuildCountdown = 1; 14300b57cec5SDimitry Andric return nullptr; 14310b57cec5SDimitry Andric case BuildPreambleError::CouldntCreateTargetInfo: 14320b57cec5SDimitry Andric case BuildPreambleError::BeginSourceFileFailed: 14330b57cec5SDimitry Andric case BuildPreambleError::CouldntEmitPCH: 14340b57cec5SDimitry Andric case BuildPreambleError::BadInputs: 14350b57cec5SDimitry Andric // These erros are more likely to repeat, retry after some period. 14360b57cec5SDimitry Andric PreambleRebuildCountdown = DefaultPreambleRebuildInterval; 14370b57cec5SDimitry Andric return nullptr; 14380b57cec5SDimitry Andric } 14390b57cec5SDimitry Andric llvm_unreachable("unexpected BuildPreambleError"); 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric } 14420b57cec5SDimitry Andric 14430b57cec5SDimitry Andric assert(Preamble && "Preamble wasn't built"); 14440b57cec5SDimitry Andric 14450b57cec5SDimitry Andric TopLevelDecls.clear(); 14460b57cec5SDimitry Andric TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs(); 14470b57cec5SDimitry Andric PreambleTopLevelHashValue = Callbacks.getHash(); 14480b57cec5SDimitry Andric 14490b57cec5SDimitry Andric NumWarningsInPreamble = getDiagnostics().getNumWarnings(); 14500b57cec5SDimitry Andric 14510b57cec5SDimitry Andric checkAndRemoveNonDriverDiags(NewPreambleDiags); 14520b57cec5SDimitry Andric StoredDiagnostics = std::move(NewPreambleDiags); 14530b57cec5SDimitry Andric PreambleDiagnostics = std::move(NewPreambleDiagsStandalone); 14540b57cec5SDimitry Andric 14550b57cec5SDimitry Andric // If the hash of top-level entities differs from the hash of the top-level 14560b57cec5SDimitry Andric // entities the last time we rebuilt the preamble, clear out the completion 14570b57cec5SDimitry Andric // cache. 14580b57cec5SDimitry Andric if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) { 14590b57cec5SDimitry Andric CompletionCacheTopLevelHashValue = 0; 14600b57cec5SDimitry Andric PreambleTopLevelHashValue = CurrentTopLevelHashValue; 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric return MainFileBuffer; 14640b57cec5SDimitry Andric } 14650b57cec5SDimitry Andric 14660b57cec5SDimitry Andric void ASTUnit::RealizeTopLevelDeclsFromPreamble() { 14670b57cec5SDimitry Andric assert(Preamble && "Should only be called when preamble was built"); 14680b57cec5SDimitry Andric 14690b57cec5SDimitry Andric std::vector<Decl *> Resolved; 14700b57cec5SDimitry Andric Resolved.reserve(TopLevelDeclsInPreamble.size()); 1471*0fca6ea1SDimitry Andric // The module file of the preamble. 1472*0fca6ea1SDimitry Andric serialization::ModuleFile &MF = Reader->getModuleManager().getPrimaryModule(); 14730b57cec5SDimitry Andric for (const auto TopLevelDecl : TopLevelDeclsInPreamble) { 14740b57cec5SDimitry Andric // Resolve the declaration ID to an actual declaration, possibly 14750b57cec5SDimitry Andric // deserializing the declaration in the process. 1476*0fca6ea1SDimitry Andric if (Decl *D = Reader->GetLocalDecl(MF, TopLevelDecl)) 14770b57cec5SDimitry Andric Resolved.push_back(D); 14780b57cec5SDimitry Andric } 14790b57cec5SDimitry Andric TopLevelDeclsInPreamble.clear(); 14800b57cec5SDimitry Andric TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end()); 14810b57cec5SDimitry Andric } 14820b57cec5SDimitry Andric 14830b57cec5SDimitry Andric void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) { 14840b57cec5SDimitry Andric // Steal the created target, context, and preprocessor if they have been 14850b57cec5SDimitry Andric // created. 14860b57cec5SDimitry Andric assert(CI.hasInvocation() && "missing invocation"); 14870b57cec5SDimitry Andric LangOpts = CI.getInvocation().LangOpts; 14880b57cec5SDimitry Andric TheSema = CI.takeSema(); 14890b57cec5SDimitry Andric Consumer = CI.takeASTConsumer(); 14900b57cec5SDimitry Andric if (CI.hasASTContext()) 14910b57cec5SDimitry Andric Ctx = &CI.getASTContext(); 14920b57cec5SDimitry Andric if (CI.hasPreprocessor()) 14930b57cec5SDimitry Andric PP = CI.getPreprocessorPtr(); 14940b57cec5SDimitry Andric CI.setSourceManager(nullptr); 14950b57cec5SDimitry Andric CI.setFileManager(nullptr); 14960b57cec5SDimitry Andric if (CI.hasTarget()) 14970b57cec5SDimitry Andric Target = &CI.getTarget(); 1498480093f4SDimitry Andric Reader = CI.getASTReader(); 14990b57cec5SDimitry Andric HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure(); 15000b57cec5SDimitry Andric } 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric StringRef ASTUnit::getMainFileName() const { 15030b57cec5SDimitry Andric if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) { 15040b57cec5SDimitry Andric const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0]; 15050b57cec5SDimitry Andric if (Input.isFile()) 15060b57cec5SDimitry Andric return Input.getFile(); 15070b57cec5SDimitry Andric else 1508e8d8bef9SDimitry Andric return Input.getBuffer().getBufferIdentifier(); 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric if (SourceMgr) { 15125f757f3fSDimitry Andric if (OptionalFileEntryRef FE = 15135f757f3fSDimitry Andric SourceMgr->getFileEntryRefForID(SourceMgr->getMainFileID())) 15140b57cec5SDimitry Andric return FE->getName(); 15150b57cec5SDimitry Andric } 15160b57cec5SDimitry Andric 15170b57cec5SDimitry Andric return {}; 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric StringRef ASTUnit::getASTFileName() const { 15210b57cec5SDimitry Andric if (!isMainFileAST()) 15220b57cec5SDimitry Andric return {}; 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric serialization::ModuleFile & 15250b57cec5SDimitry Andric Mod = Reader->getModuleManager().getPrimaryModule(); 15260b57cec5SDimitry Andric return Mod.FileName; 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric std::unique_ptr<ASTUnit> 15300b57cec5SDimitry Andric ASTUnit::create(std::shared_ptr<CompilerInvocation> CI, 15310b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> Diags, 15320b57cec5SDimitry Andric CaptureDiagsKind CaptureDiagnostics, 15330b57cec5SDimitry Andric bool UserFilesAreVolatile) { 15340b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST(new ASTUnit(false)); 15350b57cec5SDimitry Andric ConfigureDiags(Diags, *AST, CaptureDiagnostics); 15360b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = 15370b57cec5SDimitry Andric createVFSFromCompilerInvocation(*CI, *Diags); 15380b57cec5SDimitry Andric AST->Diagnostics = Diags; 15390b57cec5SDimitry Andric AST->FileSystemOpts = CI->getFileSystemOpts(); 15400b57cec5SDimitry Andric AST->Invocation = std::move(CI); 15410b57cec5SDimitry Andric AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); 15420b57cec5SDimitry Andric AST->UserFilesAreVolatile = UserFilesAreVolatile; 15430b57cec5SDimitry Andric AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, 15440b57cec5SDimitry Andric UserFilesAreVolatile); 15450b57cec5SDimitry Andric AST->ModuleCache = new InMemoryModuleCache; 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric return AST; 15480b57cec5SDimitry Andric } 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( 15510b57cec5SDimitry Andric std::shared_ptr<CompilerInvocation> CI, 15520b57cec5SDimitry Andric std::shared_ptr<PCHContainerOperations> PCHContainerOps, 15530b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action, 15540b57cec5SDimitry Andric ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath, 15550b57cec5SDimitry Andric bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, 15560b57cec5SDimitry Andric unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults, 1557e8d8bef9SDimitry Andric bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) { 15580b57cec5SDimitry Andric assert(CI && "A CompilerInvocation is required"); 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andric std::unique_ptr<ASTUnit> OwnAST; 15610b57cec5SDimitry Andric ASTUnit *AST = Unit; 15620b57cec5SDimitry Andric if (!AST) { 15630b57cec5SDimitry Andric // Create the AST unit. 15640b57cec5SDimitry Andric OwnAST = create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile); 15650b57cec5SDimitry Andric AST = OwnAST.get(); 15660b57cec5SDimitry Andric if (!AST) 15670b57cec5SDimitry Andric return nullptr; 15680b57cec5SDimitry Andric } 15690b57cec5SDimitry Andric 15700b57cec5SDimitry Andric if (!ResourceFilesPath.empty()) { 15710b57cec5SDimitry Andric // Override the resources path. 15725ffd83dbSDimitry Andric CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath); 15730b57cec5SDimitry Andric } 15740b57cec5SDimitry Andric AST->OnlyLocalDecls = OnlyLocalDecls; 15750b57cec5SDimitry Andric AST->CaptureDiagnostics = CaptureDiagnostics; 15760b57cec5SDimitry Andric if (PrecompilePreambleAfterNParses > 0) 15770b57cec5SDimitry Andric AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses; 15780b57cec5SDimitry Andric AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete; 15790b57cec5SDimitry Andric AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; 1580e8d8bef9SDimitry Andric AST->IncludeBriefCommentsInCodeCompletion = false; 15810b57cec5SDimitry Andric 15820b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 15830b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> 15840b57cec5SDimitry Andric ASTUnitCleanup(OwnAST.get()); 15850b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 15860b57cec5SDimitry Andric llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> 15870b57cec5SDimitry Andric DiagCleanup(Diags.get()); 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric // We'll manage file buffers ourselves. 15900b57cec5SDimitry Andric CI->getPreprocessorOpts().RetainRemappedFileBuffers = true; 15910b57cec5SDimitry Andric CI->getFrontendOpts().DisableFree = false; 15920b57cec5SDimitry Andric ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric // Create the compiler instance to use for building the AST. 15950b57cec5SDimitry Andric std::unique_ptr<CompilerInstance> Clang( 15960b57cec5SDimitry Andric new CompilerInstance(std::move(PCHContainerOps))); 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 15990b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> 16000b57cec5SDimitry Andric CICleanup(Clang.get()); 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric Clang->setInvocation(std::move(CI)); 16035ffd83dbSDimitry Andric AST->OriginalSourceFile = 16045ffd83dbSDimitry Andric std::string(Clang->getFrontendOpts().Inputs[0].getFile()); 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric // Set up diagnostics, capturing any diagnostics that would 16070b57cec5SDimitry Andric // otherwise be dropped. 16080b57cec5SDimitry Andric Clang->setDiagnostics(&AST->getDiagnostics()); 16090b57cec5SDimitry Andric 16100b57cec5SDimitry Andric // Create the target instance. 1611fe6060f1SDimitry Andric if (!Clang->createTarget()) 16120b57cec5SDimitry Andric return nullptr; 16130b57cec5SDimitry Andric 16140b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs.size() == 1 && 16150b57cec5SDimitry Andric "Invocation must have exactly one source file!"); 16160b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == 16170b57cec5SDimitry Andric InputKind::Source && 16180b57cec5SDimitry Andric "FIXME: AST inputs not yet supported here!"); 16190b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != 1620a7dea167SDimitry Andric Language::LLVM_IR && 16210b57cec5SDimitry Andric "IR inputs not support here!"); 16220b57cec5SDimitry Andric 16230b57cec5SDimitry Andric // Configure the various subsystems. 16240b57cec5SDimitry Andric AST->TheSema.reset(); 16250b57cec5SDimitry Andric AST->Ctx = nullptr; 16260b57cec5SDimitry Andric AST->PP = nullptr; 16270b57cec5SDimitry Andric AST->Reader = nullptr; 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric // Create a file manager object to provide access to and cache the filesystem. 16300b57cec5SDimitry Andric Clang->setFileManager(&AST->getFileManager()); 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric // Create the source manager. 16330b57cec5SDimitry Andric Clang->setSourceManager(&AST->getSourceManager()); 16340b57cec5SDimitry Andric 16350b57cec5SDimitry Andric FrontendAction *Act = Action; 16360b57cec5SDimitry Andric 16370b57cec5SDimitry Andric std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct; 16380b57cec5SDimitry Andric if (!Act) { 16390b57cec5SDimitry Andric TrackerAct.reset(new TopLevelDeclTrackerAction(*AST)); 16400b57cec5SDimitry Andric Act = TrackerAct.get(); 16410b57cec5SDimitry Andric } 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 16440b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction> 16450b57cec5SDimitry Andric ActCleanup(TrackerAct.get()); 16460b57cec5SDimitry Andric 16470b57cec5SDimitry Andric if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { 16480b57cec5SDimitry Andric AST->transferASTDataFromCompilerInstance(*Clang); 16490b57cec5SDimitry Andric if (OwnAST && ErrAST) 16500b57cec5SDimitry Andric ErrAST->swap(OwnAST); 16510b57cec5SDimitry Andric 16520b57cec5SDimitry Andric return nullptr; 16530b57cec5SDimitry Andric } 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric if (Persistent && !TrackerAct) { 16560b57cec5SDimitry Andric Clang->getPreprocessor().addPPCallbacks( 1657a7dea167SDimitry Andric std::make_unique<MacroDefinitionTrackerPPCallbacks>( 16580b57cec5SDimitry Andric AST->getCurrentTopLevelHashValue())); 16590b57cec5SDimitry Andric std::vector<std::unique_ptr<ASTConsumer>> Consumers; 16600b57cec5SDimitry Andric if (Clang->hasASTConsumer()) 16610b57cec5SDimitry Andric Consumers.push_back(Clang->takeASTConsumer()); 1662a7dea167SDimitry Andric Consumers.push_back(std::make_unique<TopLevelDeclTrackerConsumer>( 16630b57cec5SDimitry Andric *AST, AST->getCurrentTopLevelHashValue())); 16640b57cec5SDimitry Andric Clang->setASTConsumer( 1665a7dea167SDimitry Andric std::make_unique<MultiplexConsumer>(std::move(Consumers))); 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric if (llvm::Error Err = Act->Execute()) { 16680b57cec5SDimitry Andric consumeError(std::move(Err)); // FIXME this drops errors on the floor. 16690b57cec5SDimitry Andric AST->transferASTDataFromCompilerInstance(*Clang); 16700b57cec5SDimitry Andric if (OwnAST && ErrAST) 16710b57cec5SDimitry Andric ErrAST->swap(OwnAST); 16720b57cec5SDimitry Andric 16730b57cec5SDimitry Andric return nullptr; 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric 16760b57cec5SDimitry Andric // Steal the created target, context, and preprocessor. 16770b57cec5SDimitry Andric AST->transferASTDataFromCompilerInstance(*Clang); 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric Act->EndSourceFile(); 16800b57cec5SDimitry Andric 16810b57cec5SDimitry Andric if (OwnAST) 16820b57cec5SDimitry Andric return OwnAST.release(); 16830b57cec5SDimitry Andric else 16840b57cec5SDimitry Andric return AST; 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric bool ASTUnit::LoadFromCompilerInvocation( 16880b57cec5SDimitry Andric std::shared_ptr<PCHContainerOperations> PCHContainerOps, 16890b57cec5SDimitry Andric unsigned PrecompilePreambleAfterNParses, 16900b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { 16910b57cec5SDimitry Andric if (!Invocation) 16920b57cec5SDimitry Andric return true; 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric assert(VFS && "VFS is null"); 16950b57cec5SDimitry Andric 16960b57cec5SDimitry Andric // We'll manage file buffers ourselves. 16970b57cec5SDimitry Andric Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true; 16980b57cec5SDimitry Andric Invocation->getFrontendOpts().DisableFree = false; 16990b57cec5SDimitry Andric getDiagnostics().Reset(); 17000b57cec5SDimitry Andric ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; 17030b57cec5SDimitry Andric if (PrecompilePreambleAfterNParses > 0) { 17040b57cec5SDimitry Andric PreambleRebuildCountdown = PrecompilePreambleAfterNParses; 17050b57cec5SDimitry Andric OverrideMainBuffer = 17060b57cec5SDimitry Andric getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); 17070b57cec5SDimitry Andric getDiagnostics().Reset(); 17080b57cec5SDimitry Andric ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); 17090b57cec5SDimitry Andric } 17100b57cec5SDimitry Andric 17110b57cec5SDimitry Andric SimpleTimer ParsingTimer(WantTiming); 17120b57cec5SDimitry Andric ParsingTimer.setOutput("Parsing " + getMainFileName()); 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 17150b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer> 17160b57cec5SDimitry Andric MemBufferCleanup(OverrideMainBuffer.get()); 17170b57cec5SDimitry Andric 17180b57cec5SDimitry Andric return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( 17220b57cec5SDimitry Andric std::shared_ptr<CompilerInvocation> CI, 17230b57cec5SDimitry Andric std::shared_ptr<PCHContainerOperations> PCHContainerOps, 17240b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr, 17250b57cec5SDimitry Andric bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, 17260b57cec5SDimitry Andric unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, 17270b57cec5SDimitry Andric bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, 17280b57cec5SDimitry Andric bool UserFilesAreVolatile) { 17290b57cec5SDimitry Andric // Create the AST unit. 17300b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST(new ASTUnit(false)); 17310b57cec5SDimitry Andric ConfigureDiags(Diags, *AST, CaptureDiagnostics); 17320b57cec5SDimitry Andric AST->Diagnostics = Diags; 17330b57cec5SDimitry Andric AST->OnlyLocalDecls = OnlyLocalDecls; 17340b57cec5SDimitry Andric AST->CaptureDiagnostics = CaptureDiagnostics; 17350b57cec5SDimitry Andric AST->TUKind = TUKind; 17360b57cec5SDimitry Andric AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; 17370b57cec5SDimitry Andric AST->IncludeBriefCommentsInCodeCompletion 17380b57cec5SDimitry Andric = IncludeBriefCommentsInCodeCompletion; 17390b57cec5SDimitry Andric AST->Invocation = std::move(CI); 17400b57cec5SDimitry Andric AST->FileSystemOpts = FileMgr->getFileSystemOpts(); 17410b57cec5SDimitry Andric AST->FileMgr = FileMgr; 17420b57cec5SDimitry Andric AST->UserFilesAreVolatile = UserFilesAreVolatile; 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 17450b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> 17460b57cec5SDimitry Andric ASTUnitCleanup(AST.get()); 17470b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 17480b57cec5SDimitry Andric llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> 17490b57cec5SDimitry Andric DiagCleanup(Diags.get()); 17500b57cec5SDimitry Andric 17510b57cec5SDimitry Andric if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), 17520b57cec5SDimitry Andric PrecompilePreambleAfterNParses, 17530b57cec5SDimitry Andric &AST->FileMgr->getVirtualFileSystem())) 17540b57cec5SDimitry Andric return nullptr; 17550b57cec5SDimitry Andric return AST; 17560b57cec5SDimitry Andric } 17570b57cec5SDimitry Andric 175806c3fb27SDimitry Andric std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine( 17590b57cec5SDimitry Andric const char **ArgBegin, const char **ArgEnd, 17600b57cec5SDimitry Andric std::shared_ptr<PCHContainerOperations> PCHContainerOps, 17610b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, 176206c3fb27SDimitry Andric bool StorePreamblesInMemory, StringRef PreambleStoragePath, 17630b57cec5SDimitry Andric bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, 17640b57cec5SDimitry Andric ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName, 17650b57cec5SDimitry Andric unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, 17660b57cec5SDimitry Andric bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, 17670b57cec5SDimitry Andric bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies, 17680b57cec5SDimitry Andric bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, 1769bdd1243dSDimitry Andric bool RetainExcludedConditionalBlocks, std::optional<StringRef> ModuleFormat, 1770bdd1243dSDimitry Andric std::unique_ptr<ASTUnit> *ErrAST, 17710b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { 17720b57cec5SDimitry Andric assert(Diags.get() && "no DiagnosticsEngine was provided"); 17730b57cec5SDimitry Andric 177406c3fb27SDimitry Andric // If no VFS was provided, create one that tracks the physical file system. 177506c3fb27SDimitry Andric // If '-working-directory' was passed as an argument, 'createInvocation' will 177606c3fb27SDimitry Andric // set this as the current working directory of the VFS. 177706c3fb27SDimitry Andric if (!VFS) 177806c3fb27SDimitry Andric VFS = llvm::vfs::createPhysicalFileSystem(); 177906c3fb27SDimitry Andric 17800b57cec5SDimitry Andric SmallVector<StoredDiagnostic, 4> StoredDiagnostics; 17810b57cec5SDimitry Andric 17820b57cec5SDimitry Andric std::shared_ptr<CompilerInvocation> CI; 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric { 17850b57cec5SDimitry Andric CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags, 17860b57cec5SDimitry Andric &StoredDiagnostics, nullptr); 17870b57cec5SDimitry Andric 178881ad6265SDimitry Andric CreateInvocationOptions CIOpts; 178981ad6265SDimitry Andric CIOpts.VFS = VFS; 179081ad6265SDimitry Andric CIOpts.Diags = Diags; 179181ad6265SDimitry Andric CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed? 1792bdd1243dSDimitry Andric CI = createInvocation(llvm::ArrayRef(ArgBegin, ArgEnd), std::move(CIOpts)); 17930b57cec5SDimitry Andric if (!CI) 17940b57cec5SDimitry Andric return nullptr; 17950b57cec5SDimitry Andric } 17960b57cec5SDimitry Andric 17970b57cec5SDimitry Andric // Override any files that need remapping 17980b57cec5SDimitry Andric for (const auto &RemappedFile : RemappedFiles) { 17990b57cec5SDimitry Andric CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first, 18000b57cec5SDimitry Andric RemappedFile.second); 18010b57cec5SDimitry Andric } 18020b57cec5SDimitry Andric PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); 18030b57cec5SDimitry Andric PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; 18040b57cec5SDimitry Andric PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; 18050b57cec5SDimitry Andric PPOpts.SingleFileParseMode = SingleFileParse; 1806a7dea167SDimitry Andric PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks; 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric // Override the resources path. 18095ffd83dbSDimitry Andric CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath); 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric CI->getFrontendOpts().SkipFunctionBodies = 18120b57cec5SDimitry Andric SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile; 18130b57cec5SDimitry Andric 18140b57cec5SDimitry Andric if (ModuleFormat) 181581ad6265SDimitry Andric CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat); 18160b57cec5SDimitry Andric 18170b57cec5SDimitry Andric // Create the AST unit. 18180b57cec5SDimitry Andric std::unique_ptr<ASTUnit> AST; 18190b57cec5SDimitry Andric AST.reset(new ASTUnit(false)); 18200b57cec5SDimitry Andric AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); 18210b57cec5SDimitry Andric AST->StoredDiagnostics.swap(StoredDiagnostics); 18220b57cec5SDimitry Andric ConfigureDiags(Diags, *AST, CaptureDiagnostics); 18230b57cec5SDimitry Andric AST->Diagnostics = Diags; 18240b57cec5SDimitry Andric AST->FileSystemOpts = CI->getFileSystemOpts(); 18250b57cec5SDimitry Andric VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS); 18260b57cec5SDimitry Andric AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); 182706c3fb27SDimitry Andric AST->StorePreamblesInMemory = StorePreamblesInMemory; 182806c3fb27SDimitry Andric AST->PreambleStoragePath = PreambleStoragePath; 18290b57cec5SDimitry Andric AST->ModuleCache = new InMemoryModuleCache; 18300b57cec5SDimitry Andric AST->OnlyLocalDecls = OnlyLocalDecls; 18310b57cec5SDimitry Andric AST->CaptureDiagnostics = CaptureDiagnostics; 18320b57cec5SDimitry Andric AST->TUKind = TUKind; 18330b57cec5SDimitry Andric AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; 18340b57cec5SDimitry Andric AST->IncludeBriefCommentsInCodeCompletion 18350b57cec5SDimitry Andric = IncludeBriefCommentsInCodeCompletion; 18360b57cec5SDimitry Andric AST->UserFilesAreVolatile = UserFilesAreVolatile; 18370b57cec5SDimitry Andric AST->Invocation = CI; 18380b57cec5SDimitry Andric AST->SkipFunctionBodies = SkipFunctionBodies; 18390b57cec5SDimitry Andric if (ForSerialization) 18400b57cec5SDimitry Andric AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache)); 18410b57cec5SDimitry Andric // Zero out now to ease cleanup during crash recovery. 18420b57cec5SDimitry Andric CI = nullptr; 18430b57cec5SDimitry Andric Diags = nullptr; 18440b57cec5SDimitry Andric 18450b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 18460b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> 18470b57cec5SDimitry Andric ASTUnitCleanup(AST.get()); 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), 18500b57cec5SDimitry Andric PrecompilePreambleAfterNParses, 18510b57cec5SDimitry Andric VFS)) { 18520b57cec5SDimitry Andric // Some error occurred, if caller wants to examine diagnostics, pass it the 18530b57cec5SDimitry Andric // ASTUnit. 18540b57cec5SDimitry Andric if (ErrAST) { 18550b57cec5SDimitry Andric AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics); 18560b57cec5SDimitry Andric ErrAST->swap(AST); 18570b57cec5SDimitry Andric } 18580b57cec5SDimitry Andric return nullptr; 18590b57cec5SDimitry Andric } 18600b57cec5SDimitry Andric 186106c3fb27SDimitry Andric return AST; 18620b57cec5SDimitry Andric } 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, 18650b57cec5SDimitry Andric ArrayRef<RemappedFile> RemappedFiles, 18660b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { 18670b57cec5SDimitry Andric if (!Invocation) 18680b57cec5SDimitry Andric return true; 18690b57cec5SDimitry Andric 18700b57cec5SDimitry Andric if (!VFS) { 18710b57cec5SDimitry Andric assert(FileMgr && "FileMgr is null on Reparse call"); 18720b57cec5SDimitry Andric VFS = &FileMgr->getVirtualFileSystem(); 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric 18750b57cec5SDimitry Andric clearFileLevelDecls(); 18760b57cec5SDimitry Andric 18770b57cec5SDimitry Andric SimpleTimer ParsingTimer(WantTiming); 18780b57cec5SDimitry Andric ParsingTimer.setOutput("Reparsing " + getMainFileName()); 18790b57cec5SDimitry Andric 18800b57cec5SDimitry Andric // Remap files. 18810b57cec5SDimitry Andric PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); 18820b57cec5SDimitry Andric for (const auto &RB : PPOpts.RemappedFileBuffers) 18830b57cec5SDimitry Andric delete RB.second; 18840b57cec5SDimitry Andric 18850b57cec5SDimitry Andric Invocation->getPreprocessorOpts().clearRemappedFiles(); 18860b57cec5SDimitry Andric for (const auto &RemappedFile : RemappedFiles) { 18870b57cec5SDimitry Andric Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first, 18880b57cec5SDimitry Andric RemappedFile.second); 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric // If we have a preamble file lying around, or if we might try to 18920b57cec5SDimitry Andric // build a precompiled preamble, do so now. 18930b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; 18940b57cec5SDimitry Andric if (Preamble || PreambleRebuildCountdown > 0) 18950b57cec5SDimitry Andric OverrideMainBuffer = 18960b57cec5SDimitry Andric getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric // Clear out the diagnostics state. 18990b57cec5SDimitry Andric FileMgr.reset(); 19000b57cec5SDimitry Andric getDiagnostics().Reset(); 19010b57cec5SDimitry Andric ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); 19020b57cec5SDimitry Andric if (OverrideMainBuffer) 19030b57cec5SDimitry Andric getDiagnostics().setNumWarnings(NumWarningsInPreamble); 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric // Parse the sources 19060b57cec5SDimitry Andric bool Result = 19070b57cec5SDimitry Andric Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric // If we're caching global code-completion results, and the top-level 19100b57cec5SDimitry Andric // declarations have changed, clear out the code-completion cache. 19110b57cec5SDimitry Andric if (!Result && ShouldCacheCodeCompletionResults && 19120b57cec5SDimitry Andric CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue) 19130b57cec5SDimitry Andric CacheCodeCompletionResults(); 19140b57cec5SDimitry Andric 19150b57cec5SDimitry Andric // We now need to clear out the completion info related to this translation 19160b57cec5SDimitry Andric // unit; it'll be recreated if necessary. 19170b57cec5SDimitry Andric CCTUInfo.reset(); 19180b57cec5SDimitry Andric 19190b57cec5SDimitry Andric return Result; 19200b57cec5SDimitry Andric } 19210b57cec5SDimitry Andric 19220b57cec5SDimitry Andric void ASTUnit::ResetForParse() { 19230b57cec5SDimitry Andric SavedMainFileBuffer.reset(); 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric SourceMgr.reset(); 19260b57cec5SDimitry Andric TheSema.reset(); 19270b57cec5SDimitry Andric Ctx.reset(); 19280b57cec5SDimitry Andric PP.reset(); 19290b57cec5SDimitry Andric Reader.reset(); 19300b57cec5SDimitry Andric 19310b57cec5SDimitry Andric TopLevelDecls.clear(); 19320b57cec5SDimitry Andric clearFileLevelDecls(); 19330b57cec5SDimitry Andric } 19340b57cec5SDimitry Andric 19350b57cec5SDimitry Andric //----------------------------------------------------------------------------// 19360b57cec5SDimitry Andric // Code completion 19370b57cec5SDimitry Andric //----------------------------------------------------------------------------// 19380b57cec5SDimitry Andric 19390b57cec5SDimitry Andric namespace { 19400b57cec5SDimitry Andric 19410b57cec5SDimitry Andric /// Code completion consumer that combines the cached code-completion 19420b57cec5SDimitry Andric /// results from an ASTUnit with the code-completion results provided to it, 19430b57cec5SDimitry Andric /// then passes the result on to 19440b57cec5SDimitry Andric class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer { 19450b57cec5SDimitry Andric uint64_t NormalContexts; 19460b57cec5SDimitry Andric ASTUnit &AST; 19470b57cec5SDimitry Andric CodeCompleteConsumer &Next; 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric public: 19500b57cec5SDimitry Andric AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, 19510b57cec5SDimitry Andric const CodeCompleteOptions &CodeCompleteOpts) 19520b57cec5SDimitry Andric : CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) { 19530b57cec5SDimitry Andric // Compute the set of contexts in which we will look when we don't have 19540b57cec5SDimitry Andric // any information about the specific context. 19550b57cec5SDimitry Andric NormalContexts 19560b57cec5SDimitry Andric = (1LL << CodeCompletionContext::CCC_TopLevel) 19570b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCInterface) 19580b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCImplementation) 19590b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCIvarList) 19600b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Statement) 19610b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Expression) 19620b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver) 19630b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_DotMemberAccess) 19640b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess) 19650b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess) 19660b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ObjCProtocolName) 19670b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression) 19680b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_Recovery); 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric if (AST.getASTContext().getLangOpts().CPlusPlus) 19710b57cec5SDimitry Andric NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag) 19720b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_UnionTag) 19730b57cec5SDimitry Andric | (1LL << CodeCompletionContext::CCC_ClassOrStructTag); 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, 19770b57cec5SDimitry Andric CodeCompletionResult *Results, 19780b57cec5SDimitry Andric unsigned NumResults) override; 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, 19810b57cec5SDimitry Andric OverloadCandidate *Candidates, 19820b57cec5SDimitry Andric unsigned NumCandidates, 198304eeddc0SDimitry Andric SourceLocation OpenParLoc, 198404eeddc0SDimitry Andric bool Braced) override { 19850b57cec5SDimitry Andric Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates, 198604eeddc0SDimitry Andric OpenParLoc, Braced); 19870b57cec5SDimitry Andric } 19880b57cec5SDimitry Andric 19890b57cec5SDimitry Andric CodeCompletionAllocator &getAllocator() override { 19900b57cec5SDimitry Andric return Next.getAllocator(); 19910b57cec5SDimitry Andric } 19920b57cec5SDimitry Andric 19930b57cec5SDimitry Andric CodeCompletionTUInfo &getCodeCompletionTUInfo() override { 19940b57cec5SDimitry Andric return Next.getCodeCompletionTUInfo(); 19950b57cec5SDimitry Andric } 19960b57cec5SDimitry Andric }; 19970b57cec5SDimitry Andric 19980b57cec5SDimitry Andric } // namespace 19990b57cec5SDimitry Andric 20000b57cec5SDimitry Andric /// Helper function that computes which global names are hidden by the 20010b57cec5SDimitry Andric /// local code-completion results. 20020b57cec5SDimitry Andric static void CalculateHiddenNames(const CodeCompletionContext &Context, 20030b57cec5SDimitry Andric CodeCompletionResult *Results, 20040b57cec5SDimitry Andric unsigned NumResults, 20050b57cec5SDimitry Andric ASTContext &Ctx, 20060b57cec5SDimitry Andric llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){ 20070b57cec5SDimitry Andric bool OnlyTagNames = false; 20080b57cec5SDimitry Andric switch (Context.getKind()) { 20090b57cec5SDimitry Andric case CodeCompletionContext::CCC_Recovery: 20100b57cec5SDimitry Andric case CodeCompletionContext::CCC_TopLevel: 20110b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCInterface: 20120b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCImplementation: 20130b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCIvarList: 20140b57cec5SDimitry Andric case CodeCompletionContext::CCC_ClassStructUnion: 20150b57cec5SDimitry Andric case CodeCompletionContext::CCC_Statement: 20160b57cec5SDimitry Andric case CodeCompletionContext::CCC_Expression: 20170b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCMessageReceiver: 20180b57cec5SDimitry Andric case CodeCompletionContext::CCC_DotMemberAccess: 20190b57cec5SDimitry Andric case CodeCompletionContext::CCC_ArrowMemberAccess: 20200b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCPropertyAccess: 20210b57cec5SDimitry Andric case CodeCompletionContext::CCC_Namespace: 20220b57cec5SDimitry Andric case CodeCompletionContext::CCC_Type: 20230b57cec5SDimitry Andric case CodeCompletionContext::CCC_Symbol: 20240b57cec5SDimitry Andric case CodeCompletionContext::CCC_SymbolOrNewName: 20250b57cec5SDimitry Andric case CodeCompletionContext::CCC_ParenthesizedExpression: 20260b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCInterfaceName: 20275f757f3fSDimitry Andric case CodeCompletionContext::CCC_TopLevelOrExpression: 20280b57cec5SDimitry Andric break; 20290b57cec5SDimitry Andric 20300b57cec5SDimitry Andric case CodeCompletionContext::CCC_EnumTag: 20310b57cec5SDimitry Andric case CodeCompletionContext::CCC_UnionTag: 20320b57cec5SDimitry Andric case CodeCompletionContext::CCC_ClassOrStructTag: 20330b57cec5SDimitry Andric OnlyTagNames = true; 20340b57cec5SDimitry Andric break; 20350b57cec5SDimitry Andric 20360b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCProtocolName: 20370b57cec5SDimitry Andric case CodeCompletionContext::CCC_MacroName: 20380b57cec5SDimitry Andric case CodeCompletionContext::CCC_MacroNameUse: 20390b57cec5SDimitry Andric case CodeCompletionContext::CCC_PreprocessorExpression: 20400b57cec5SDimitry Andric case CodeCompletionContext::CCC_PreprocessorDirective: 20410b57cec5SDimitry Andric case CodeCompletionContext::CCC_NaturalLanguage: 20420b57cec5SDimitry Andric case CodeCompletionContext::CCC_SelectorName: 20430b57cec5SDimitry Andric case CodeCompletionContext::CCC_TypeQualifiers: 20440b57cec5SDimitry Andric case CodeCompletionContext::CCC_Other: 20450b57cec5SDimitry Andric case CodeCompletionContext::CCC_OtherWithMacros: 20460b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCInstanceMessage: 20470b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCClassMessage: 20480b57cec5SDimitry Andric case CodeCompletionContext::CCC_ObjCCategoryName: 20490b57cec5SDimitry Andric case CodeCompletionContext::CCC_IncludedFile: 2050349cc55cSDimitry Andric case CodeCompletionContext::CCC_Attribute: 20510b57cec5SDimitry Andric case CodeCompletionContext::CCC_NewName: 205206c3fb27SDimitry Andric case CodeCompletionContext::CCC_ObjCClassForwardDecl: 20530b57cec5SDimitry Andric // We're looking for nothing, or we're looking for names that cannot 20540b57cec5SDimitry Andric // be hidden. 20550b57cec5SDimitry Andric return; 20560b57cec5SDimitry Andric } 20570b57cec5SDimitry Andric 20580b57cec5SDimitry Andric using Result = CodeCompletionResult; 20590b57cec5SDimitry Andric for (unsigned I = 0; I != NumResults; ++I) { 20600b57cec5SDimitry Andric if (Results[I].Kind != Result::RK_Declaration) 20610b57cec5SDimitry Andric continue; 20620b57cec5SDimitry Andric 20630b57cec5SDimitry Andric unsigned IDNS 20640b57cec5SDimitry Andric = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace(); 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric bool Hiding = false; 20670b57cec5SDimitry Andric if (OnlyTagNames) 20680b57cec5SDimitry Andric Hiding = (IDNS & Decl::IDNS_Tag); 20690b57cec5SDimitry Andric else { 20700b57cec5SDimitry Andric unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | 20710b57cec5SDimitry Andric Decl::IDNS_Namespace | Decl::IDNS_Ordinary | 20720b57cec5SDimitry Andric Decl::IDNS_NonMemberOperator); 20730b57cec5SDimitry Andric if (Ctx.getLangOpts().CPlusPlus) 20740b57cec5SDimitry Andric HiddenIDNS |= Decl::IDNS_Tag; 20750b57cec5SDimitry Andric Hiding = (IDNS & HiddenIDNS); 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric 20780b57cec5SDimitry Andric if (!Hiding) 20790b57cec5SDimitry Andric continue; 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric DeclarationName Name = Results[I].Declaration->getDeclName(); 20820b57cec5SDimitry Andric if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo()) 20830b57cec5SDimitry Andric HiddenNames.insert(Identifier->getName()); 20840b57cec5SDimitry Andric else 20850b57cec5SDimitry Andric HiddenNames.insert(Name.getAsString()); 20860b57cec5SDimitry Andric } 20870b57cec5SDimitry Andric } 20880b57cec5SDimitry Andric 20890b57cec5SDimitry Andric void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, 20900b57cec5SDimitry Andric CodeCompletionContext Context, 20910b57cec5SDimitry Andric CodeCompletionResult *Results, 20920b57cec5SDimitry Andric unsigned NumResults) { 20930b57cec5SDimitry Andric // Merge the results we were given with the results we cached. 20940b57cec5SDimitry Andric bool AddedResult = false; 20950b57cec5SDimitry Andric uint64_t InContexts = 20960b57cec5SDimitry Andric Context.getKind() == CodeCompletionContext::CCC_Recovery 20970b57cec5SDimitry Andric ? NormalContexts : (1LL << Context.getKind()); 20980b57cec5SDimitry Andric // Contains the set of names that are hidden by "local" completion results. 20990b57cec5SDimitry Andric llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames; 21000b57cec5SDimitry Andric using Result = CodeCompletionResult; 21010b57cec5SDimitry Andric SmallVector<Result, 8> AllResults; 21020b57cec5SDimitry Andric for (ASTUnit::cached_completion_iterator 21030b57cec5SDimitry Andric C = AST.cached_completion_begin(), 21040b57cec5SDimitry Andric CEnd = AST.cached_completion_end(); 21050b57cec5SDimitry Andric C != CEnd; ++C) { 21060b57cec5SDimitry Andric // If the context we are in matches any of the contexts we are 21070b57cec5SDimitry Andric // interested in, we'll add this result. 21080b57cec5SDimitry Andric if ((C->ShowInContexts & InContexts) == 0) 21090b57cec5SDimitry Andric continue; 21100b57cec5SDimitry Andric 21110b57cec5SDimitry Andric // If we haven't added any results previously, do so now. 21120b57cec5SDimitry Andric if (!AddedResult) { 21130b57cec5SDimitry Andric CalculateHiddenNames(Context, Results, NumResults, S.Context, 21140b57cec5SDimitry Andric HiddenNames); 21150b57cec5SDimitry Andric AllResults.insert(AllResults.end(), Results, Results + NumResults); 21160b57cec5SDimitry Andric AddedResult = true; 21170b57cec5SDimitry Andric } 21180b57cec5SDimitry Andric 21190b57cec5SDimitry Andric // Determine whether this global completion result is hidden by a local 21200b57cec5SDimitry Andric // completion result. If so, skip it. 21210b57cec5SDimitry Andric if (C->Kind != CXCursor_MacroDefinition && 21220b57cec5SDimitry Andric HiddenNames.count(C->Completion->getTypedText())) 21230b57cec5SDimitry Andric continue; 21240b57cec5SDimitry Andric 21250b57cec5SDimitry Andric // Adjust priority based on similar type classes. 21260b57cec5SDimitry Andric unsigned Priority = C->Priority; 21270b57cec5SDimitry Andric CodeCompletionString *Completion = C->Completion; 21280b57cec5SDimitry Andric if (!Context.getPreferredType().isNull()) { 21290b57cec5SDimitry Andric if (C->Kind == CXCursor_MacroDefinition) { 21300b57cec5SDimitry Andric Priority = getMacroUsagePriority(C->Completion->getTypedText(), 21310b57cec5SDimitry Andric S.getLangOpts(), 21320b57cec5SDimitry Andric Context.getPreferredType()->isAnyPointerType()); 21330b57cec5SDimitry Andric } else if (C->Type) { 21340b57cec5SDimitry Andric CanQualType Expected 21350b57cec5SDimitry Andric = S.Context.getCanonicalType( 21360b57cec5SDimitry Andric Context.getPreferredType().getUnqualifiedType()); 21370b57cec5SDimitry Andric SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected); 21380b57cec5SDimitry Andric if (ExpectedSTC == C->TypeClass) { 21390b57cec5SDimitry Andric // We know this type is similar; check for an exact match. 21400b57cec5SDimitry Andric llvm::StringMap<unsigned> &CachedCompletionTypes 21410b57cec5SDimitry Andric = AST.getCachedCompletionTypes(); 21420b57cec5SDimitry Andric llvm::StringMap<unsigned>::iterator Pos 21430b57cec5SDimitry Andric = CachedCompletionTypes.find(QualType(Expected).getAsString()); 21440b57cec5SDimitry Andric if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type) 21450b57cec5SDimitry Andric Priority /= CCF_ExactTypeMatch; 21460b57cec5SDimitry Andric else 21470b57cec5SDimitry Andric Priority /= CCF_SimilarTypeMatch; 21480b57cec5SDimitry Andric } 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric } 21510b57cec5SDimitry Andric 21520b57cec5SDimitry Andric // Adjust the completion string, if required. 21530b57cec5SDimitry Andric if (C->Kind == CXCursor_MacroDefinition && 21540b57cec5SDimitry Andric Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { 21550b57cec5SDimitry Andric // Create a new code-completion string that just contains the 21560b57cec5SDimitry Andric // macro name, without its arguments. 21570b57cec5SDimitry Andric CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(), 21580b57cec5SDimitry Andric CCP_CodePattern, C->Availability); 21590b57cec5SDimitry Andric Builder.AddTypedTextChunk(C->Completion->getTypedText()); 21600b57cec5SDimitry Andric Priority = CCP_CodePattern; 21610b57cec5SDimitry Andric Completion = Builder.TakeString(); 21620b57cec5SDimitry Andric } 21630b57cec5SDimitry Andric 21640b57cec5SDimitry Andric AllResults.push_back(Result(Completion, Priority, C->Kind, 21650b57cec5SDimitry Andric C->Availability)); 21660b57cec5SDimitry Andric } 21670b57cec5SDimitry Andric 21680b57cec5SDimitry Andric // If we did not add any cached completion results, just forward the 21690b57cec5SDimitry Andric // results we were given to the next consumer. 21700b57cec5SDimitry Andric if (!AddedResult) { 21710b57cec5SDimitry Andric Next.ProcessCodeCompleteResults(S, Context, Results, NumResults); 21720b57cec5SDimitry Andric return; 21730b57cec5SDimitry Andric } 21740b57cec5SDimitry Andric 21750b57cec5SDimitry Andric Next.ProcessCodeCompleteResults(S, Context, AllResults.data(), 21760b57cec5SDimitry Andric AllResults.size()); 21770b57cec5SDimitry Andric } 21780b57cec5SDimitry Andric 21790b57cec5SDimitry Andric void ASTUnit::CodeComplete( 21800b57cec5SDimitry Andric StringRef File, unsigned Line, unsigned Column, 21810b57cec5SDimitry Andric ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros, 21820b57cec5SDimitry Andric bool IncludeCodePatterns, bool IncludeBriefComments, 21830b57cec5SDimitry Andric CodeCompleteConsumer &Consumer, 21840b57cec5SDimitry Andric std::shared_ptr<PCHContainerOperations> PCHContainerOps, 21850b57cec5SDimitry Andric DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, 21860b57cec5SDimitry Andric FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, 21875f757f3fSDimitry Andric SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers, 21885f757f3fSDimitry Andric std::unique_ptr<SyntaxOnlyAction> Act) { 21890b57cec5SDimitry Andric if (!Invocation) 21900b57cec5SDimitry Andric return; 21910b57cec5SDimitry Andric 21920b57cec5SDimitry Andric SimpleTimer CompletionTimer(WantTiming); 21930b57cec5SDimitry Andric CompletionTimer.setOutput("Code completion @ " + File + ":" + 21940b57cec5SDimitry Andric Twine(Line) + ":" + Twine(Column)); 21950b57cec5SDimitry Andric 21960b57cec5SDimitry Andric auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation); 21970b57cec5SDimitry Andric 21980b57cec5SDimitry Andric FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts(); 21990b57cec5SDimitry Andric CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts; 22000b57cec5SDimitry Andric PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts(); 22010b57cec5SDimitry Andric 22020b57cec5SDimitry Andric CodeCompleteOpts.IncludeMacros = IncludeMacros && 22030b57cec5SDimitry Andric CachedCompletionResults.empty(); 22040b57cec5SDimitry Andric CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns; 22050b57cec5SDimitry Andric CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty(); 22060b57cec5SDimitry Andric CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments; 22070b57cec5SDimitry Andric CodeCompleteOpts.LoadExternal = Consumer.loadExternal(); 22080b57cec5SDimitry Andric CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts(); 22090b57cec5SDimitry Andric 22100b57cec5SDimitry Andric assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion); 22110b57cec5SDimitry Andric 22125ffd83dbSDimitry Andric FrontendOpts.CodeCompletionAt.FileName = std::string(File); 22130b57cec5SDimitry Andric FrontendOpts.CodeCompletionAt.Line = Line; 22140b57cec5SDimitry Andric FrontendOpts.CodeCompletionAt.Column = Column; 22150b57cec5SDimitry Andric 22160b57cec5SDimitry Andric // Set the language options appropriately. 22175f757f3fSDimitry Andric LangOpts = CCInvocation->getLangOpts(); 22180b57cec5SDimitry Andric 22190b57cec5SDimitry Andric // Spell-checking and warnings are wasteful during code-completion. 22200b57cec5SDimitry Andric LangOpts.SpellChecking = false; 22210b57cec5SDimitry Andric CCInvocation->getDiagnosticOpts().IgnoreWarnings = true; 22220b57cec5SDimitry Andric 22230b57cec5SDimitry Andric std::unique_ptr<CompilerInstance> Clang( 22240b57cec5SDimitry Andric new CompilerInstance(PCHContainerOps)); 22250b57cec5SDimitry Andric 22260b57cec5SDimitry Andric // Recover resources if we crash before exiting this method. 22270b57cec5SDimitry Andric llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> 22280b57cec5SDimitry Andric CICleanup(Clang.get()); 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric auto &Inv = *CCInvocation; 22310b57cec5SDimitry Andric Clang->setInvocation(std::move(CCInvocation)); 22325ffd83dbSDimitry Andric OriginalSourceFile = 22335ffd83dbSDimitry Andric std::string(Clang->getFrontendOpts().Inputs[0].getFile()); 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric // Set up diagnostics, capturing any diagnostics produced. 22360b57cec5SDimitry Andric Clang->setDiagnostics(&Diag); 22370b57cec5SDimitry Andric CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All, 22380b57cec5SDimitry Andric Clang->getDiagnostics(), 22390b57cec5SDimitry Andric &StoredDiagnostics, nullptr); 22400b57cec5SDimitry Andric ProcessWarningOptions(Diag, Inv.getDiagnosticOpts()); 22410b57cec5SDimitry Andric 22420b57cec5SDimitry Andric // Create the target instance. 2243fe6060f1SDimitry Andric if (!Clang->createTarget()) { 22440b57cec5SDimitry Andric Clang->setInvocation(nullptr); 22450b57cec5SDimitry Andric return; 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric 22480b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs.size() == 1 && 22490b57cec5SDimitry Andric "Invocation must have exactly one source file!"); 22500b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == 22510b57cec5SDimitry Andric InputKind::Source && 22520b57cec5SDimitry Andric "FIXME: AST inputs not yet supported here!"); 22530b57cec5SDimitry Andric assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != 2254a7dea167SDimitry Andric Language::LLVM_IR && 22550b57cec5SDimitry Andric "IR inputs not support here!"); 22560b57cec5SDimitry Andric 22570b57cec5SDimitry Andric // Use the source and file managers that we were given. 22580b57cec5SDimitry Andric Clang->setFileManager(&FileMgr); 22590b57cec5SDimitry Andric Clang->setSourceManager(&SourceMgr); 22600b57cec5SDimitry Andric 22610b57cec5SDimitry Andric // Remap files. 22620b57cec5SDimitry Andric PreprocessorOpts.clearRemappedFiles(); 22630b57cec5SDimitry Andric PreprocessorOpts.RetainRemappedFileBuffers = true; 22640b57cec5SDimitry Andric for (const auto &RemappedFile : RemappedFiles) { 22650b57cec5SDimitry Andric PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second); 22660b57cec5SDimitry Andric OwnedBuffers.push_back(RemappedFile.second); 22670b57cec5SDimitry Andric } 22680b57cec5SDimitry Andric 22690b57cec5SDimitry Andric // Use the code completion consumer we were given, but adding any cached 22700b57cec5SDimitry Andric // code-completion results. 22710b57cec5SDimitry Andric AugmentedCodeCompleteConsumer *AugmentedConsumer 22720b57cec5SDimitry Andric = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts); 22730b57cec5SDimitry Andric Clang->setCodeCompletionConsumer(AugmentedConsumer); 22740b57cec5SDimitry Andric 2275e8d8bef9SDimitry Andric auto getUniqueID = 2276bdd1243dSDimitry Andric [&FileMgr](StringRef Filename) -> std::optional<llvm::sys::fs::UniqueID> { 2277e8d8bef9SDimitry Andric if (auto Status = FileMgr.getVirtualFileSystem().status(Filename)) 2278e8d8bef9SDimitry Andric return Status->getUniqueID(); 2279bdd1243dSDimitry Andric return std::nullopt; 2280e8d8bef9SDimitry Andric }; 2281e8d8bef9SDimitry Andric 2282e8d8bef9SDimitry Andric auto hasSameUniqueID = [getUniqueID](StringRef LHS, StringRef RHS) { 2283e8d8bef9SDimitry Andric if (LHS == RHS) 2284e8d8bef9SDimitry Andric return true; 2285e8d8bef9SDimitry Andric if (auto LHSID = getUniqueID(LHS)) 2286e8d8bef9SDimitry Andric if (auto RHSID = getUniqueID(RHS)) 2287e8d8bef9SDimitry Andric return *LHSID == *RHSID; 2288e8d8bef9SDimitry Andric return false; 2289e8d8bef9SDimitry Andric }; 2290e8d8bef9SDimitry Andric 22910b57cec5SDimitry Andric // If we have a precompiled preamble, try to use it. We only allow 22920b57cec5SDimitry Andric // the use of the precompiled preamble if we're if the completion 22930b57cec5SDimitry Andric // point is within the main file, after the end of the precompiled 22940b57cec5SDimitry Andric // preamble. 22950b57cec5SDimitry Andric std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; 2296e8d8bef9SDimitry Andric if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) { 22970b57cec5SDimitry Andric OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( 2298e8d8bef9SDimitry Andric PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1); 22990b57cec5SDimitry Andric } 23000b57cec5SDimitry Andric 23010b57cec5SDimitry Andric // If the main file has been overridden due to the use of a preamble, 23020b57cec5SDimitry Andric // make that override happen and introduce the preamble. 23030b57cec5SDimitry Andric if (OverrideMainBuffer) { 23040b57cec5SDimitry Andric assert(Preamble && 23050b57cec5SDimitry Andric "No preamble was built, but OverrideMainBuffer is not null"); 23060b57cec5SDimitry Andric 23070b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = 23080b57cec5SDimitry Andric &FileMgr.getVirtualFileSystem(); 23090b57cec5SDimitry Andric Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS, 23100b57cec5SDimitry Andric OverrideMainBuffer.get()); 23110b57cec5SDimitry Andric // FIXME: there is no way to update VFS if it was changed by 23120b57cec5SDimitry Andric // AddImplicitPreamble as FileMgr is accepted as a parameter by this method. 23130b57cec5SDimitry Andric // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the 23140b57cec5SDimitry Andric // PCH files are always readable. 23150b57cec5SDimitry Andric OwnedBuffers.push_back(OverrideMainBuffer.release()); 23160b57cec5SDimitry Andric } else { 23170b57cec5SDimitry Andric PreprocessorOpts.PrecompiledPreambleBytes.first = 0; 23180b57cec5SDimitry Andric PreprocessorOpts.PrecompiledPreambleBytes.second = false; 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric // Disable the preprocessing record if modules are not enabled. 23220b57cec5SDimitry Andric if (!Clang->getLangOpts().Modules) 23230b57cec5SDimitry Andric PreprocessorOpts.DetailedRecord = false; 23240b57cec5SDimitry Andric 23255f757f3fSDimitry Andric if (!Act) 23260b57cec5SDimitry Andric Act.reset(new SyntaxOnlyAction); 23275f757f3fSDimitry Andric 23280b57cec5SDimitry Andric if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { 23290b57cec5SDimitry Andric if (llvm::Error Err = Act->Execute()) { 23300b57cec5SDimitry Andric consumeError(std::move(Err)); // FIXME this drops errors on the floor. 23310b57cec5SDimitry Andric } 23320b57cec5SDimitry Andric Act->EndSourceFile(); 23330b57cec5SDimitry Andric } 23340b57cec5SDimitry Andric } 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric bool ASTUnit::Save(StringRef File) { 23370b57cec5SDimitry Andric if (HadModuleLoaderFatalFailure) 23380b57cec5SDimitry Andric return true; 23390b57cec5SDimitry Andric 23400b57cec5SDimitry Andric // FIXME: Can we somehow regenerate the stat cache here, or do we need to 23410b57cec5SDimitry Andric // unconditionally create a stat cache when we parse the file? 23420b57cec5SDimitry Andric 234306c3fb27SDimitry Andric if (llvm::Error Err = llvm::writeToOutput( 234406c3fb27SDimitry Andric File, [this](llvm::raw_ostream &Out) { 2345a7dea167SDimitry Andric return serialize(Out) ? llvm::make_error<llvm::StringError>( 2346a7dea167SDimitry Andric "ASTUnit serialization failed", 2347a7dea167SDimitry Andric llvm::inconvertibleErrorCode()) 2348a7dea167SDimitry Andric : llvm::Error::success(); 2349a7dea167SDimitry Andric })) { 2350a7dea167SDimitry Andric consumeError(std::move(Err)); 23510b57cec5SDimitry Andric return true; 23520b57cec5SDimitry Andric } 23530b57cec5SDimitry Andric return false; 23540b57cec5SDimitry Andric } 23550b57cec5SDimitry Andric 23565f757f3fSDimitry Andric static bool serializeUnit(ASTWriter &Writer, SmallVectorImpl<char> &Buffer, 23575f757f3fSDimitry Andric Sema &S, raw_ostream &OS) { 23585f757f3fSDimitry Andric Writer.WriteAST(S, std::string(), nullptr, ""); 23590b57cec5SDimitry Andric 23600b57cec5SDimitry Andric // Write the generated bitstream to "Out". 23610b57cec5SDimitry Andric if (!Buffer.empty()) 23620b57cec5SDimitry Andric OS.write(Buffer.data(), Buffer.size()); 23630b57cec5SDimitry Andric 23640b57cec5SDimitry Andric return false; 23650b57cec5SDimitry Andric } 23660b57cec5SDimitry Andric 23670b57cec5SDimitry Andric bool ASTUnit::serialize(raw_ostream &OS) { 23680b57cec5SDimitry Andric if (WriterData) 23695f757f3fSDimitry Andric return serializeUnit(WriterData->Writer, WriterData->Buffer, getSema(), OS); 23700b57cec5SDimitry Andric 23710b57cec5SDimitry Andric SmallString<128> Buffer; 23720b57cec5SDimitry Andric llvm::BitstreamWriter Stream(Buffer); 23730b57cec5SDimitry Andric InMemoryModuleCache ModuleCache; 23740b57cec5SDimitry Andric ASTWriter Writer(Stream, Buffer, ModuleCache, {}); 23755f757f3fSDimitry Andric return serializeUnit(Writer, Buffer, getSema(), OS); 23760b57cec5SDimitry Andric } 23770b57cec5SDimitry Andric 23780b57cec5SDimitry Andric void ASTUnit::TranslateStoredDiagnostics( 23790b57cec5SDimitry Andric FileManager &FileMgr, 23800b57cec5SDimitry Andric SourceManager &SrcMgr, 23810b57cec5SDimitry Andric const SmallVectorImpl<StandaloneDiagnostic> &Diags, 23820b57cec5SDimitry Andric SmallVectorImpl<StoredDiagnostic> &Out) { 23830b57cec5SDimitry Andric // Map the standalone diagnostic into the new source manager. We also need to 23840b57cec5SDimitry Andric // remap all the locations to the new view. This includes the diag location, 23850b57cec5SDimitry Andric // any associated source ranges, and the source ranges of associated fix-its. 23860b57cec5SDimitry Andric // FIXME: There should be a cleaner way to do this. 23870b57cec5SDimitry Andric SmallVector<StoredDiagnostic, 4> Result; 23880b57cec5SDimitry Andric Result.reserve(Diags.size()); 23890b57cec5SDimitry Andric 23900b57cec5SDimitry Andric for (const auto &SD : Diags) { 23910b57cec5SDimitry Andric // Rebuild the StoredDiagnostic. 23920b57cec5SDimitry Andric if (SD.Filename.empty()) 23930b57cec5SDimitry Andric continue; 2394a7dea167SDimitry Andric auto FE = FileMgr.getFile(SD.Filename); 23950b57cec5SDimitry Andric if (!FE) 23960b57cec5SDimitry Andric continue; 23970b57cec5SDimitry Andric SourceLocation FileLoc; 23980b57cec5SDimitry Andric auto ItFileID = PreambleSrcLocCache.find(SD.Filename); 23990b57cec5SDimitry Andric if (ItFileID == PreambleSrcLocCache.end()) { 2400a7dea167SDimitry Andric FileID FID = SrcMgr.translateFile(*FE); 24010b57cec5SDimitry Andric FileLoc = SrcMgr.getLocForStartOfFile(FID); 24020b57cec5SDimitry Andric PreambleSrcLocCache[SD.Filename] = FileLoc; 24030b57cec5SDimitry Andric } else { 24040b57cec5SDimitry Andric FileLoc = ItFileID->getValue(); 24050b57cec5SDimitry Andric } 24060b57cec5SDimitry Andric 24070b57cec5SDimitry Andric if (FileLoc.isInvalid()) 24080b57cec5SDimitry Andric continue; 24090b57cec5SDimitry Andric SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset); 24100b57cec5SDimitry Andric FullSourceLoc Loc(L, SrcMgr); 24110b57cec5SDimitry Andric 24120b57cec5SDimitry Andric SmallVector<CharSourceRange, 4> Ranges; 24130b57cec5SDimitry Andric Ranges.reserve(SD.Ranges.size()); 24140b57cec5SDimitry Andric for (const auto &Range : SD.Ranges) { 24150b57cec5SDimitry Andric SourceLocation BL = FileLoc.getLocWithOffset(Range.first); 24160b57cec5SDimitry Andric SourceLocation EL = FileLoc.getLocWithOffset(Range.second); 24170b57cec5SDimitry Andric Ranges.push_back(CharSourceRange::getCharRange(BL, EL)); 24180b57cec5SDimitry Andric } 24190b57cec5SDimitry Andric 24200b57cec5SDimitry Andric SmallVector<FixItHint, 2> FixIts; 24210b57cec5SDimitry Andric FixIts.reserve(SD.FixIts.size()); 24220b57cec5SDimitry Andric for (const auto &FixIt : SD.FixIts) { 24230b57cec5SDimitry Andric FixIts.push_back(FixItHint()); 24240b57cec5SDimitry Andric FixItHint &FH = FixIts.back(); 24250b57cec5SDimitry Andric FH.CodeToInsert = FixIt.CodeToInsert; 24260b57cec5SDimitry Andric SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first); 24270b57cec5SDimitry Andric SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second); 24280b57cec5SDimitry Andric FH.RemoveRange = CharSourceRange::getCharRange(BL, EL); 24290b57cec5SDimitry Andric } 24300b57cec5SDimitry Andric 24310b57cec5SDimitry Andric Result.push_back(StoredDiagnostic(SD.Level, SD.ID, 24320b57cec5SDimitry Andric SD.Message, Loc, Ranges, FixIts)); 24330b57cec5SDimitry Andric } 24340b57cec5SDimitry Andric Result.swap(Out); 24350b57cec5SDimitry Andric } 24360b57cec5SDimitry Andric 24370b57cec5SDimitry Andric void ASTUnit::addFileLevelDecl(Decl *D) { 24380b57cec5SDimitry Andric assert(D); 24390b57cec5SDimitry Andric 24400b57cec5SDimitry Andric // We only care about local declarations. 24410b57cec5SDimitry Andric if (D->isFromASTFile()) 24420b57cec5SDimitry Andric return; 24430b57cec5SDimitry Andric 24440b57cec5SDimitry Andric SourceManager &SM = *SourceMgr; 24450b57cec5SDimitry Andric SourceLocation Loc = D->getLocation(); 24460b57cec5SDimitry Andric if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc)) 24470b57cec5SDimitry Andric return; 24480b57cec5SDimitry Andric 24490b57cec5SDimitry Andric // We only keep track of the file-level declarations of each file. 24500b57cec5SDimitry Andric if (!D->getLexicalDeclContext()->isFileContext()) 24510b57cec5SDimitry Andric return; 24520b57cec5SDimitry Andric 24530b57cec5SDimitry Andric SourceLocation FileLoc = SM.getFileLoc(Loc); 24540b57cec5SDimitry Andric assert(SM.isLocalSourceLocation(FileLoc)); 24550b57cec5SDimitry Andric FileID FID; 24560b57cec5SDimitry Andric unsigned Offset; 24570b57cec5SDimitry Andric std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); 24580b57cec5SDimitry Andric if (FID.isInvalid()) 24590b57cec5SDimitry Andric return; 24600b57cec5SDimitry Andric 24615ffd83dbSDimitry Andric std::unique_ptr<LocDeclsTy> &Decls = FileDecls[FID]; 24620b57cec5SDimitry Andric if (!Decls) 24635ffd83dbSDimitry Andric Decls = std::make_unique<LocDeclsTy>(); 24640b57cec5SDimitry Andric 24650b57cec5SDimitry Andric std::pair<unsigned, Decl *> LocDecl(Offset, D); 24660b57cec5SDimitry Andric 24670b57cec5SDimitry Andric if (Decls->empty() || Decls->back().first <= Offset) { 24680b57cec5SDimitry Andric Decls->push_back(LocDecl); 24690b57cec5SDimitry Andric return; 24700b57cec5SDimitry Andric } 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric LocDeclsTy::iterator I = 24730b57cec5SDimitry Andric llvm::upper_bound(*Decls, LocDecl, llvm::less_first()); 24740b57cec5SDimitry Andric 24750b57cec5SDimitry Andric Decls->insert(I, LocDecl); 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric 24780b57cec5SDimitry Andric void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, 24790b57cec5SDimitry Andric SmallVectorImpl<Decl *> &Decls) { 24800b57cec5SDimitry Andric if (File.isInvalid()) 24810b57cec5SDimitry Andric return; 24820b57cec5SDimitry Andric 24830b57cec5SDimitry Andric if (SourceMgr->isLoadedFileID(File)) { 24840b57cec5SDimitry Andric assert(Ctx->getExternalSource() && "No external source!"); 24850b57cec5SDimitry Andric return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length, 24860b57cec5SDimitry Andric Decls); 24870b57cec5SDimitry Andric } 24880b57cec5SDimitry Andric 24890b57cec5SDimitry Andric FileDeclsTy::iterator I = FileDecls.find(File); 24900b57cec5SDimitry Andric if (I == FileDecls.end()) 24910b57cec5SDimitry Andric return; 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric LocDeclsTy &LocDecls = *I->second; 24940b57cec5SDimitry Andric if (LocDecls.empty()) 24950b57cec5SDimitry Andric return; 24960b57cec5SDimitry Andric 24970b57cec5SDimitry Andric LocDeclsTy::iterator BeginIt = 24980b57cec5SDimitry Andric llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) { 24990b57cec5SDimitry Andric return LD.first < Offset; 25000b57cec5SDimitry Andric }); 25010b57cec5SDimitry Andric if (BeginIt != LocDecls.begin()) 25020b57cec5SDimitry Andric --BeginIt; 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // If we are pointing at a top-level decl inside an objc container, we need 25050b57cec5SDimitry Andric // to backtrack until we find it otherwise we will fail to report that the 25060b57cec5SDimitry Andric // region overlaps with an objc container. 25070b57cec5SDimitry Andric while (BeginIt != LocDecls.begin() && 25080b57cec5SDimitry Andric BeginIt->second->isTopLevelDeclInObjCContainer()) 25090b57cec5SDimitry Andric --BeginIt; 25100b57cec5SDimitry Andric 25110b57cec5SDimitry Andric LocDeclsTy::iterator EndIt = llvm::upper_bound( 25120b57cec5SDimitry Andric LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr), 25130b57cec5SDimitry Andric llvm::less_first()); 25140b57cec5SDimitry Andric if (EndIt != LocDecls.end()) 25150b57cec5SDimitry Andric ++EndIt; 25160b57cec5SDimitry Andric 25170b57cec5SDimitry Andric for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt) 25180b57cec5SDimitry Andric Decls.push_back(DIt->second); 25190b57cec5SDimitry Andric } 25200b57cec5SDimitry Andric 25210b57cec5SDimitry Andric SourceLocation ASTUnit::getLocation(const FileEntry *File, 25220b57cec5SDimitry Andric unsigned Line, unsigned Col) const { 25230b57cec5SDimitry Andric const SourceManager &SM = getSourceManager(); 25240b57cec5SDimitry Andric SourceLocation Loc = SM.translateFileLineCol(File, Line, Col); 25250b57cec5SDimitry Andric return SM.getMacroArgExpandedLocation(Loc); 25260b57cec5SDimitry Andric } 25270b57cec5SDimitry Andric 25280b57cec5SDimitry Andric SourceLocation ASTUnit::getLocation(const FileEntry *File, 25290b57cec5SDimitry Andric unsigned Offset) const { 25300b57cec5SDimitry Andric const SourceManager &SM = getSourceManager(); 25310b57cec5SDimitry Andric SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1); 25320b57cec5SDimitry Andric return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset)); 25330b57cec5SDimitry Andric } 25340b57cec5SDimitry Andric 25350b57cec5SDimitry Andric /// If \arg Loc is a loaded location from the preamble, returns 25360b57cec5SDimitry Andric /// the corresponding local location of the main file, otherwise it returns 25370b57cec5SDimitry Andric /// \arg Loc. 25380b57cec5SDimitry Andric SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const { 25390b57cec5SDimitry Andric FileID PreambleID; 25400b57cec5SDimitry Andric if (SourceMgr) 25410b57cec5SDimitry Andric PreambleID = SourceMgr->getPreambleFileID(); 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid()) 25440b57cec5SDimitry Andric return Loc; 25450b57cec5SDimitry Andric 25460b57cec5SDimitry Andric unsigned Offs; 25470b57cec5SDimitry Andric if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) { 25480b57cec5SDimitry Andric SourceLocation FileLoc 25490b57cec5SDimitry Andric = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID()); 25500b57cec5SDimitry Andric return FileLoc.getLocWithOffset(Offs); 25510b57cec5SDimitry Andric } 25520b57cec5SDimitry Andric 25530b57cec5SDimitry Andric return Loc; 25540b57cec5SDimitry Andric } 25550b57cec5SDimitry Andric 25560b57cec5SDimitry Andric /// If \arg Loc is a local location of the main file but inside the 25570b57cec5SDimitry Andric /// preamble chunk, returns the corresponding loaded location from the 25580b57cec5SDimitry Andric /// preamble, otherwise it returns \arg Loc. 25590b57cec5SDimitry Andric SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const { 25600b57cec5SDimitry Andric FileID PreambleID; 25610b57cec5SDimitry Andric if (SourceMgr) 25620b57cec5SDimitry Andric PreambleID = SourceMgr->getPreambleFileID(); 25630b57cec5SDimitry Andric 25640b57cec5SDimitry Andric if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid()) 25650b57cec5SDimitry Andric return Loc; 25660b57cec5SDimitry Andric 25670b57cec5SDimitry Andric unsigned Offs; 25680b57cec5SDimitry Andric if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) && 25690b57cec5SDimitry Andric Offs < Preamble->getBounds().Size) { 25700b57cec5SDimitry Andric SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID); 25710b57cec5SDimitry Andric return FileLoc.getLocWithOffset(Offs); 25720b57cec5SDimitry Andric } 25730b57cec5SDimitry Andric 25740b57cec5SDimitry Andric return Loc; 25750b57cec5SDimitry Andric } 25760b57cec5SDimitry Andric 25770b57cec5SDimitry Andric bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const { 25780b57cec5SDimitry Andric FileID FID; 25790b57cec5SDimitry Andric if (SourceMgr) 25800b57cec5SDimitry Andric FID = SourceMgr->getPreambleFileID(); 25810b57cec5SDimitry Andric 25820b57cec5SDimitry Andric if (Loc.isInvalid() || FID.isInvalid()) 25830b57cec5SDimitry Andric return false; 25840b57cec5SDimitry Andric 25850b57cec5SDimitry Andric return SourceMgr->isInFileID(Loc, FID); 25860b57cec5SDimitry Andric } 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric bool ASTUnit::isInMainFileID(SourceLocation Loc) const { 25890b57cec5SDimitry Andric FileID FID; 25900b57cec5SDimitry Andric if (SourceMgr) 25910b57cec5SDimitry Andric FID = SourceMgr->getMainFileID(); 25920b57cec5SDimitry Andric 25930b57cec5SDimitry Andric if (Loc.isInvalid() || FID.isInvalid()) 25940b57cec5SDimitry Andric return false; 25950b57cec5SDimitry Andric 25960b57cec5SDimitry Andric return SourceMgr->isInFileID(Loc, FID); 25970b57cec5SDimitry Andric } 25980b57cec5SDimitry Andric 25990b57cec5SDimitry Andric SourceLocation ASTUnit::getEndOfPreambleFileID() const { 26000b57cec5SDimitry Andric FileID FID; 26010b57cec5SDimitry Andric if (SourceMgr) 26020b57cec5SDimitry Andric FID = SourceMgr->getPreambleFileID(); 26030b57cec5SDimitry Andric 26040b57cec5SDimitry Andric if (FID.isInvalid()) 26050b57cec5SDimitry Andric return {}; 26060b57cec5SDimitry Andric 26070b57cec5SDimitry Andric return SourceMgr->getLocForEndOfFile(FID); 26080b57cec5SDimitry Andric } 26090b57cec5SDimitry Andric 26100b57cec5SDimitry Andric SourceLocation ASTUnit::getStartOfMainFileID() const { 26110b57cec5SDimitry Andric FileID FID; 26120b57cec5SDimitry Andric if (SourceMgr) 26130b57cec5SDimitry Andric FID = SourceMgr->getMainFileID(); 26140b57cec5SDimitry Andric 26150b57cec5SDimitry Andric if (FID.isInvalid()) 26160b57cec5SDimitry Andric return {}; 26170b57cec5SDimitry Andric 26180b57cec5SDimitry Andric return SourceMgr->getLocForStartOfFile(FID); 26190b57cec5SDimitry Andric } 26200b57cec5SDimitry Andric 26210b57cec5SDimitry Andric llvm::iterator_range<PreprocessingRecord::iterator> 26220b57cec5SDimitry Andric ASTUnit::getLocalPreprocessingEntities() const { 26230b57cec5SDimitry Andric if (isMainFileAST()) { 26240b57cec5SDimitry Andric serialization::ModuleFile & 26250b57cec5SDimitry Andric Mod = Reader->getModuleManager().getPrimaryModule(); 26260b57cec5SDimitry Andric return Reader->getModulePreprocessedEntities(Mod); 26270b57cec5SDimitry Andric } 26280b57cec5SDimitry Andric 26290b57cec5SDimitry Andric if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord()) 26300b57cec5SDimitry Andric return llvm::make_range(PPRec->local_begin(), PPRec->local_end()); 26310b57cec5SDimitry Andric 26320b57cec5SDimitry Andric return llvm::make_range(PreprocessingRecord::iterator(), 26330b57cec5SDimitry Andric PreprocessingRecord::iterator()); 26340b57cec5SDimitry Andric } 26350b57cec5SDimitry Andric 26360b57cec5SDimitry Andric bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) { 26370b57cec5SDimitry Andric if (isMainFileAST()) { 26380b57cec5SDimitry Andric serialization::ModuleFile & 26390b57cec5SDimitry Andric Mod = Reader->getModuleManager().getPrimaryModule(); 26400b57cec5SDimitry Andric for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) { 26410b57cec5SDimitry Andric if (!Fn(context, D)) 26420b57cec5SDimitry Andric return false; 26430b57cec5SDimitry Andric } 26440b57cec5SDimitry Andric 26450b57cec5SDimitry Andric return true; 26460b57cec5SDimitry Andric } 26470b57cec5SDimitry Andric 26480b57cec5SDimitry Andric for (ASTUnit::top_level_iterator TL = top_level_begin(), 26490b57cec5SDimitry Andric TLEnd = top_level_end(); 26500b57cec5SDimitry Andric TL != TLEnd; ++TL) { 26510b57cec5SDimitry Andric if (!Fn(context, *TL)) 26520b57cec5SDimitry Andric return false; 26530b57cec5SDimitry Andric } 26540b57cec5SDimitry Andric 26550b57cec5SDimitry Andric return true; 26560b57cec5SDimitry Andric } 26570b57cec5SDimitry Andric 265806c3fb27SDimitry Andric OptionalFileEntryRef ASTUnit::getPCHFile() { 26590b57cec5SDimitry Andric if (!Reader) 266006c3fb27SDimitry Andric return std::nullopt; 26610b57cec5SDimitry Andric 26620b57cec5SDimitry Andric serialization::ModuleFile *Mod = nullptr; 26630b57cec5SDimitry Andric Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) { 26640b57cec5SDimitry Andric switch (M.Kind) { 26650b57cec5SDimitry Andric case serialization::MK_ImplicitModule: 26660b57cec5SDimitry Andric case serialization::MK_ExplicitModule: 26670b57cec5SDimitry Andric case serialization::MK_PrebuiltModule: 26680b57cec5SDimitry Andric return true; // skip dependencies. 26690b57cec5SDimitry Andric case serialization::MK_PCH: 26700b57cec5SDimitry Andric Mod = &M; 26710b57cec5SDimitry Andric return true; // found it. 26720b57cec5SDimitry Andric case serialization::MK_Preamble: 26730b57cec5SDimitry Andric return false; // look in dependencies. 26740b57cec5SDimitry Andric case serialization::MK_MainFile: 26750b57cec5SDimitry Andric return false; // look in dependencies. 26760b57cec5SDimitry Andric } 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric return true; 26790b57cec5SDimitry Andric }); 26800b57cec5SDimitry Andric if (Mod) 26810b57cec5SDimitry Andric return Mod->File; 26820b57cec5SDimitry Andric 268306c3fb27SDimitry Andric return std::nullopt; 26840b57cec5SDimitry Andric } 26850b57cec5SDimitry Andric 26860b57cec5SDimitry Andric bool ASTUnit::isModuleFile() const { 26870b57cec5SDimitry Andric return isMainFileAST() && getLangOpts().isCompilingModule(); 26880b57cec5SDimitry Andric } 26890b57cec5SDimitry Andric 26900b57cec5SDimitry Andric InputKind ASTUnit::getInputKind() const { 26910b57cec5SDimitry Andric auto &LangOpts = getLangOpts(); 26920b57cec5SDimitry Andric 2693a7dea167SDimitry Andric Language Lang; 26940b57cec5SDimitry Andric if (LangOpts.OpenCL) 2695a7dea167SDimitry Andric Lang = Language::OpenCL; 26960b57cec5SDimitry Andric else if (LangOpts.CUDA) 2697a7dea167SDimitry Andric Lang = Language::CUDA; 26980b57cec5SDimitry Andric else if (LangOpts.RenderScript) 2699a7dea167SDimitry Andric Lang = Language::RenderScript; 27000b57cec5SDimitry Andric else if (LangOpts.CPlusPlus) 2701a7dea167SDimitry Andric Lang = LangOpts.ObjC ? Language::ObjCXX : Language::CXX; 27020b57cec5SDimitry Andric else 2703a7dea167SDimitry Andric Lang = LangOpts.ObjC ? Language::ObjC : Language::C; 27040b57cec5SDimitry Andric 27050b57cec5SDimitry Andric InputKind::Format Fmt = InputKind::Source; 27060b57cec5SDimitry Andric if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap) 27070b57cec5SDimitry Andric Fmt = InputKind::ModuleMap; 27080b57cec5SDimitry Andric 27090b57cec5SDimitry Andric // We don't know if input was preprocessed. Assume not. 27100b57cec5SDimitry Andric bool PP = false; 27110b57cec5SDimitry Andric 27120b57cec5SDimitry Andric return InputKind(Lang, Fmt, PP); 27130b57cec5SDimitry Andric } 27140b57cec5SDimitry Andric 27150b57cec5SDimitry Andric #ifndef NDEBUG 27160b57cec5SDimitry Andric ASTUnit::ConcurrencyState::ConcurrencyState() { 2717a7dea167SDimitry Andric Mutex = new std::recursive_mutex; 27180b57cec5SDimitry Andric } 27190b57cec5SDimitry Andric 27200b57cec5SDimitry Andric ASTUnit::ConcurrencyState::~ConcurrencyState() { 2721a7dea167SDimitry Andric delete static_cast<std::recursive_mutex *>(Mutex); 27220b57cec5SDimitry Andric } 27230b57cec5SDimitry Andric 27240b57cec5SDimitry Andric void ASTUnit::ConcurrencyState::start() { 2725a7dea167SDimitry Andric bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock(); 27260b57cec5SDimitry Andric assert(acquired && "Concurrent access to ASTUnit!"); 27270b57cec5SDimitry Andric } 27280b57cec5SDimitry Andric 27290b57cec5SDimitry Andric void ASTUnit::ConcurrencyState::finish() { 2730a7dea167SDimitry Andric static_cast<std::recursive_mutex *>(Mutex)->unlock(); 27310b57cec5SDimitry Andric } 27320b57cec5SDimitry Andric 27330b57cec5SDimitry Andric #else // NDEBUG 27340b57cec5SDimitry Andric 27350b57cec5SDimitry Andric ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; } 27360b57cec5SDimitry Andric ASTUnit::ConcurrencyState::~ConcurrencyState() {} 27370b57cec5SDimitry Andric void ASTUnit::ConcurrencyState::start() {} 27380b57cec5SDimitry Andric void ASTUnit::ConcurrencyState::finish() {} 27390b57cec5SDimitry Andric 27400b57cec5SDimitry Andric #endif // NDEBUG 2741