xref: /freebsd-src/contrib/llvm-project/clang/lib/Frontend/ASTUnit.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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