14f233181SEugene Zelenko //===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//
23a08ec16SArgyrios Kyrtzidis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63a08ec16SArgyrios Kyrtzidis //
73a08ec16SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
83a08ec16SArgyrios Kyrtzidis //
93a08ec16SArgyrios Kyrtzidis // ASTUnit Implementation.
103a08ec16SArgyrios Kyrtzidis //
113a08ec16SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
123a08ec16SArgyrios Kyrtzidis 
13ce379752SArgyrios Kyrtzidis #include "clang/Frontend/ASTUnit.h"
14764c0820SDaniel Dunbar #include "clang/AST/ASTConsumer.h"
153a02247dSChandler Carruth #include "clang/AST/ASTContext.h"
164f233181SEugene Zelenko #include "clang/AST/CommentCommandTraits.h"
174f233181SEugene Zelenko #include "clang/AST/Decl.h"
184f233181SEugene Zelenko #include "clang/AST/DeclBase.h"
194f233181SEugene Zelenko #include "clang/AST/DeclCXX.h"
204f233181SEugene Zelenko #include "clang/AST/DeclGroup.h"
214f233181SEugene Zelenko #include "clang/AST/DeclObjC.h"
224f233181SEugene Zelenko #include "clang/AST/DeclTemplate.h"
234f233181SEugene Zelenko #include "clang/AST/DeclarationName.h"
244f233181SEugene Zelenko #include "clang/AST/ExternalASTSource.h"
254f233181SEugene Zelenko #include "clang/AST/PrettyPrinter.h"
264f233181SEugene Zelenko #include "clang/AST/Type.h"
273a02247dSChandler Carruth #include "clang/AST/TypeOrdering.h"
283a02247dSChandler Carruth #include "clang/Basic/Diagnostic.h"
294f233181SEugene Zelenko #include "clang/Basic/FileManager.h"
304f233181SEugene Zelenko #include "clang/Basic/IdentifierTable.h"
314f233181SEugene Zelenko #include "clang/Basic/LLVM.h"
324f233181SEugene Zelenko #include "clang/Basic/LangOptions.h"
3309d890d7SRainer Orth #include "clang/Basic/LangStandard.h"
344f233181SEugene Zelenko #include "clang/Basic/Module.h"
354f233181SEugene Zelenko #include "clang/Basic/SourceLocation.h"
364f233181SEugene Zelenko #include "clang/Basic/SourceManager.h"
373a02247dSChandler Carruth #include "clang/Basic/TargetInfo.h"
383a02247dSChandler Carruth #include "clang/Basic/TargetOptions.h"
39764c0820SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h"
404f233181SEugene Zelenko #include "clang/Frontend/CompilerInvocation.h"
414f233181SEugene Zelenko #include "clang/Frontend/FrontendAction.h"
42764c0820SDaniel Dunbar #include "clang/Frontend/FrontendActions.h"
4355a17b66SDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h"
44764c0820SDaniel Dunbar #include "clang/Frontend/FrontendOptions.h"
45b11f5a4cSArgyrios Kyrtzidis #include "clang/Frontend/MultiplexConsumer.h"
464f233181SEugene Zelenko #include "clang/Frontend/PrecompiledPreamble.h"
4736e3b5c7SDouglas Gregor #include "clang/Frontend/Utils.h"
48ce379752SArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
494f233181SEugene Zelenko #include "clang/Lex/HeaderSearchOptions.h"
504f233181SEugene Zelenko #include "clang/Lex/Lexer.h"
514f233181SEugene Zelenko #include "clang/Lex/PPCallbacks.h"
524f233181SEugene Zelenko #include "clang/Lex/PreprocessingRecord.h"
53ce379752SArgyrios Kyrtzidis #include "clang/Lex/Preprocessor.h"
541452ff15SDouglas Gregor #include "clang/Lex/PreprocessorOptions.h"
554f233181SEugene Zelenko #include "clang/Lex/Token.h"
564f233181SEugene Zelenko #include "clang/Sema/CodeCompleteConsumer.h"
574f233181SEugene Zelenko #include "clang/Sema/CodeCompleteOptions.h"
580a4e61f8SDavid Blaikie #include "clang/Sema/Sema.h"
594f233181SEugene Zelenko #include "clang/Serialization/ASTBitCodes.h"
603a02247dSChandler Carruth #include "clang/Serialization/ASTReader.h"
613a02247dSChandler Carruth #include "clang/Serialization/ASTWriter.h"
624f233181SEugene Zelenko #include "clang/Serialization/ContinuousRangeMap.h"
638bef5cd4SDuncan P. N. Exon Smith #include "clang/Serialization/InMemoryModuleCache.h"
64f7170d17SDuncan P. N. Exon Smith #include "clang/Serialization/ModuleFile.h"
65f3b0046bSRichard Trieu #include "clang/Serialization/PCHContainerOperations.h"
66ce6c42f6SChris Lattner #include "llvm/ADT/ArrayRef.h"
674f233181SEugene Zelenko #include "llvm/ADT/DenseMap.h"
684f233181SEugene Zelenko #include "llvm/ADT/IntrusiveRefCntPtr.h"
694f233181SEugene Zelenko #include "llvm/ADT/None.h"
704f233181SEugene Zelenko #include "llvm/ADT/Optional.h"
714f233181SEugene Zelenko #include "llvm/ADT/STLExtras.h"
72fd14a1f6SLemonBoy #include "llvm/ADT/ScopeExit.h"
734f233181SEugene Zelenko #include "llvm/ADT/SmallString.h"
744f233181SEugene Zelenko #include "llvm/ADT/SmallVector.h"
754f233181SEugene Zelenko #include "llvm/ADT/StringMap.h"
764f233181SEugene Zelenko #include "llvm/ADT/StringRef.h"
7740a5a7deSDouglas Gregor #include "llvm/ADT/StringSet.h"
784f233181SEugene Zelenko #include "llvm/ADT/Twine.h"
794f233181SEugene Zelenko #include "llvm/ADT/iterator_range.h"
80e0308279SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitstreamWriter.h"
814f233181SEugene Zelenko #include "llvm/Support/Allocator.h"
824f233181SEugene Zelenko #include "llvm/Support/Casting.h"
833a02247dSChandler Carruth #include "llvm/Support/CrashRecoveryContext.h"
84560ce2c7SJonas Devlieghere #include "llvm/Support/DJB.h"
854f233181SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
864f233181SEugene Zelenko #include "llvm/Support/ErrorOr.h"
874f233181SEugene Zelenko #include "llvm/Support/FileSystem.h"
88f69c9178SJan Korous #include "llvm/Support/FileUtilities.h"
893a02247dSChandler Carruth #include "llvm/Support/MemoryBuffer.h"
903a02247dSChandler Carruth #include "llvm/Support/Timer.h"
91fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h"
923a02247dSChandler Carruth #include "llvm/Support/raw_ostream.h"
934f233181SEugene Zelenko #include <algorithm>
944527fb2fSBenjamin Kramer #include <atomic>
954f233181SEugene Zelenko #include <cassert>
964f233181SEugene Zelenko #include <cstdint>
97318e4036SZhongxing Xu #include <cstdio>
983a02247dSChandler Carruth #include <cstdlib>
994f233181SEugene Zelenko #include <memory>
100e57b60f3SBenjamin Kramer #include <mutex>
1014f233181SEugene Zelenko #include <string>
1024f233181SEugene Zelenko #include <tuple>
1034f233181SEugene Zelenko #include <utility>
1044f233181SEugene Zelenko #include <vector>
105dcfba334SHans Wennborg 
106ce379752SArgyrios Kyrtzidis using namespace clang;
107ce379752SArgyrios Kyrtzidis 
10816896c45SDouglas Gregor using llvm::TimeRecord;
10916896c45SDouglas Gregor 
11016896c45SDouglas Gregor namespace {
1114f233181SEugene Zelenko 
11216896c45SDouglas Gregor   class SimpleTimer {
11316896c45SDouglas Gregor     bool WantTiming;
11416896c45SDouglas Gregor     TimeRecord Start;
11516896c45SDouglas Gregor     std::string Output;
11616896c45SDouglas Gregor 
11716896c45SDouglas Gregor   public:
SimpleTimer(bool WantTiming)1181cbdd951SDouglas Gregor     explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {
119f2e5a91fSBenjamin Kramer       if (WantTiming)
12016896c45SDouglas Gregor         Start = TimeRecord::getCurrentTime();
12116896c45SDouglas Gregor     }
12216896c45SDouglas Gregor 
~SimpleTimer()12316896c45SDouglas Gregor     ~SimpleTimer() {
12416896c45SDouglas Gregor       if (WantTiming) {
12516896c45SDouglas Gregor         TimeRecord Elapsed = TimeRecord::getCurrentTime();
12616896c45SDouglas Gregor         Elapsed -= Start;
12716896c45SDouglas Gregor         llvm::errs() << Output << ':';
12816896c45SDouglas Gregor         Elapsed.print(Elapsed, llvm::errs());
12916896c45SDouglas Gregor         llvm::errs() << '\n';
13016896c45SDouglas Gregor       }
13116896c45SDouglas Gregor     }
1324f233181SEugene Zelenko 
setOutput(const Twine & Output)1334f233181SEugene Zelenko     void setOutput(const Twine &Output) {
1344f233181SEugene Zelenko       if (WantTiming)
1354f233181SEugene Zelenko         this->Output = Output.str();
1364f233181SEugene Zelenko     }
13716896c45SDouglas Gregor   };
13806b4f919STed Kremenek 
1394f233181SEugene Zelenko } // namespace
1404f233181SEugene Zelenko 
141af69e40cSIlya Biryukov template <class T>
valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val)1424f233181SEugene Zelenko static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
143af69e40cSIlya Biryukov   if (!Val)
144af69e40cSIlya Biryukov     return nullptr;
145af69e40cSIlya Biryukov   return std::move(*Val);
146af69e40cSIlya Biryukov }
147af69e40cSIlya Biryukov 
148af69e40cSIlya Biryukov template <class T>
moveOnNoError(llvm::ErrorOr<T> Val,T & Output)1494f233181SEugene Zelenko static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
150af69e40cSIlya Biryukov   if (!Val)
151af69e40cSIlya Biryukov     return false;
152af69e40cSIlya Biryukov   Output = std::move(*Val);
153af69e40cSIlya Biryukov   return true;
154af69e40cSIlya Biryukov }
15506b4f919STed Kremenek 
1569fc8faf9SAdrian Prantl /// Get a source buffer for \p MainFilePath, handling all file-to-file
157200b3289SIlya Biryukov /// and file-to-buffer remappings inside \p Invocation.
158200b3289SIlya Biryukov static std::unique_ptr<llvm::MemoryBuffer>
getBufferForFileHandlingRemapping(const CompilerInvocation & Invocation,llvm::vfs::FileSystem * VFS,StringRef FilePath,bool isVolatile)159200b3289SIlya Biryukov getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
160fc51490bSJonas Devlieghere                                   llvm::vfs::FileSystem *VFS,
161fc51490bSJonas Devlieghere                                   StringRef FilePath, bool isVolatile) {
162200b3289SIlya Biryukov   const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();
163bd307a53STed Kremenek 
164200b3289SIlya Biryukov   // Try to determine if the main file has been remapped, either from the
165200b3289SIlya Biryukov   // command line (to another file) or directly through the compiler
166200b3289SIlya Biryukov   // invocation (to a memory buffer).
167200b3289SIlya Biryukov   llvm::MemoryBuffer *Buffer = nullptr;
168200b3289SIlya Biryukov   std::unique_ptr<llvm::MemoryBuffer> BufferOwner;
169200b3289SIlya Biryukov   auto FileStatus = VFS->status(FilePath);
170200b3289SIlya Biryukov   if (FileStatus) {
171200b3289SIlya Biryukov     llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID();
17206b4f919STed Kremenek 
173200b3289SIlya Biryukov     // Check whether there is a file-file remapping of the main file
174200b3289SIlya Biryukov     for (const auto &RF : PreprocessorOpts.RemappedFiles) {
175200b3289SIlya Biryukov       std::string MPath(RF.first);
176200b3289SIlya Biryukov       auto MPathStatus = VFS->status(MPath);
177200b3289SIlya Biryukov       if (MPathStatus) {
178200b3289SIlya Biryukov         llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
179200b3289SIlya Biryukov         if (MainFileID == MID) {
180200b3289SIlya Biryukov           // We found a remapping. Try to load the resulting, remapped source.
1812ebe3a02SIvan Donchevskii           BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));
182200b3289SIlya Biryukov           if (!BufferOwner)
183200b3289SIlya Biryukov             return nullptr;
18406b4f919STed Kremenek         }
18506b4f919STed Kremenek       }
18606b4f919STed Kremenek     }
18706b4f919STed Kremenek 
188200b3289SIlya Biryukov     // Check whether there is a file-buffer remapping. It supercedes the
189200b3289SIlya Biryukov     // file-file remapping.
190200b3289SIlya Biryukov     for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
191200b3289SIlya Biryukov       std::string MPath(RB.first);
192200b3289SIlya Biryukov       auto MPathStatus = VFS->status(MPath);
193200b3289SIlya Biryukov       if (MPathStatus) {
194200b3289SIlya Biryukov         llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
195200b3289SIlya Biryukov         if (MainFileID == MID) {
196200b3289SIlya Biryukov           // We found a remapping.
197200b3289SIlya Biryukov           BufferOwner.reset();
198200b3289SIlya Biryukov           Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);
19906b4f919STed Kremenek         }
20006b4f919STed Kremenek       }
20106b4f919STed Kremenek     }
20206b4f919STed Kremenek   }
20306b4f919STed Kremenek 
204200b3289SIlya Biryukov   // If the main source file was not remapped, load it now.
205200b3289SIlya Biryukov   if (!Buffer && !BufferOwner) {
2062ebe3a02SIvan Donchevskii     BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));
207200b3289SIlya Biryukov     if (!BufferOwner)
208200b3289SIlya Biryukov       return nullptr;
20906b4f919STed Kremenek   }
21006b4f919STed Kremenek 
211200b3289SIlya Biryukov   if (BufferOwner)
212200b3289SIlya Biryukov     return BufferOwner;
213200b3289SIlya Biryukov   if (!Buffer)
214200b3289SIlya Biryukov     return nullptr;
215200b3289SIlya Biryukov   return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);
21606b4f919STed Kremenek }
21706b4f919STed Kremenek 
2180db720f0SArgyrios Kyrtzidis struct ASTUnit::ASTWriterData {
2190db720f0SArgyrios Kyrtzidis   SmallString<128> Buffer;
2200db720f0SArgyrios Kyrtzidis   llvm::BitstreamWriter Stream;
2210db720f0SArgyrios Kyrtzidis   ASTWriter Writer;
2220db720f0SArgyrios Kyrtzidis 
ASTWriterDataASTUnit::ASTWriterData2238bef5cd4SDuncan P. N. Exon Smith   ASTWriterData(InMemoryModuleCache &ModuleCache)
2248bef5cd4SDuncan P. N. Exon Smith       : Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {}
2250db720f0SArgyrios Kyrtzidis };
2260db720f0SArgyrios Kyrtzidis 
clearFileLevelDecls()227e54568d6SArgyrios Kyrtzidis void ASTUnit::clearFileLevelDecls() {
228d9485dfbSDavid Blaikie   FileDecls.clear();
229e54568d6SArgyrios Kyrtzidis }
230e54568d6SArgyrios Kyrtzidis 
2319fc8faf9SAdrian Prantl /// After failing to build a precompiled preamble (due to
232bb420abdSDouglas Gregor /// errors in the source that occurs in the preamble), the number of
233bb420abdSDouglas Gregor /// reparses during which we'll skip even trying to precompile the
234bb420abdSDouglas Gregor /// preamble.
235bb420abdSDouglas Gregor const unsigned DefaultPreambleRebuildInterval = 5;
236bb420abdSDouglas Gregor 
2379fc8faf9SAdrian Prantl /// Tracks the number of ASTUnit objects that are currently active.
23868dbaeadSDouglas Gregor ///
23968dbaeadSDouglas Gregor /// Used for debugging purposes only.
2404527fb2fSBenjamin Kramer static std::atomic<unsigned> ActiveASTUnitObjects;
24168dbaeadSDouglas Gregor 
ASTUnit(bool _MainFileIsAST)242d03e823fSDouglas Gregor ASTUnit::ASTUnit(bool _MainFileIsAST)
2434f233181SEugene Zelenko     : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
2442c8bd47aSDouglas Gregor       ShouldCacheCodeCompletionResults(false),
2456d7833f1SArgyrios Kyrtzidis       IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
2464740c450SDouglas Gregor       UnsafeToFree(false) {
2474527fb2fSBenjamin Kramer   if (getenv("LIBCLANG_OBJTRACKING"))
2484527fb2fSBenjamin Kramer     fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);
24915ba0b34SDouglas Gregor }
250d03e823fSDouglas Gregor 
~ASTUnit()25144cd60eeSSteve Naroff ASTUnit::~ASTUnit() {
2526b930967SDouglas Gregor   // If we loaded from an AST file, balance out the BeginSourceFile call.
2536b930967SDouglas Gregor   if (MainFileIsAST && getDiagnostics().getClient()) {
2546b930967SDouglas Gregor     getDiagnostics().getClient()->EndSourceFile();
2556b930967SDouglas Gregor   }
2566b930967SDouglas Gregor 
257e54568d6SArgyrios Kyrtzidis   clearFileLevelDecls();
258e54568d6SArgyrios Kyrtzidis 
2593f4bea06SDouglas Gregor   // Free the buffers associated with remapped files. We are required to
2603f4bea06SDouglas Gregor   // perform this operation here because we explicitly request that the
2613f4bea06SDouglas Gregor   // compiler instance *not* free these buffers for each invocation of the
2623f4bea06SDouglas Gregor   // parser.
263ea4395ebSDavid Blaikie   if (Invocation && OwnsRemappedFileBuffers) {
2643f4bea06SDouglas Gregor     PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
2651b070d25SAlp Toker     for (const auto &RB : PPOpts.RemappedFileBuffers)
2661b070d25SAlp Toker       delete RB.second;
2673f4bea06SDouglas Gregor   }
26896c04261SDouglas Gregor 
269b14904c4SDouglas Gregor   ClearCachedCompletionResults();
27068dbaeadSDouglas Gregor 
2714527fb2fSBenjamin Kramer   if (getenv("LIBCLANG_OBJTRACKING"))
2724527fb2fSBenjamin Kramer     fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);
273aa21cc40SDouglas Gregor }
274aa21cc40SDouglas Gregor 
setPreprocessor(std::shared_ptr<Preprocessor> PP)27541565463SDavid Blaikie void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
27641565463SDavid Blaikie   this->PP = std::move(PP);
27741565463SDavid Blaikie }
278da6e0547SArgyrios Kyrtzidis 
enableSourceFileDiagnostics()279e4192a86SAdam Balogh void ASTUnit::enableSourceFileDiagnostics() {
280e4192a86SAdam Balogh   assert(getDiagnostics().getClient() && Ctx &&
281e4192a86SAdam Balogh       "Bad context for source file");
282e4192a86SAdam Balogh   getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());
283e4192a86SAdam Balogh }
284e4192a86SAdam Balogh 
2859fc8faf9SAdrian Prantl /// Determine the set of code-completion contexts in which this
28639982197SDouglas Gregor /// declaration should be shown.
getDeclShowContexts(const NamedDecl * ND,const LangOptions & LangOpts,bool & IsNestedNameSpecifier)287b006e099SKadir Cetinkaya static uint64_t getDeclShowContexts(const NamedDecl *ND,
28859cab556SDouglas Gregor                                     const LangOptions &LangOpts,
28959cab556SDouglas Gregor                                     bool &IsNestedNameSpecifier) {
29059cab556SDouglas Gregor   IsNestedNameSpecifier = false;
29159cab556SDouglas Gregor 
29239982197SDouglas Gregor   if (isa<UsingShadowDecl>(ND))
29300f70bd9SGeorge Burgess IV     ND = ND->getUnderlyingDecl();
29439982197SDouglas Gregor   if (!ND)
29539982197SDouglas Gregor     return 0;
29639982197SDouglas Gregor 
297697cc9e6SRichard Smith   uint64_t Contexts = 0;
29839982197SDouglas Gregor   if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
29951ee12a9SErik Verbruggen       isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||
30051ee12a9SErik Verbruggen       isa<TypeAliasTemplateDecl>(ND)) {
30139982197SDouglas Gregor     // Types can appear in these contexts.
30239982197SDouglas Gregor     if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
303697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
304697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_ObjCIvarList)
305697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_ClassStructUnion)
306697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_Statement)
307697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_Type)
308697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
30939982197SDouglas Gregor 
31039982197SDouglas Gregor     // In C++, types can appear in expressions contexts (for functional casts).
31139982197SDouglas Gregor     if (LangOpts.CPlusPlus)
312697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
31339982197SDouglas Gregor 
31439982197SDouglas Gregor     // In Objective-C, message sends can send interfaces. In Objective-C++,
31539982197SDouglas Gregor     // all types are available due to functional casts.
31639982197SDouglas Gregor     if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
317697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
31839982197SDouglas Gregor 
3192132584dSDouglas Gregor     // In Objective-C, you can only be a subclass of another Objective-C class
320f3df1f7bSAlex Lorenz     if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
321f3df1f7bSAlex Lorenz       // Objective-C interfaces can be used in a class property expression.
322f3df1f7bSAlex Lorenz       if (ID->getDefinition())
323f3df1f7bSAlex Lorenz         Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
324697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
325f3df1f7bSAlex Lorenz     }
3262132584dSDouglas Gregor 
32739982197SDouglas Gregor     // Deal with tag names.
32839982197SDouglas Gregor     if (isa<EnumDecl>(ND)) {
329697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);
33039982197SDouglas Gregor 
33159cab556SDouglas Gregor       // Part of the nested-name-specifier in C++0x.
3322bf7fdb7SRichard Smith       if (LangOpts.CPlusPlus11)
33359cab556SDouglas Gregor         IsNestedNameSpecifier = true;
3344f233181SEugene Zelenko     } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {
33539982197SDouglas Gregor       if (Record->isUnion())
336697cc9e6SRichard Smith         Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
33739982197SDouglas Gregor       else
338697cc9e6SRichard Smith         Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
33939982197SDouglas Gregor 
34039982197SDouglas Gregor       if (LangOpts.CPlusPlus)
34159cab556SDouglas Gregor         IsNestedNameSpecifier = true;
3420ac41389SDouglas Gregor     } else if (isa<ClassTemplateDecl>(ND))
34359cab556SDouglas Gregor       IsNestedNameSpecifier = true;
34439982197SDouglas Gregor   } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
34539982197SDouglas Gregor     // Values can appear in these contexts.
346697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_Statement)
347697cc9e6SRichard Smith              | (1LL << CodeCompletionContext::CCC_Expression)
348697cc9e6SRichard Smith              | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
349697cc9e6SRichard Smith              | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
35039982197SDouglas Gregor   } else if (isa<ObjCProtocolDecl>(ND)) {
351697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);
3522132584dSDouglas Gregor   } else if (isa<ObjCCategoryDecl>(ND)) {
353697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);
35439982197SDouglas Gregor   } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
355697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_Namespace);
35639982197SDouglas Gregor 
35739982197SDouglas Gregor     // Part of the nested-name-specifier.
35859cab556SDouglas Gregor     IsNestedNameSpecifier = true;
35939982197SDouglas Gregor   }
36039982197SDouglas Gregor 
36139982197SDouglas Gregor   return Contexts;
36239982197SDouglas Gregor }
36339982197SDouglas Gregor 
CacheCodeCompletionResults()364b14904c4SDouglas Gregor void ASTUnit::CacheCodeCompletionResults() {
365b14904c4SDouglas Gregor   if (!TheSema)
366b14904c4SDouglas Gregor     return;
367b14904c4SDouglas Gregor 
36816896c45SDouglas Gregor   SimpleTimer Timer(WantTiming);
36916896c45SDouglas Gregor   Timer.setOutput("Cache global code completions for " + getMainFileName());
370b14904c4SDouglas Gregor 
371b14904c4SDouglas Gregor   // Clear out the previous results.
372b14904c4SDouglas Gregor   ClearCachedCompletionResults();
373b14904c4SDouglas Gregor 
374b14904c4SDouglas Gregor   // Gather the set of global code completions.
3754f233181SEugene Zelenko   using Result = CodeCompletionResult;
3760e62c1ccSChris Lattner   SmallVector<Result, 8> Results;
377ea4395ebSDavid Blaikie   CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
3782bafa007SArgyrios Kyrtzidis   CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);
3799d7c0fefSArgyrios Kyrtzidis   TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator,
3802bafa007SArgyrios Kyrtzidis                                        CCTUInfo, Results);
381b14904c4SDouglas Gregor 
382b14904c4SDouglas Gregor   // Translate global code completions into cached completions.
383b61c07acSDouglas Gregor   llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
384c3425b1fSDouglas Gregor   CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
385b61c07acSDouglas Gregor 
3864f233181SEugene Zelenko   for (auto &R : Results) {
3876a96ae5eSBenjamin Kramer     switch (R.Kind) {
38839982197SDouglas Gregor     case Result::RK_Declaration: {
38959cab556SDouglas Gregor       bool IsNestedNameSpecifier = false;
39039982197SDouglas Gregor       CachedCodeCompletionResult CachedResult;
3916a96ae5eSBenjamin Kramer       CachedResult.Completion = R.CreateCodeCompletionString(
392c3425b1fSDouglas Gregor           *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
3933292d06aSDmitri Gribenko           IncludeBriefCommentsInCodeCompletion);
3946a96ae5eSBenjamin Kramer       CachedResult.ShowInContexts = getDeclShowContexts(
3956a96ae5eSBenjamin Kramer           R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);
3966a96ae5eSBenjamin Kramer       CachedResult.Priority = R.Priority;
3976a96ae5eSBenjamin Kramer       CachedResult.Kind = R.CursorKind;
3986a96ae5eSBenjamin Kramer       CachedResult.Availability = R.Availability;
39924747408SDouglas Gregor 
400b61c07acSDouglas Gregor       // Keep track of the type of this completion in an ASTContext-agnostic
401b61c07acSDouglas Gregor       // way.
4026a96ae5eSBenjamin Kramer       QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);
403b61c07acSDouglas Gregor       if (UsageType.isNull()) {
40424747408SDouglas Gregor         CachedResult.TypeClass = STC_Void;
405b61c07acSDouglas Gregor         CachedResult.Type = 0;
406b61c07acSDouglas Gregor       } else {
407b61c07acSDouglas Gregor         CanQualType CanUsageType
408b61c07acSDouglas Gregor           = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
409b61c07acSDouglas Gregor         CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
410b61c07acSDouglas Gregor 
411b61c07acSDouglas Gregor         // Determine whether we have already seen this type. If so, we save
412b61c07acSDouglas Gregor         // ourselves the work of formatting the type string by using the
413b61c07acSDouglas Gregor         // temporary, CanQualType-based hash table to find the associated value.
414b61c07acSDouglas Gregor         unsigned &TypeValue = CompletionTypes[CanUsageType];
415b61c07acSDouglas Gregor         if (TypeValue == 0) {
416b61c07acSDouglas Gregor           TypeValue = CompletionTypes.size();
417b61c07acSDouglas Gregor           CachedCompletionTypes[QualType(CanUsageType).getAsString()]
418b61c07acSDouglas Gregor             = TypeValue;
41924747408SDouglas Gregor         }
420b61c07acSDouglas Gregor 
421b61c07acSDouglas Gregor         CachedResult.Type = TypeValue;
422b61c07acSDouglas Gregor       }
423b61c07acSDouglas Gregor 
42439982197SDouglas Gregor       CachedCompletionResults.push_back(CachedResult);
42559cab556SDouglas Gregor 
42659cab556SDouglas Gregor       /// Handle nested-name-specifiers in C++.
4276a96ae5eSBenjamin Kramer       if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&
4286a96ae5eSBenjamin Kramer           !R.StartsNestedNameSpecifier) {
42959cab556SDouglas Gregor         // The contexts in which a nested-name-specifier can appear in C++.
430697cc9e6SRichard Smith         uint64_t NNSContexts
431697cc9e6SRichard Smith           = (1LL << CodeCompletionContext::CCC_TopLevel)
432697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
433697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
434697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_Statement)
435697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_Expression)
436697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
437697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_EnumTag)
438697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_UnionTag)
439697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ClassOrStructTag)
440697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_Type)
441b006e099SKadir Cetinkaya           | (1LL << CodeCompletionContext::CCC_SymbolOrNewName)
442697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
44359cab556SDouglas Gregor 
4446a96ae5eSBenjamin Kramer         if (isa<NamespaceDecl>(R.Declaration) ||
4456a96ae5eSBenjamin Kramer             isa<NamespaceAliasDecl>(R.Declaration))
446697cc9e6SRichard Smith           NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
44759cab556SDouglas Gregor 
448b006e099SKadir Cetinkaya         if (uint64_t RemainingContexts
44959cab556SDouglas Gregor                                 = NNSContexts & ~CachedResult.ShowInContexts) {
45059cab556SDouglas Gregor           // If there any contexts where this completion can be a
45159cab556SDouglas Gregor           // nested-name-specifier but isn't already an option, create a
45259cab556SDouglas Gregor           // nested-name-specifier completion.
4536a96ae5eSBenjamin Kramer           R.StartsNestedNameSpecifier = true;
4546a96ae5eSBenjamin Kramer           CachedResult.Completion = R.CreateCodeCompletionString(
455c3425b1fSDouglas Gregor               *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
4563292d06aSDmitri Gribenko               IncludeBriefCommentsInCodeCompletion);
45759cab556SDouglas Gregor           CachedResult.ShowInContexts = RemainingContexts;
45859cab556SDouglas Gregor           CachedResult.Priority = CCP_NestedNameSpecifier;
45959cab556SDouglas Gregor           CachedResult.TypeClass = STC_Void;
46059cab556SDouglas Gregor           CachedResult.Type = 0;
46159cab556SDouglas Gregor           CachedCompletionResults.push_back(CachedResult);
46259cab556SDouglas Gregor         }
46359cab556SDouglas Gregor       }
464b14904c4SDouglas Gregor       break;
46539982197SDouglas Gregor     }
466b14904c4SDouglas Gregor 
467b14904c4SDouglas Gregor     case Result::RK_Keyword:
468b14904c4SDouglas Gregor     case Result::RK_Pattern:
469b14904c4SDouglas Gregor       // Ignore keywords and patterns; we don't care, since they are so
470b14904c4SDouglas Gregor       // easily regenerated.
471b14904c4SDouglas Gregor       break;
472b14904c4SDouglas Gregor 
473b14904c4SDouglas Gregor     case Result::RK_Macro: {
474b14904c4SDouglas Gregor       CachedCodeCompletionResult CachedResult;
4756a96ae5eSBenjamin Kramer       CachedResult.Completion = R.CreateCodeCompletionString(
476c3425b1fSDouglas Gregor           *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
4773292d06aSDmitri Gribenko           IncludeBriefCommentsInCodeCompletion);
478b14904c4SDouglas Gregor       CachedResult.ShowInContexts
479697cc9e6SRichard Smith         = (1LL << CodeCompletionContext::CCC_TopLevel)
480697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCInterface)
481697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
482697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
483697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
484697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Statement)
485697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Expression)
486697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
487697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_MacroNameUse)
488697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_PreprocessorExpression)
489697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
490697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_OtherWithMacros);
491c49f5b2fSDouglas Gregor 
4926a96ae5eSBenjamin Kramer       CachedResult.Priority = R.Priority;
4936a96ae5eSBenjamin Kramer       CachedResult.Kind = R.CursorKind;
4946a96ae5eSBenjamin Kramer       CachedResult.Availability = R.Availability;
4956e24033bSDouglas Gregor       CachedResult.TypeClass = STC_Void;
496b61c07acSDouglas Gregor       CachedResult.Type = 0;
497b14904c4SDouglas Gregor       CachedCompletionResults.push_back(CachedResult);
498b14904c4SDouglas Gregor       break;
499b14904c4SDouglas Gregor     }
500b14904c4SDouglas Gregor     }
501b14904c4SDouglas Gregor   }
502b14904c4SDouglas Gregor 
503df7a79a9SDouglas Gregor   // Save the current top-level hash value.
504df7a79a9SDouglas Gregor   CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
505b14904c4SDouglas Gregor }
506b14904c4SDouglas Gregor 
ClearCachedCompletionResults()507b14904c4SDouglas Gregor void ASTUnit::ClearCachedCompletionResults() {
508b14904c4SDouglas Gregor   CachedCompletionResults.clear();
509b61c07acSDouglas Gregor   CachedCompletionTypes.clear();
51049a2790fSCraig Topper   CachedCompletionAllocator = nullptr;
511b14904c4SDouglas Gregor }
512b14904c4SDouglas Gregor 
513ce379752SArgyrios Kyrtzidis namespace {
514ce379752SArgyrios Kyrtzidis 
5159fc8faf9SAdrian Prantl /// Gathers information from ASTReader that will be used to initialize
516ce379752SArgyrios Kyrtzidis /// a Preprocessor.
517d44cd6adSSebastian Redl class ASTInfoCollector : public ASTReaderListener {
51883297dfcSDouglas Gregor   Preprocessor &PP;
519dbafb6c3SRichard Smith   ASTContext *Context;
5201893475dSRichard Smith   HeaderSearchOptions &HSOpts;
5211893475dSRichard Smith   PreprocessorOptions &PPOpts;
522ce379752SArgyrios Kyrtzidis   LangOptions &LangOpt;
52380758084SAlp Toker   std::shared_ptr<TargetOptions> &TargetOpts;
524c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<TargetInfo> &Target;
525ce379752SArgyrios Kyrtzidis   unsigned &Counter;
5264f233181SEugene Zelenko   bool InitializedLanguage = false;
527ce379752SArgyrios Kyrtzidis 
528ce379752SArgyrios Kyrtzidis public:
ASTInfoCollector(Preprocessor & PP,ASTContext * Context,HeaderSearchOptions & HSOpts,PreprocessorOptions & PPOpts,LangOptions & LangOpt,std::shared_ptr<TargetOptions> & TargetOpts,IntrusiveRefCntPtr<TargetInfo> & Target,unsigned & Counter)529dbafb6c3SRichard Smith   ASTInfoCollector(Preprocessor &PP, ASTContext *Context,
5301893475dSRichard Smith                    HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
5311893475dSRichard Smith                    LangOptions &LangOpt,
53280758084SAlp Toker                    std::shared_ptr<TargetOptions> &TargetOpts,
53380758084SAlp Toker                    IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
5341893475dSRichard Smith       : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),
5351893475dSRichard Smith         LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
5364f233181SEugene Zelenko         Counter(Counter) {}
537ce379752SArgyrios Kyrtzidis 
ReadLanguageOptions(const LangOptions & LangOpts,bool Complain,bool AllowCompatibleDifferences)5381e2cf0ddSRichard Smith   bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
5391e2cf0ddSRichard Smith                            bool AllowCompatibleDifferences) override {
5400db720f0SArgyrios Kyrtzidis     if (InitializedLanguage)
54183297dfcSDouglas Gregor       return false;
54283297dfcSDouglas Gregor 
543ce379752SArgyrios Kyrtzidis     LangOpt = LangOpts;
544e8bbc121SDouglas Gregor     InitializedLanguage = true;
5459e1fb563SArgyrios Kyrtzidis 
5460db720f0SArgyrios Kyrtzidis     updated();
547ce379752SArgyrios Kyrtzidis     return false;
548ce379752SArgyrios Kyrtzidis   }
549ce379752SArgyrios Kyrtzidis 
ReadHeaderSearchOptions(const HeaderSearchOptions & HSOpts,StringRef SpecificModuleCachePath,bool Complain)5504f233181SEugene Zelenko   bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
5511893475dSRichard Smith                                StringRef SpecificModuleCachePath,
5521893475dSRichard Smith                                bool Complain) override {
5531893475dSRichard Smith     this->HSOpts = HSOpts;
5541893475dSRichard Smith     return false;
5551893475dSRichard Smith   }
5561893475dSRichard Smith 
ReadPreprocessorOptions(const PreprocessorOptions & PPOpts,bool Complain,std::string & SuggestedPredefines)5574f233181SEugene Zelenko   bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
5581893475dSRichard Smith                                std::string &SuggestedPredefines) override {
5591893475dSRichard Smith     this->PPOpts = PPOpts;
5601893475dSRichard Smith     return false;
5611893475dSRichard Smith   }
5621893475dSRichard Smith 
ReadTargetOptions(const TargetOptions & TargetOpts,bool Complain,bool AllowCompatibleDifferences)5630d745bcfSChandler Carruth   bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
5640d745bcfSChandler Carruth                          bool AllowCompatibleDifferences) override {
56583297dfcSDouglas Gregor     // If we've already initialized the target, don't do it again.
5660db720f0SArgyrios Kyrtzidis     if (Target)
56783297dfcSDouglas Gregor       return false;
56883297dfcSDouglas Gregor 
56980758084SAlp Toker     this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);
57080758084SAlp Toker     Target =
57180758084SAlp Toker         TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts);
5729e1fb563SArgyrios Kyrtzidis 
5730db720f0SArgyrios Kyrtzidis     updated();
574ce379752SArgyrios Kyrtzidis     return false;
575ce379752SArgyrios Kyrtzidis   }
576ce379752SArgyrios Kyrtzidis 
ReadCounter(const serialization::ModuleFile & M,unsigned Value)577afa7cb3aSCraig Topper   void ReadCounter(const serialization::ModuleFile &M,
578afa7cb3aSCraig Topper                    unsigned Value) override {
579ce379752SArgyrios Kyrtzidis     Counter = Value;
580ce379752SArgyrios Kyrtzidis   }
5819e1fb563SArgyrios Kyrtzidis 
5829e1fb563SArgyrios Kyrtzidis private:
updated()5830db720f0SArgyrios Kyrtzidis   void updated() {
5840db720f0SArgyrios Kyrtzidis     if (!Target || !InitializedLanguage)
5850db720f0SArgyrios Kyrtzidis       return;
5860db720f0SArgyrios Kyrtzidis 
5879e1fb563SArgyrios Kyrtzidis     // Inform the target of the language options.
5889e1fb563SArgyrios Kyrtzidis     //
5899e1fb563SArgyrios Kyrtzidis     // FIXME: We shouldn't need to do this, the target should be immutable once
5909e1fb563SArgyrios Kyrtzidis     // created. This complexity should be lifted elsewhere.
591aaba3718SMelanie Blower     Target->adjust(PP.getDiagnostics(), LangOpt);
5920db720f0SArgyrios Kyrtzidis 
5930db720f0SArgyrios Kyrtzidis     // Initialize the preprocessor.
5940db720f0SArgyrios Kyrtzidis     PP.Initialize(*Target);
5950db720f0SArgyrios Kyrtzidis 
596dbafb6c3SRichard Smith     if (!Context)
597dbafb6c3SRichard Smith       return;
598dbafb6c3SRichard Smith 
5990db720f0SArgyrios Kyrtzidis     // Initialize the ASTContext
600dbafb6c3SRichard Smith     Context->InitBuiltinTypes(*Target);
601acf2e786SDmitri Gribenko 
602fd9fad9eSVedant Kumar     // Adjust printing policy based on language options.
603fd9fad9eSVedant Kumar     Context->setPrintingPolicy(PrintingPolicy(LangOpt));
604fd9fad9eSVedant Kumar 
605acf2e786SDmitri Gribenko     // We didn't have access to the comment options when the ASTContext was
606acf2e786SDmitri Gribenko     // constructed, so register them now.
607dbafb6c3SRichard Smith     Context->getCommentCommandTraits().registerCommentOptions(
608acf2e786SDmitri Gribenko         LangOpt.CommentOpts);
6099e1fb563SArgyrios Kyrtzidis   }
610ce379752SArgyrios Kyrtzidis };
611ce379752SArgyrios Kyrtzidis 
6129fc8faf9SAdrian Prantl /// Diagnostic consumer that saves each diagnostic it is given.
6138edd8da4SNikolai Kosjar class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
614200b3289SIlya Biryukov   SmallVectorImpl<StoredDiagnostic> *StoredDiags;
615200b3289SIlya Biryukov   SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;
6168edd8da4SNikolai Kosjar   bool CaptureNonErrorsFromIncludes = true;
6174f233181SEugene Zelenko   const LangOptions *LangOpts = nullptr;
6184f233181SEugene Zelenko   SourceManager *SourceMgr = nullptr;
61933cdd810SDouglas Gregor 
62033cdd810SDouglas Gregor public:
FilterAndStoreDiagnosticConsumer(SmallVectorImpl<StoredDiagnostic> * StoredDiags,SmallVectorImpl<ASTUnit::StandaloneDiagnostic> * StandaloneDiags,bool CaptureNonErrorsFromIncludes)6218edd8da4SNikolai Kosjar   FilterAndStoreDiagnosticConsumer(
622200b3289SIlya Biryukov       SmallVectorImpl<StoredDiagnostic> *StoredDiags,
6238edd8da4SNikolai Kosjar       SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags,
6248edd8da4SNikolai Kosjar       bool CaptureNonErrorsFromIncludes)
6258edd8da4SNikolai Kosjar       : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),
6268edd8da4SNikolai Kosjar         CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {
627200b3289SIlya Biryukov     assert((StoredDiags || StandaloneDiags) &&
628200b3289SIlya Biryukov            "No output collections were passed to StoredDiagnosticConsumer.");
629200b3289SIlya Biryukov   }
6306b930967SDouglas Gregor 
BeginSourceFile(const LangOptions & LangOpts,const Preprocessor * PP=nullptr)631afa7cb3aSCraig Topper   void BeginSourceFile(const LangOptions &LangOpts,
63249a2790fSCraig Topper                        const Preprocessor *PP = nullptr) override {
633200b3289SIlya Biryukov     this->LangOpts = &LangOpts;
6346b930967SDouglas Gregor     if (PP)
6356b930967SDouglas Gregor       SourceMgr = &PP->getSourceManager();
6366b930967SDouglas Gregor   }
63733cdd810SDouglas Gregor 
638afa7cb3aSCraig Topper   void HandleDiagnostic(DiagnosticsEngine::Level Level,
639afa7cb3aSCraig Topper                         const Diagnostic &Info) override;
64033cdd810SDouglas Gregor };
64133cdd810SDouglas Gregor 
6428edd8da4SNikolai Kosjar /// RAII object that optionally captures and filters diagnostics, if
64333cdd810SDouglas Gregor /// there is no diagnostic client to capture them already.
64433cdd810SDouglas Gregor class CaptureDroppedDiagnostics {
6459c902b55SDavid Blaikie   DiagnosticsEngine &Diags;
6468edd8da4SNikolai Kosjar   FilterAndStoreDiagnosticConsumer Client;
6474f233181SEugene Zelenko   DiagnosticConsumer *PreviousClient = nullptr;
64841c247a6SAlexander Kornienko   std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
64933cdd810SDouglas Gregor 
65033cdd810SDouglas Gregor public:
CaptureDroppedDiagnostics(CaptureDiagsKind CaptureDiagnostics,DiagnosticsEngine & Diags,SmallVectorImpl<StoredDiagnostic> * StoredDiags,SmallVectorImpl<ASTUnit::StandaloneDiagnostic> * StandaloneDiags)6514f233181SEugene Zelenko   CaptureDroppedDiagnostics(
6528edd8da4SNikolai Kosjar       CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
653200b3289SIlya Biryukov       SmallVectorImpl<StoredDiagnostic> *StoredDiags,
654200b3289SIlya Biryukov       SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
6558edd8da4SNikolai Kosjar       : Diags(Diags),
6568edd8da4SNikolai Kosjar         Client(StoredDiags, StandaloneDiags,
6578edd8da4SNikolai Kosjar                CaptureDiagnostics !=
6588edd8da4SNikolai Kosjar                    CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {
6598edd8da4SNikolai Kosjar     if (CaptureDiagnostics != CaptureDiagsKind::None ||
6608edd8da4SNikolai Kosjar         Diags.getClient() == nullptr) {
66141c247a6SAlexander Kornienko       OwningPreviousClient = Diags.takeClient();
66241c247a6SAlexander Kornienko       PreviousClient = Diags.getClient();
66341c247a6SAlexander Kornienko       Diags.setClient(&Client, false);
66433cdd810SDouglas Gregor     }
6652dd19f1dSDouglas Gregor   }
66633cdd810SDouglas Gregor 
~CaptureDroppedDiagnostics()66733cdd810SDouglas Gregor   ~CaptureDroppedDiagnostics() {
66841c247a6SAlexander Kornienko     if (Diags.getClient() == &Client)
66941c247a6SAlexander Kornienko       Diags.setClient(PreviousClient, !!OwningPreviousClient.release());
6702dd19f1dSDouglas Gregor   }
67133cdd810SDouglas Gregor };
67233cdd810SDouglas Gregor 
6734f233181SEugene Zelenko } // namespace
674ce379752SArgyrios Kyrtzidis 
675200b3289SIlya Biryukov static ASTUnit::StandaloneDiagnostic
676200b3289SIlya Biryukov makeStandaloneDiagnostic(const LangOptions &LangOpts,
677200b3289SIlya Biryukov                          const StoredDiagnostic &InDiag);
678200b3289SIlya Biryukov 
isInMainFile(const clang::Diagnostic & D)6798edd8da4SNikolai Kosjar static bool isInMainFile(const clang::Diagnostic &D) {
6808edd8da4SNikolai Kosjar   if (!D.hasSourceManager() || !D.getLocation().isValid())
6818edd8da4SNikolai Kosjar     return false;
6828edd8da4SNikolai Kosjar 
6838edd8da4SNikolai Kosjar   auto &M = D.getSourceManager();
6848edd8da4SNikolai Kosjar   return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation()));
6858edd8da4SNikolai Kosjar }
6868edd8da4SNikolai Kosjar 
HandleDiagnostic(DiagnosticsEngine::Level Level,const Diagnostic & Info)6878edd8da4SNikolai Kosjar void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(
6888edd8da4SNikolai Kosjar     DiagnosticsEngine::Level Level, const Diagnostic &Info) {
689c79346a5SArgyrios Kyrtzidis   // Default implementation (Warnings/errors count).
690e2eefaecSDavid Blaikie   DiagnosticConsumer::HandleDiagnostic(Level, Info);
691c79346a5SArgyrios Kyrtzidis 
6926b930967SDouglas Gregor   // Only record the diagnostic if it's part of the source manager we know
6936b930967SDouglas Gregor   // about. This effectively drops diagnostics from modules we're building.
6946b930967SDouglas Gregor   // FIXME: In the long run, ee don't want to drop source managers from modules.
695200b3289SIlya Biryukov   if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) {
6968edd8da4SNikolai Kosjar     if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning &&
6978edd8da4SNikolai Kosjar         !isInMainFile(Info)) {
6988edd8da4SNikolai Kosjar       return;
6998edd8da4SNikolai Kosjar     }
7008edd8da4SNikolai Kosjar 
701200b3289SIlya Biryukov     StoredDiagnostic *ResultDiag = nullptr;
702200b3289SIlya Biryukov     if (StoredDiags) {
703200b3289SIlya Biryukov       StoredDiags->emplace_back(Level, Info);
704200b3289SIlya Biryukov       ResultDiag = &StoredDiags->back();
705200b3289SIlya Biryukov     }
706200b3289SIlya Biryukov 
707200b3289SIlya Biryukov     if (StandaloneDiags) {
7084f233181SEugene Zelenko       llvm::Optional<StoredDiagnostic> StoredDiag = None;
709200b3289SIlya Biryukov       if (!ResultDiag) {
710200b3289SIlya Biryukov         StoredDiag.emplace(Level, Info);
711200b3289SIlya Biryukov         ResultDiag = StoredDiag.getPointer();
712200b3289SIlya Biryukov       }
713200b3289SIlya Biryukov       StandaloneDiags->push_back(
714200b3289SIlya Biryukov           makeStandaloneDiagnostic(*LangOpts, *ResultDiag));
715200b3289SIlya Biryukov     }
716200b3289SIlya Biryukov   }
71733cdd810SDouglas Gregor }
71833cdd810SDouglas Gregor 
getASTReader() const719a38cb204SArgyrios Kyrtzidis IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {
720a38cb204SArgyrios Kyrtzidis   return Reader;
721a38cb204SArgyrios Kyrtzidis }
722a38cb204SArgyrios Kyrtzidis 
getASTMutationListener()7231c7455f4SArgyrios Kyrtzidis ASTMutationListener *ASTUnit::getASTMutationListener() {
7241c7455f4SArgyrios Kyrtzidis   if (WriterData)
7251c7455f4SArgyrios Kyrtzidis     return &WriterData->Writer;
72649a2790fSCraig Topper   return nullptr;
7271c7455f4SArgyrios Kyrtzidis }
7281c7455f4SArgyrios Kyrtzidis 
getDeserializationListener()7290db720f0SArgyrios Kyrtzidis ASTDeserializationListener *ASTUnit::getDeserializationListener() {
7300db720f0SArgyrios Kyrtzidis   if (WriterData)
7310db720f0SArgyrios Kyrtzidis     return &WriterData->Writer;
73249a2790fSCraig Topper   return nullptr;
7330db720f0SArgyrios Kyrtzidis }
7340db720f0SArgyrios Kyrtzidis 
73516e1ba1eSRafael Espindola std::unique_ptr<llvm::MemoryBuffer>
getBufferForFile(StringRef Filename,std::string * ErrorStr)73616e1ba1eSRafael Espindola ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {
7375159f616SChris Lattner   assert(FileMgr);
7382ebe3a02SIvan Donchevskii   auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);
739a885796dSBenjamin Kramer   if (Buffer)
740a885796dSBenjamin Kramer     return std::move(*Buffer);
741a885796dSBenjamin Kramer   if (ErrorStr)
742a885796dSBenjamin Kramer     *ErrorStr = Buffer.getError().message();
743a885796dSBenjamin Kramer   return nullptr;
74471731d6bSArgyrios Kyrtzidis }
74571731d6bSArgyrios Kyrtzidis 
7469fc8faf9SAdrian Prantl /// Configure the diagnostics object for use with ASTUnit.
ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,ASTUnit & AST,CaptureDiagsKind CaptureDiagnostics)747d512c1edSJustin Bogner void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
7488edd8da4SNikolai Kosjar                              ASTUnit &AST,
7498edd8da4SNikolai Kosjar                              CaptureDiagsKind CaptureDiagnostics) {
750d512c1edSJustin Bogner   assert(Diags.get() && "no DiagnosticsEngine was provided");
7518edd8da4SNikolai Kosjar   if (CaptureDiagnostics != CaptureDiagsKind::None)
7528edd8da4SNikolai Kosjar     Diags->setClient(new FilterAndStoreDiagnosticConsumer(
7538edd8da4SNikolai Kosjar         &AST.StoredDiagnostics, nullptr,
7548edd8da4SNikolai Kosjar         CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes));
75544c6ee77SDouglas Gregor }
75644c6ee77SDouglas Gregor 
LoadFromASTFile(const std::string & Filename,const PCHContainerReader & PCHContainerRdr,WhatToLoad ToLoad,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,const FileSystemOptions & FileSystemOpts,bool UseDebugInfo,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,bool AllowASTWithCompilerErrors,bool UserFilesAreVolatile,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)7576f7382ddSDavid Blaikie std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
7586b21ab21SAdrian Prantl     const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
759dbafb6c3SRichard Smith     WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
7606b21ab21SAdrian Prantl     const FileSystemOptions &FileSystemOpts, bool UseDebugInfo,
761c3ff9939SDuncan P. N. Exon Smith     bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
7629d6d069fSAndy Soffer     bool AllowASTWithCompilerErrors, bool UserFilesAreVolatile,
7639d6d069fSAndy Soffer     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
764b8984329SAhmed Charles   std::unique_ptr<ASTUnit> AST(new ASTUnit(true));
7654422bfeaSTed Kremenek 
7664422bfeaSTed Kremenek   // Recover resources if we crash before exiting this method.
767022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
768022a4904STed Kremenek     ASTUnitCleanup(AST.get());
7699c902b55SDavid Blaikie   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
7709c902b55SDavid Blaikie     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
771f994cef8SAlp Toker     DiagCleanup(Diags.get());
7724422bfeaSTed Kremenek 
773dbbcb11fSJustin Bogner   ConfigureDiags(Diags, *AST, CaptureDiagnostics);
774d03e823fSDouglas Gregor 
775ab75597dSRichard Smith   AST->LangOpts = std::make_shared<LangOptions>();
77616bef857SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
77744c6ee77SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
7787f95d26eSDouglas Gregor   AST->Diagnostics = Diags;
7798832c066SBen Langmuir   AST->FileMgr = new FileManager(FileSystemOpts, VFS);
7806d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
7815e14d39aSTed Kremenek   AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
7826d7833f1SArgyrios Kyrtzidis                                      AST->getFileManager(),
7836d7833f1SArgyrios Kyrtzidis                                      UserFilesAreVolatile);
7848bef5cd4SDuncan P. N. Exon Smith   AST->ModuleCache = new InMemoryModuleCache;
7859c28cb3fSDavid Blaikie   AST->HSOpts = std::make_shared<HeaderSearchOptions>();
786adcd0268SBenjamin Kramer   AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormat());
787b85b9ccbSDouglas Gregor   AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
7881f76c4e8SManuel Klimek                                          AST->getSourceManager(),
7891fb5c3a6SDouglas Gregor                                          AST->getDiagnostics(),
790ab75597dSRichard Smith                                          AST->getLangOpts(),
79149a2790fSCraig Topper                                          /*Target=*/nullptr));
7921893475dSRichard Smith   AST->PPOpts = std::make_shared<PreprocessorOptions>();
793aa98ed9aSDouglas Gregor 
794ce379752SArgyrios Kyrtzidis   // Gather Info for preprocessor construction later on.
795ce379752SArgyrios Kyrtzidis 
7966f7382ddSDavid Blaikie   HeaderSearch &HeaderInfo = *AST->HeaderInfo;
797ce379752SArgyrios Kyrtzidis   unsigned Counter;
798ce379752SArgyrios Kyrtzidis 
79941565463SDavid Blaikie   AST->PP = std::make_shared<Preprocessor>(
8001893475dSRichard Smith       AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts,
8018bef5cd4SDuncan P. N. Exon Smith       AST->getSourceManager(), HeaderInfo, AST->ModuleLoader,
80249a2790fSCraig Topper       /*IILookup=*/nullptr,
8031ae02f68SAlp Toker       /*OwnsHeaderSearch=*/false);
804e8bbc121SDouglas Gregor   Preprocessor &PP = *AST->PP;
805e8bbc121SDouglas Gregor 
806dbafb6c3SRichard Smith   if (ToLoad >= LoadASTOnly)
807ab75597dSRichard Smith     AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
80808043437SAlp Toker                               PP.getIdentifierTable(), PP.getSelectorTable(),
80911b47c10SVassil Vassilev                               PP.getBuiltinInfo(),
81011b47c10SVassil Vassilev                               AST->getTranslationUnitKind());
81183297dfcSDouglas Gregor 
812b0e89906SArgyrios Kyrtzidis   DisableValidationForModuleKind disableValid =
813b0e89906SArgyrios Kyrtzidis       DisableValidationForModuleKind::None;
814945a8193SArgyrios Kyrtzidis   if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
815b0e89906SArgyrios Kyrtzidis     disableValid = DisableValidationForModuleKind::All;
8168bef5cd4SDuncan P. N. Exon Smith   AST->Reader = new ASTReader(
8178bef5cd4SDuncan P. N. Exon Smith       PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},
8184a280ff4SArgyrios Kyrtzidis       /*isysroot=*/"",
81917d4bd3dSKazu Hirata       /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);
8202159b8d2STed Kremenek 
8212b3d49b6SJonas Devlieghere   AST->Reader->setListener(std::make_unique<ASTInfoCollector>(
822dbafb6c3SRichard Smith       *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
8231893475dSRichard Smith       AST->TargetOpts, AST->Target, Counter));
8242d9c740cSDaniel Dunbar 
825f0b4cd1eSArgyrios Kyrtzidis   // Attach the AST reader to the AST context as an external AST
826f0b4cd1eSArgyrios Kyrtzidis   // source, so that declarations will be deserialized from the
827f0b4cd1eSArgyrios Kyrtzidis   // AST file as needed.
828f0b4cd1eSArgyrios Kyrtzidis   // We need the external source to be set up before we read the AST, because
829f0b4cd1eSArgyrios Kyrtzidis   // eagerly-deserialized declarations may use it.
830dbafb6c3SRichard Smith   if (AST->Ctx)
831dbafb6c3SRichard Smith     AST->Ctx->setExternalSource(AST->Reader);
832f0b4cd1eSArgyrios Kyrtzidis 
8331b7ed91eSArgyrios Kyrtzidis   switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,
8342ec29367SArgyrios Kyrtzidis                           SourceLocation(), ASTReader::ARR_None)) {
8352c499f65SSebastian Redl   case ASTReader::Success:
836ce379752SArgyrios Kyrtzidis     break;
837ce379752SArgyrios Kyrtzidis 
8382c499f65SSebastian Redl   case ASTReader::Failure:
8397029ce1aSDouglas Gregor   case ASTReader::Missing:
840c9ad5fb6SDouglas Gregor   case ASTReader::OutOfDate:
841c9ad5fb6SDouglas Gregor   case ASTReader::VersionMismatch:
842c9ad5fb6SDouglas Gregor   case ASTReader::ConfigurationMismatch:
843c9ad5fb6SDouglas Gregor   case ASTReader::HadErrors:
844d03e823fSDouglas Gregor     AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
84549a2790fSCraig Topper     return nullptr;
846ce379752SArgyrios Kyrtzidis   }
847ce379752SArgyrios Kyrtzidis 
848adcd0268SBenjamin Kramer   AST->OriginalSourceFile = std::string(AST->Reader->getOriginalSourceFile());
849a8a50937SDaniel Dunbar 
850ce379752SArgyrios Kyrtzidis   PP.setCounterValue(Counter);
851ce379752SArgyrios Kyrtzidis 
8526fd55e06SDouglas Gregor   // Create an AST consumer, even though it isn't used.
853dbafb6c3SRichard Smith   if (ToLoad >= LoadASTOnly)
8546fd55e06SDouglas Gregor     AST->Consumer.reset(new ASTConsumer);
8556fd55e06SDouglas Gregor 
8562c499f65SSebastian Redl   // Create a semantic analysis object and tell the AST reader about it.
857dbafb6c3SRichard Smith   if (ToLoad >= LoadEverything) {
858dbafb6c3SRichard Smith     AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer));
8596fd55e06SDouglas Gregor     AST->TheSema->Initialize();
8601b7ed91eSArgyrios Kyrtzidis     AST->Reader->InitializeSema(*AST->TheSema);
861dbafb6c3SRichard Smith   }
8626fd55e06SDouglas Gregor 
8636b930967SDouglas Gregor   // Tell the diagnostic client that we have started a source file.
864dbafb6c3SRichard Smith   AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP);
8656b930967SDouglas Gregor 
8666f7382ddSDavid Blaikie   return AST;
867ce379752SArgyrios Kyrtzidis }
868764c0820SDaniel Dunbar 
8699fc8faf9SAdrian Prantl /// Add the given macro to the hash of all top-level entities.
AddDefinedMacroToHash(const Token & MacroNameTok,unsigned & Hash)8704f233181SEugene Zelenko static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
871560ce2c7SJonas Devlieghere   Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);
872200b3289SIlya Biryukov }
873200b3289SIlya Biryukov 
8744f233181SEugene Zelenko namespace {
8754f233181SEugene Zelenko 
8769fc8faf9SAdrian Prantl /// Preprocessor callback class that updates a hash value with the names
877df7a79a9SDouglas Gregor /// of all macros that have been defined by the translation unit.
878df7a79a9SDouglas Gregor class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
879df7a79a9SDouglas Gregor   unsigned &Hash;
880644dca07SDaniel Dunbar 
881644dca07SDaniel Dunbar public:
MacroDefinitionTrackerPPCallbacks(unsigned & Hash)882df7a79a9SDouglas Gregor   explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}
883df7a79a9SDouglas Gregor 
MacroDefined(const Token & MacroNameTok,const MacroDirective * MD)884afa7cb3aSCraig Topper   void MacroDefined(const Token &MacroNameTok,
885afa7cb3aSCraig Topper                     const MacroDirective *MD) override {
886200b3289SIlya Biryukov     AddDefinedMacroToHash(MacroNameTok, Hash);
887df7a79a9SDouglas Gregor   }
888df7a79a9SDouglas Gregor };
889df7a79a9SDouglas Gregor 
8904f233181SEugene Zelenko } // namespace
8914f233181SEugene Zelenko 
8929fc8faf9SAdrian Prantl /// Add the given declaration to the hash of all top-level entities.
AddTopLevelDeclarationToHash(Decl * D,unsigned & Hash)8934f233181SEugene Zelenko static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
894df7a79a9SDouglas Gregor   if (!D)
895df7a79a9SDouglas Gregor     return;
896df7a79a9SDouglas Gregor 
897df7a79a9SDouglas Gregor   DeclContext *DC = D->getDeclContext();
898df7a79a9SDouglas Gregor   if (!DC)
899df7a79a9SDouglas Gregor     return;
900df7a79a9SDouglas Gregor 
901df7a79a9SDouglas Gregor   if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
902df7a79a9SDouglas Gregor     return;
903df7a79a9SDouglas Gregor 
9044f233181SEugene Zelenko   if (const auto *ND = dyn_cast<NamedDecl>(D)) {
9054f233181SEugene Zelenko     if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {
906ca5c7be0SArgyrios Kyrtzidis       // For an unscoped enum include the enumerators in the hash since they
907ca5c7be0SArgyrios Kyrtzidis       // enter the top-level namespace.
908ca5c7be0SArgyrios Kyrtzidis       if (!EnumD->isScoped()) {
90923a6dcb3SAaron Ballman         for (const auto *EI : EnumD->enumerators()) {
91023a6dcb3SAaron Ballman           if (EI->getIdentifier())
911560ce2c7SJonas Devlieghere             Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);
912ca5c7be0SArgyrios Kyrtzidis         }
913ca5c7be0SArgyrios Kyrtzidis       }
914ca5c7be0SArgyrios Kyrtzidis     }
915ca5c7be0SArgyrios Kyrtzidis 
916df7a79a9SDouglas Gregor     if (ND->getIdentifier())
917560ce2c7SJonas Devlieghere       Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);
918df7a79a9SDouglas Gregor     else if (DeclarationName Name = ND->getDeclName()) {
919df7a79a9SDouglas Gregor       std::string NameStr = Name.getAsString();
920560ce2c7SJonas Devlieghere       Hash = llvm::djbHash(NameStr, Hash);
921df7a79a9SDouglas Gregor     }
922df7a79a9SDouglas Gregor     return;
923df7a79a9SDouglas Gregor   }
92448d88de2SArgyrios Kyrtzidis 
9254f233181SEugene Zelenko   if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {
9264f233181SEugene Zelenko     if (const Module *Mod = ImportD->getImportedModule()) {
92748d88de2SArgyrios Kyrtzidis       std::string ModName = Mod->getFullModuleName();
928560ce2c7SJonas Devlieghere       Hash = llvm::djbHash(ModName, Hash);
92948d88de2SArgyrios Kyrtzidis     }
93048d88de2SArgyrios Kyrtzidis     return;
93148d88de2SArgyrios Kyrtzidis   }
932df7a79a9SDouglas Gregor }
933df7a79a9SDouglas Gregor 
9344f233181SEugene Zelenko namespace {
9354f233181SEugene Zelenko 
936df7a79a9SDouglas Gregor class TopLevelDeclTrackerConsumer : public ASTConsumer {
937df7a79a9SDouglas Gregor   ASTUnit &Unit;
938df7a79a9SDouglas Gregor   unsigned &Hash;
939df7a79a9SDouglas Gregor 
940df7a79a9SDouglas Gregor public:
TopLevelDeclTrackerConsumer(ASTUnit & _Unit,unsigned & Hash)941df7a79a9SDouglas Gregor   TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
942df7a79a9SDouglas Gregor       : Unit(_Unit), Hash(Hash) {
943df7a79a9SDouglas Gregor     Hash = 0;
944df7a79a9SDouglas Gregor   }
945644dca07SDaniel Dunbar 
handleTopLevelDecl(Decl * D)946e54568d6SArgyrios Kyrtzidis   void handleTopLevelDecl(Decl *D) {
947516eec2dSArgyrios Kyrtzidis     if (!D)
948516eec2dSArgyrios Kyrtzidis       return;
949516eec2dSArgyrios Kyrtzidis 
950acc59c3eSTed Kremenek     // FIXME: Currently ObjC method declarations are incorrectly being
951acc59c3eSTed Kremenek     // reported as top-level declarations, even though their DeclContext
952acc59c3eSTed Kremenek     // is the containing ObjC @interface/@implementation.  This is a
953acc59c3eSTed Kremenek     // fundamental problem in the parser right now.
954acc59c3eSTed Kremenek     if (isa<ObjCMethodDecl>(D))
955e54568d6SArgyrios Kyrtzidis       return;
956df7a79a9SDouglas Gregor 
957df7a79a9SDouglas Gregor     AddTopLevelDeclarationToHash(D, Hash);
958e9db88f9SDouglas Gregor     Unit.addTopLevelDecl(D);
959e54568d6SArgyrios Kyrtzidis 
960e54568d6SArgyrios Kyrtzidis     handleFileLevelDecl(D);
961acc59c3eSTed Kremenek   }
962e54568d6SArgyrios Kyrtzidis 
handleFileLevelDecl(Decl * D)963e54568d6SArgyrios Kyrtzidis   void handleFileLevelDecl(Decl *D) {
964e54568d6SArgyrios Kyrtzidis     Unit.addFileLevelDecl(D);
9654f233181SEugene Zelenko     if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
966629afaefSAaron Ballman       for (auto *I : NSD->decls())
967629afaefSAaron Ballman         handleFileLevelDecl(I);
968e54568d6SArgyrios Kyrtzidis     }
969e54568d6SArgyrios Kyrtzidis   }
970e54568d6SArgyrios Kyrtzidis 
HandleTopLevelDecl(DeclGroupRef D)971afa7cb3aSCraig Topper   bool HandleTopLevelDecl(DeclGroupRef D) override {
9724f233181SEugene Zelenko     for (auto *TopLevelDecl : D)
9736a96ae5eSBenjamin Kramer       handleTopLevelDecl(TopLevelDecl);
974841dd886SArgyrios Kyrtzidis     return true;
975644dca07SDaniel Dunbar   }
976eaa4ade8SSebastian Redl 
977eaa4ade8SSebastian Redl   // We're not interested in "interesting" decls.
HandleInterestingDecl(DeclGroupRef)978afa7cb3aSCraig Topper   void HandleInterestingDecl(DeclGroupRef) override {}
979e54568d6SArgyrios Kyrtzidis 
HandleTopLevelDeclInObjCContainer(DeclGroupRef D)980afa7cb3aSCraig Topper   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
9814f233181SEugene Zelenko     for (auto *TopLevelDecl : D)
9826a96ae5eSBenjamin Kramer       handleTopLevelDecl(TopLevelDecl);
983e54568d6SArgyrios Kyrtzidis   }
9840db720f0SArgyrios Kyrtzidis 
GetASTMutationListener()985afa7cb3aSCraig Topper   ASTMutationListener *GetASTMutationListener() override {
9861c7455f4SArgyrios Kyrtzidis     return Unit.getASTMutationListener();
9871c7455f4SArgyrios Kyrtzidis   }
9881c7455f4SArgyrios Kyrtzidis 
GetASTDeserializationListener()989afa7cb3aSCraig Topper   ASTDeserializationListener *GetASTDeserializationListener() override {
9900db720f0SArgyrios Kyrtzidis     return Unit.getDeserializationListener();
9910db720f0SArgyrios Kyrtzidis   }
992644dca07SDaniel Dunbar };
993644dca07SDaniel Dunbar 
994644dca07SDaniel Dunbar class TopLevelDeclTrackerAction : public ASTFrontendAction {
995644dca07SDaniel Dunbar public:
996644dca07SDaniel Dunbar   ASTUnit &Unit;
997644dca07SDaniel Dunbar 
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)9986beb6aa8SDavid Blaikie   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
999afa7cb3aSCraig Topper                                                  StringRef InFile) override {
1000df7a79a9SDouglas Gregor     CI.getPreprocessor().addPPCallbacks(
10012b3d49b6SJonas Devlieghere         std::make_unique<MacroDefinitionTrackerPPCallbacks>(
1002b8a70530SCraig Topper                                            Unit.getCurrentTopLevelHashValue()));
10032b3d49b6SJonas Devlieghere     return std::make_unique<TopLevelDeclTrackerConsumer>(
10046beb6aa8SDavid Blaikie         Unit, Unit.getCurrentTopLevelHashValue());
1005764c0820SDaniel Dunbar   }
1006764c0820SDaniel Dunbar 
1007764c0820SDaniel Dunbar public:
TopLevelDeclTrackerAction(ASTUnit & _Unit)1008644dca07SDaniel Dunbar   TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
1009644dca07SDaniel Dunbar 
hasCodeCompletionSupport() const1010afa7cb3aSCraig Topper   bool hasCodeCompletionSupport() const override { return false; }
10114f233181SEugene Zelenko 
getTranslationUnitKind()1012afa7cb3aSCraig Topper   TranslationUnitKind getTranslationUnitKind() override {
101369f74f80SDouglas Gregor     return Unit.getTranslationUnitKind();
1014028d3e4dSDouglas Gregor   }
1015764c0820SDaniel Dunbar };
1016764c0820SDaniel Dunbar 
1017200b3289SIlya Biryukov class ASTUnitPreambleCallbacks : public PreambleCallbacks {
101865745dc0SBenjamin Kramer public:
getHash() const1019200b3289SIlya Biryukov   unsigned getHash() const { return Hash; }
102065745dc0SBenjamin Kramer 
takeTopLevelDecls()1021200b3289SIlya Biryukov   std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
102265745dc0SBenjamin Kramer 
takeTopLevelDeclIDs()1023200b3289SIlya Biryukov   std::vector<serialization::DeclID> takeTopLevelDeclIDs() {
1024200b3289SIlya Biryukov     return std::move(TopLevelDeclIDs);
1025df7a79a9SDouglas Gregor   }
102648c8cd3fSDouglas Gregor 
AfterPCHEmitted(ASTWriter & Writer)1027200b3289SIlya Biryukov   void AfterPCHEmitted(ASTWriter &Writer) override {
1028200b3289SIlya Biryukov     TopLevelDeclIDs.reserve(TopLevelDecls.size());
10294f233181SEugene Zelenko     for (const auto *D : TopLevelDecls) {
1030200b3289SIlya Biryukov       // Invalid top-level decls may not have been serialized.
1031200b3289SIlya Biryukov       if (D->isInvalidDecl())
1032200b3289SIlya Biryukov         continue;
1033200b3289SIlya Biryukov       TopLevelDeclIDs.push_back(Writer.getDeclID(D));
1034200b3289SIlya Biryukov     }
1035200b3289SIlya Biryukov   }
1036200b3289SIlya Biryukov 
HandleTopLevelDecl(DeclGroupRef DG)1037200b3289SIlya Biryukov   void HandleTopLevelDecl(DeclGroupRef DG) override {
10384f233181SEugene Zelenko     for (auto *D : DG) {
103948c8cd3fSDouglas Gregor       // FIXME: Currently ObjC method declarations are incorrectly being
104048c8cd3fSDouglas Gregor       // reported as top-level declarations, even though their DeclContext
104148c8cd3fSDouglas Gregor       // is the containing ObjC @interface/@implementation.  This is a
104248c8cd3fSDouglas Gregor       // fundamental problem in the parser right now.
104348c8cd3fSDouglas Gregor       if (isa<ObjCMethodDecl>(D))
104448c8cd3fSDouglas Gregor         continue;
1045df7a79a9SDouglas Gregor       AddTopLevelDeclarationToHash(D, Hash);
1046e9db88f9SDouglas Gregor       TopLevelDecls.push_back(D);
1047e9db88f9SDouglas Gregor     }
1048e9db88f9SDouglas Gregor   }
1049e9db88f9SDouglas Gregor 
createPPCallbacks()105041e90bcbSIlya Biryukov   std::unique_ptr<PPCallbacks> createPPCallbacks() override {
10512b3d49b6SJonas Devlieghere     return std::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash);
1052acfbbd77SArgyrios Kyrtzidis   }
105365745dc0SBenjamin Kramer 
1054200b3289SIlya Biryukov private:
1055200b3289SIlya Biryukov   unsigned Hash = 0;
1056200b3289SIlya Biryukov   std::vector<Decl *> TopLevelDecls;
1057200b3289SIlya Biryukov   std::vector<serialization::DeclID> TopLevelDeclIDs;
1058200b3289SIlya Biryukov   llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;
105948c8cd3fSDouglas Gregor };
106048c8cd3fSDouglas Gregor 
10614f233181SEugene Zelenko } // namespace
106248c8cd3fSDouglas Gregor 
isNonDriverDiag(const StoredDiagnostic & StoredDiag)10631ce5d800SBenjamin Kramer static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {
10641ce5d800SBenjamin Kramer   return StoredDiag.getLocation().isValid();
10651ce5d800SBenjamin Kramer }
10661ce5d800SBenjamin Kramer 
10671ce5d800SBenjamin Kramer static void
checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> & StoredDiags)10681ce5d800SBenjamin Kramer checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {
106938bacf34SArgyrios Kyrtzidis   // Get rid of stored diagnostics except the ones from the driver which do not
107038bacf34SArgyrios Kyrtzidis   // have a source location.
1071d245f2e8SKazu Hirata   llvm::erase_if(StoredDiags, isNonDriverDiag);
107238bacf34SArgyrios Kyrtzidis }
107338bacf34SArgyrios Kyrtzidis 
checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & StoredDiagnostics,SourceManager & SM)107438bacf34SArgyrios Kyrtzidis static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
107538bacf34SArgyrios Kyrtzidis                                                               StoredDiagnostics,
107638bacf34SArgyrios Kyrtzidis                                   SourceManager &SM) {
107738bacf34SArgyrios Kyrtzidis   // The stored diagnostic has the old source manager in it; update
107838bacf34SArgyrios Kyrtzidis   // the locations to refer into the new source manager. Since we've
107938bacf34SArgyrios Kyrtzidis   // been careful to make sure that the source manager's state
108038bacf34SArgyrios Kyrtzidis   // before and after are identical, so that we can reuse the source
108138bacf34SArgyrios Kyrtzidis   // location itself.
10824f233181SEugene Zelenko   for (auto &SD : StoredDiagnostics) {
10836a96ae5eSBenjamin Kramer     if (SD.getLocation().isValid()) {
10846a96ae5eSBenjamin Kramer       FullSourceLoc Loc(SD.getLocation(), SM);
10856a96ae5eSBenjamin Kramer       SD.setLocation(Loc);
108638bacf34SArgyrios Kyrtzidis     }
108738bacf34SArgyrios Kyrtzidis   }
108838bacf34SArgyrios Kyrtzidis }
108938bacf34SArgyrios Kyrtzidis 
1090aa21cc40SDouglas Gregor /// Parse the source file into a translation unit using the given compiler
1091aa21cc40SDouglas Gregor /// invocation, replacing the current translation unit.
1092aa21cc40SDouglas Gregor ///
1093aa21cc40SDouglas Gregor /// \returns True if a failure occurred that causes the ASTUnit not to
1094aa21cc40SDouglas Gregor /// contain any translation-unit information, false otherwise.
Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)1095bb165fb0SAdrian Prantl bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
1096af69e40cSIlya Biryukov                     std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
1097fc51490bSJonas Devlieghere                     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
109832482080SRafael Espindola   if (!Invocation)
1099aa21cc40SDouglas Gregor     return true;
1100aa21cc40SDouglas Gregor 
11011da7eac8SDuncan P. N. Exon Smith   if (VFS && FileMgr)
1102db8a7422SDuncan P. N. Exon Smith     assert(VFS == &FileMgr->getVirtualFileSystem() &&
11031da7eac8SDuncan P. N. Exon Smith            "VFS passed to Parse and VFS in FileMgr are different");
11041da7eac8SDuncan P. N. Exon Smith 
1105417085acSIlya Biryukov   auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);
1106417085acSIlya Biryukov   if (OverrideMainBuffer) {
1107417085acSIlya Biryukov     assert(Preamble &&
1108417085acSIlya Biryukov            "No preamble was built, but OverrideMainBuffer is not null");
1109417085acSIlya Biryukov     Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());
11101da7eac8SDuncan P. N. Exon Smith     // VFS may have changed...
1111417085acSIlya Biryukov   }
1112417085acSIlya Biryukov 
1113764c0820SDaniel Dunbar   // Create the compiler instance to use for building the AST.
1114bb165fb0SAdrian Prantl   std::unique_ptr<CompilerInstance> Clang(
1115d6da1a09SBenjamin Kramer       new CompilerInstance(std::move(PCHContainerOps)));
11161da7eac8SDuncan P. N. Exon Smith 
1117fd14a1f6SLemonBoy   // Clean up on error, disengage it if the function returns successfully.
1118fd14a1f6SLemonBoy   auto CleanOnError = llvm::make_scope_exit([&]() {
1119fd14a1f6SLemonBoy     // Remove the overridden buffer we used for the preamble.
1120fd14a1f6SLemonBoy     SavedMainFileBuffer = nullptr;
1121fd14a1f6SLemonBoy 
1122fd14a1f6SLemonBoy     // Keep the ownership of the data in the ASTUnit because the client may
1123fd14a1f6SLemonBoy     // want to see the diagnostics.
1124fd14a1f6SLemonBoy     transferASTDataFromCompilerInstance(*Clang);
1125fd14a1f6SLemonBoy     FailedParseDiagnostics.swap(StoredDiagnostics);
1126fd14a1f6SLemonBoy     StoredDiagnostics.clear();
1127fd14a1f6SLemonBoy     NumStoredDiagnosticsFromDriver = 0;
1128fd14a1f6SLemonBoy   });
1129fd14a1f6SLemonBoy 
11301da7eac8SDuncan P. N. Exon Smith   // Ensure that Clang has a FileManager with the right VFS, which may have
11311da7eac8SDuncan P. N. Exon Smith   // changed above in AddImplicitPreamble.  If VFS is nullptr, rely on
11321da7eac8SDuncan P. N. Exon Smith   // createFileManager to create one.
1133db8a7422SDuncan P. N. Exon Smith   if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS)
11341da7eac8SDuncan P. N. Exon Smith     Clang->setFileManager(&*FileMgr);
11351da7eac8SDuncan P. N. Exon Smith   else
11361da7eac8SDuncan P. N. Exon Smith     FileMgr = Clang->createFileManager(std::move(VFS));
113784de4a17STed Kremenek 
113884de4a17STed Kremenek   // Recover resources if we crash before exiting this method.
1139022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1140022a4904STed Kremenek     CICleanup(Clang.get());
114184de4a17STed Kremenek 
1142417085acSIlya Biryukov   Clang->setInvocation(CCInvocation);
1143adcd0268SBenjamin Kramer   OriginalSourceFile =
1144adcd0268SBenjamin Kramer       std::string(Clang->getFrontendOpts().Inputs[0].getFile());
1145764c0820SDaniel Dunbar 
11468e984da8SDouglas Gregor   // Set up diagnostics, capturing any diagnostics that would
11478e984da8SDouglas Gregor   // otherwise be dropped.
114884de4a17STed Kremenek   Clang->setDiagnostics(&getDiagnostics());
1149764c0820SDaniel Dunbar 
1150764c0820SDaniel Dunbar   // Create the target instance.
115114a7296cSoToToT   if (!Clang->createTarget())
1152aa21cc40SDouglas Gregor     return true;
1153764c0820SDaniel Dunbar 
115484de4a17STed Kremenek   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1155764c0820SDaniel Dunbar          "Invocation must have exactly one source file!");
115640c0efa5SRichard Smith   assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
115740c0efa5SRichard Smith              InputKind::Source &&
1158764c0820SDaniel Dunbar          "FIXME: AST inputs not yet supported here!");
115940c0efa5SRichard Smith   assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
116009d890d7SRainer Orth              Language::LLVM_IR &&
11619507f9ccSDaniel Dunbar          "IR inputs not support here!");
1162764c0820SDaniel Dunbar 
1163aa21cc40SDouglas Gregor   // Configure the various subsystems.
1164269d840eSAlp Toker   LangOpts = Clang->getInvocation().LangOpts;
116584de4a17STed Kremenek   FileSystemOpts = Clang->getFileSystemOpts();
1166346066b6SErik Verbruggen 
1167346066b6SErik Verbruggen   ResetForParse();
1168346066b6SErik Verbruggen 
11696d7833f1SArgyrios Kyrtzidis   SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
11706d7833f1SArgyrios Kyrtzidis                                 UserFilesAreVolatile);
11717b02b583SDouglas Gregor   if (!OverrideMainBuffer) {
117238bacf34SArgyrios Kyrtzidis     checkAndRemoveNonDriverDiags(StoredDiagnostics);
11737b02b583SDouglas Gregor     TopLevelDeclsInPreamble.clear();
11747b02b583SDouglas Gregor   }
1175d9a30af2SDouglas Gregor 
1176764c0820SDaniel Dunbar   // Create the source manager.
117784de4a17STed Kremenek   Clang->setSourceManager(&getSourceManager());
1178764c0820SDaniel Dunbar 
11793f4bea06SDouglas Gregor   // If the main file has been overridden due to the use of a preamble,
11803f4bea06SDouglas Gregor   // make that override happen and introduce the preamble.
11813f4bea06SDouglas Gregor   if (OverrideMainBuffer) {
1182d9a30af2SDouglas Gregor     // The stored diagnostic has the old source manager in it; update
1183d9a30af2SDouglas Gregor     // the locations to refer into the new source manager. Since we've
1184d9a30af2SDouglas Gregor     // been careful to make sure that the source manager's state
1185d9a30af2SDouglas Gregor     // before and after are identical, so that we can reuse the source
1186d9a30af2SDouglas Gregor     // location itself.
118738bacf34SArgyrios Kyrtzidis     checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());
11887bb8af61SDouglas Gregor 
11897bb8af61SDouglas Gregor     // Keep track of the override buffer;
119032482080SRafael Espindola     SavedMainFileBuffer = std::move(OverrideMainBuffer);
11913f4bea06SDouglas Gregor   }
11923f4bea06SDouglas Gregor 
1193b8984329SAhmed Charles   std::unique_ptr<TopLevelDeclTrackerAction> Act(
1194022a4904STed Kremenek       new TopLevelDeclTrackerAction(*this));
1195022a4904STed Kremenek 
1196022a4904STed Kremenek   // Recover resources if we crash before exiting this method.
1197022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
1198022a4904STed Kremenek     ActCleanup(Act.get());
1199022a4904STed Kremenek 
120032fbe312SDouglas Gregor   if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
1201fd14a1f6SLemonBoy     return true;
1202764c0820SDaniel Dunbar 
120326b8f78fSRichard Smith   if (SavedMainFileBuffer)
120424c55228SArgyrios Kyrtzidis     TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
120524c55228SArgyrios Kyrtzidis                                PreambleDiagnostics, StoredDiagnostics);
1206efe6fa50SErik Verbruggen   else
1207efe6fa50SErik Verbruggen     PreambleSrcLocCache.clear();
1208925296b4SDouglas Gregor 
12090e828958SJF Bastien   if (llvm::Error Err = Act->Execute()) {
12100e828958SJF Bastien     consumeError(std::move(Err)); // FIXME this drops errors on the floor.
1211fd14a1f6SLemonBoy     return true;
12120e828958SJF Bastien   }
1213764c0820SDaniel Dunbar 
1214ac1cc934SArgyrios Kyrtzidis   transferASTDataFromCompilerInstance(*Clang);
1215764c0820SDaniel Dunbar 
1216644dca07SDaniel Dunbar   Act->EndSourceFile();
1217764c0820SDaniel Dunbar 
1218ac1cc934SArgyrios Kyrtzidis   FailedParseDiagnostics.clear();
1219ac1cc934SArgyrios Kyrtzidis 
1220fd14a1f6SLemonBoy   CleanOnError.release();
1221fd14a1f6SLemonBoy 
1222aa21cc40SDouglas Gregor   return false;
1223aa21cc40SDouglas Gregor }
1224aa21cc40SDouglas Gregor 
122524c55228SArgyrios Kyrtzidis static std::pair<unsigned, unsigned>
makeStandaloneRange(CharSourceRange Range,const SourceManager & SM,const LangOptions & LangOpts)122624c55228SArgyrios Kyrtzidis makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,
122724c55228SArgyrios Kyrtzidis                     const LangOptions &LangOpts) {
122824c55228SArgyrios Kyrtzidis   CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts);
122924c55228SArgyrios Kyrtzidis   unsigned Offset = SM.getFileOffset(FileRange.getBegin());
123024c55228SArgyrios Kyrtzidis   unsigned EndOffset = SM.getFileOffset(FileRange.getEnd());
123124c55228SArgyrios Kyrtzidis   return std::make_pair(Offset, EndOffset);
123224c55228SArgyrios Kyrtzidis }
123324c55228SArgyrios Kyrtzidis 
makeStandaloneFixIt(const SourceManager & SM,const LangOptions & LangOpts,const FixItHint & InFix)12341a6e0a9bSBenjamin Kramer static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,
123524c55228SArgyrios Kyrtzidis                                                     const LangOptions &LangOpts,
12361a6e0a9bSBenjamin Kramer                                                     const FixItHint &InFix) {
12371a6e0a9bSBenjamin Kramer   ASTUnit::StandaloneFixIt OutFix;
123824c55228SArgyrios Kyrtzidis   OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);
123924c55228SArgyrios Kyrtzidis   OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM,
124024c55228SArgyrios Kyrtzidis                                                LangOpts);
124124c55228SArgyrios Kyrtzidis   OutFix.CodeToInsert = InFix.CodeToInsert;
124224c55228SArgyrios Kyrtzidis   OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;
12431a6e0a9bSBenjamin Kramer   return OutFix;
124424c55228SArgyrios Kyrtzidis }
124524c55228SArgyrios Kyrtzidis 
12461a6e0a9bSBenjamin Kramer static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions & LangOpts,const StoredDiagnostic & InDiag)12471a6e0a9bSBenjamin Kramer makeStandaloneDiagnostic(const LangOptions &LangOpts,
12481a6e0a9bSBenjamin Kramer                          const StoredDiagnostic &InDiag) {
12491a6e0a9bSBenjamin Kramer   ASTUnit::StandaloneDiagnostic OutDiag;
125024c55228SArgyrios Kyrtzidis   OutDiag.ID = InDiag.getID();
125124c55228SArgyrios Kyrtzidis   OutDiag.Level = InDiag.getLevel();
1252adcd0268SBenjamin Kramer   OutDiag.Message = std::string(InDiag.getMessage());
125324c55228SArgyrios Kyrtzidis   OutDiag.LocOffset = 0;
125424c55228SArgyrios Kyrtzidis   if (InDiag.getLocation().isInvalid())
12551a6e0a9bSBenjamin Kramer     return OutDiag;
125624c55228SArgyrios Kyrtzidis   const SourceManager &SM = InDiag.getLocation().getManager();
125724c55228SArgyrios Kyrtzidis   SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());
1258adcd0268SBenjamin Kramer   OutDiag.Filename = std::string(SM.getFilename(FileLoc));
125924c55228SArgyrios Kyrtzidis   if (OutDiag.Filename.empty())
12601a6e0a9bSBenjamin Kramer     return OutDiag;
126124c55228SArgyrios Kyrtzidis   OutDiag.LocOffset = SM.getFileOffset(FileLoc);
12624f233181SEugene Zelenko   for (const auto &Range : InDiag.getRanges())
12636a96ae5eSBenjamin Kramer     OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));
12644f233181SEugene Zelenko   for (const auto &FixIt : InDiag.getFixIts())
12656a96ae5eSBenjamin Kramer     OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));
12661a6e0a9bSBenjamin Kramer 
12671a6e0a9bSBenjamin Kramer   return OutDiag;
126824c55228SArgyrios Kyrtzidis }
126924c55228SArgyrios Kyrtzidis 
12709fc8faf9SAdrian Prantl /// Attempt to build or re-use a precompiled preamble when (re-)parsing
12714dde7498SDouglas Gregor /// the source file.
12724dde7498SDouglas Gregor ///
12734dde7498SDouglas Gregor /// This routine will compute the preamble of the main source file. If a
12744dde7498SDouglas Gregor /// non-trivial preamble is found, it will precompile that preamble into a
12754dde7498SDouglas Gregor /// precompiled header so that the precompiled preamble can be used to reduce
12764dde7498SDouglas Gregor /// reparsing time. If a precompiled preamble has already been constructed,
12774dde7498SDouglas Gregor /// this routine will determine if it is still valid and, if so, avoid
12784dde7498SDouglas Gregor /// rebuilding the precompiled preamble.
12794dde7498SDouglas Gregor ///
1280028d3e4dSDouglas Gregor /// \param AllowRebuild When true (the default), this routine is
1281028d3e4dSDouglas Gregor /// allowed to rebuild the precompiled preamble if it is found to be
1282028d3e4dSDouglas Gregor /// out-of-date.
1283028d3e4dSDouglas Gregor ///
1284028d3e4dSDouglas Gregor /// \param MaxLines When non-zero, the maximum number of lines that
1285028d3e4dSDouglas Gregor /// can occur within the preamble.
1286028d3e4dSDouglas Gregor ///
12876481ef1fSDouglas Gregor /// \returns If the precompiled preamble can be used, returns a newly-allocated
12886481ef1fSDouglas Gregor /// buffer that should be used in place of the main file when doing so.
12896481ef1fSDouglas Gregor /// Otherwise, returns a NULL pointer.
12902346a375SRafael Espindola std::unique_ptr<llvm::MemoryBuffer>
getMainBufferWithPrecompiledPreamble(std::shared_ptr<PCHContainerOperations> PCHContainerOps,CompilerInvocation & PreambleInvocationIn,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,bool AllowRebuild,unsigned MaxLines)12912346a375SRafael Espindola ASTUnit::getMainBufferWithPrecompiledPreamble(
1292bb165fb0SAdrian Prantl     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
12936e89528cSIvan Donchevskii     CompilerInvocation &PreambleInvocationIn,
1294fc51490bSJonas Devlieghere     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,
1295028d3e4dSDouglas Gregor     unsigned MaxLines) {
1296200b3289SIlya Biryukov   auto MainFilePath =
1297200b3289SIlya Biryukov       PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
1298200b3289SIlya Biryukov   std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =
1299200b3289SIlya Biryukov       getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),
13002ebe3a02SIvan Donchevskii                                         MainFilePath, UserFilesAreVolatile);
1301200b3289SIlya Biryukov   if (!MainFileBuffer)
130249a2790fSCraig Topper     return nullptr;
13034dde7498SDouglas Gregor 
13044c55c3b6SDuncan P. N. Exon Smith   PreambleBounds Bounds = ComputePreambleBounds(
13054c55c3b6SDuncan P. N. Exon Smith       *PreambleInvocationIn.getLangOpts(), *MainFileBuffer, MaxLines);
1306200b3289SIlya Biryukov   if (!Bounds.Size)
1307200b3289SIlya Biryukov     return nullptr;
13084dde7498SDouglas Gregor 
1309200b3289SIlya Biryukov   if (Preamble) {
1310f4d02fbeSDuncan P. N. Exon Smith     if (Preamble->CanReuse(PreambleInvocationIn, *MainFileBuffer, Bounds,
1311f4d02fbeSDuncan P. N. Exon Smith                            *VFS)) {
1312d9a30af2SDouglas Gregor       // Okay! We can re-use the precompiled preamble.
1313d9a30af2SDouglas Gregor 
1314d9a30af2SDouglas Gregor       // Set the state of the diagnostic object to mimic its state
1315d9a30af2SDouglas Gregor       // after parsing the preamble.
1316d9a30af2SDouglas Gregor       getDiagnostics().Reset();
131736e3b5c7SDouglas Gregor       ProcessWarningOptions(getDiagnostics(),
1318200b3289SIlya Biryukov                             PreambleInvocationIn.getDiagnosticOpts());
1319d9a30af2SDouglas Gregor       getDiagnostics().setNumWarnings(NumWarningsInPreamble);
1320d9a30af2SDouglas Gregor 
1321295c19e9SNikolai Kosjar       PreambleRebuildCountdown = 1;
1322200b3289SIlya Biryukov       return MainFileBuffer;
1323200b3289SIlya Biryukov     } else {
1324200b3289SIlya Biryukov       Preamble.reset();
1325200b3289SIlya Biryukov       PreambleDiagnostics.clear();
1326200b3289SIlya Biryukov       TopLevelDeclsInPreamble.clear();
1327a44c432bSAlex Lorenz       PreambleSrcLocCache.clear();
1328295c19e9SNikolai Kosjar       PreambleRebuildCountdown = 1;
1329200b3289SIlya Biryukov     }
1330bb420abdSDouglas Gregor   }
1331bb420abdSDouglas Gregor 
1332bb420abdSDouglas Gregor   // If the preamble rebuild counter > 1, it's because we previously
1333bb420abdSDouglas Gregor   // failed to build a preamble and we're not yet ready to try
1334bb420abdSDouglas Gregor   // again. Decrement the counter and return a failure.
1335295c19e9SNikolai Kosjar   if (PreambleRebuildCountdown > 1) {
1336295c19e9SNikolai Kosjar     --PreambleRebuildCountdown;
133749a2790fSCraig Topper     return nullptr;
13384dde7498SDouglas Gregor   }
13394dde7498SDouglas Gregor 
1340200b3289SIlya Biryukov   assert(!Preamble && "No Preamble should be stored at that point");
1341200b3289SIlya Biryukov   // If we aren't allowed to rebuild the precompiled preamble, just
1342200b3289SIlya Biryukov   // return now.
1343200b3289SIlya Biryukov   if (!AllowRebuild)
134449a2790fSCraig Topper     return nullptr;
1345200b3289SIlya Biryukov 
1346295c19e9SNikolai Kosjar   ++PreambleCounter;
1347295c19e9SNikolai Kosjar 
1348200b3289SIlya Biryukov   SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone;
1349200b3289SIlya Biryukov   SmallVector<StoredDiagnostic, 4> NewPreambleDiags;
1350f81d46f4SIlya Biryukov   ASTUnitPreambleCallbacks Callbacks;
1351200b3289SIlya Biryukov   {
1352200b3289SIlya Biryukov     llvm::Optional<CaptureDroppedDiagnostics> Capture;
13538edd8da4SNikolai Kosjar     if (CaptureDiagnostics != CaptureDiagsKind::None)
13548edd8da4SNikolai Kosjar       Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags,
1355200b3289SIlya Biryukov                       &NewPreambleDiagsStandalone);
1356e10f0e56SDouglas Gregor 
13574dde7498SDouglas Gregor     // We did not previously compute a preamble, or it can't be reused anyway.
135816896c45SDouglas Gregor     SimpleTimer PreambleTimer(WantTiming);
135916896c45SDouglas Gregor     PreambleTimer.setOutput("Precompiling preamble");
1360be2d8c60SDouglas Gregor 
13616e89528cSIvan Donchevskii     const bool PreviousSkipFunctionBodies =
13626e89528cSIvan Donchevskii         PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;
13636e89528cSIvan Donchevskii     if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)
13646e89528cSIvan Donchevskii       PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;
13656e89528cSIvan Donchevskii 
1366200b3289SIlya Biryukov     llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
1367200b3289SIlya Biryukov         PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
1368417085acSIlya Biryukov         PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
13696e89528cSIvan Donchevskii 
13706e89528cSIvan Donchevskii     PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =
13716e89528cSIvan Donchevskii         PreviousSkipFunctionBodies;
13726e89528cSIvan Donchevskii 
1373200b3289SIlya Biryukov     if (NewPreamble) {
1374200b3289SIlya Biryukov       Preamble = std::move(*NewPreamble);
1375295c19e9SNikolai Kosjar       PreambleRebuildCountdown = 1;
1376200b3289SIlya Biryukov     } else {
1377200b3289SIlya Biryukov       switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {
1378200b3289SIlya Biryukov       case BuildPreambleError::CouldntCreateTempFile:
1379200b3289SIlya Biryukov         // Try again next time.
1380295c19e9SNikolai Kosjar         PreambleRebuildCountdown = 1;
1381f81d46f4SIlya Biryukov         return nullptr;
1382200b3289SIlya Biryukov       case BuildPreambleError::CouldntCreateTargetInfo:
1383200b3289SIlya Biryukov       case BuildPreambleError::BeginSourceFileFailed:
1384200b3289SIlya Biryukov       case BuildPreambleError::CouldntEmitPCH:
13852917526fSIlya Biryukov       case BuildPreambleError::BadInputs:
1386200b3289SIlya Biryukov         // These erros are more likely to repeat, retry after some period.
1387295c19e9SNikolai Kosjar         PreambleRebuildCountdown = DefaultPreambleRebuildInterval;
138849a2790fSCraig Topper         return nullptr;
1389be2d8c60SDouglas Gregor       }
1390f81d46f4SIlya Biryukov       llvm_unreachable("unexpected BuildPreambleError");
1391f81d46f4SIlya Biryukov     }
1392200b3289SIlya Biryukov   }
1393be2d8c60SDouglas Gregor 
1394200b3289SIlya Biryukov   assert(Preamble && "Preamble wasn't built");
1395be2d8c60SDouglas Gregor 
1396e9db88f9SDouglas Gregor   TopLevelDecls.clear();
1397200b3289SIlya Biryukov   TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs();
1398200b3289SIlya Biryukov   PreambleTopLevelHashValue = Callbacks.getHash();
1399be2d8c60SDouglas Gregor 
1400d9a30af2SDouglas Gregor   NumWarningsInPreamble = getDiagnostics().getNumWarnings();
14010e11955cSDouglas Gregor 
1402200b3289SIlya Biryukov   checkAndRemoveNonDriverDiags(NewPreambleDiags);
1403200b3289SIlya Biryukov   StoredDiagnostics = std::move(NewPreambleDiags);
1404200b3289SIlya Biryukov   PreambleDiagnostics = std::move(NewPreambleDiagsStandalone);
1405df7a79a9SDouglas Gregor 
1406df7a79a9SDouglas Gregor   // If the hash of top-level entities differs from the hash of the top-level
1407df7a79a9SDouglas Gregor   // entities the last time we rebuilt the preamble, clear out the completion
1408df7a79a9SDouglas Gregor   // cache.
1409df7a79a9SDouglas Gregor   if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {
1410df7a79a9SDouglas Gregor     CompletionCacheTopLevelHashValue = 0;
1411df7a79a9SDouglas Gregor     PreambleTopLevelHashValue = CurrentTopLevelHashValue;
1412df7a79a9SDouglas Gregor   }
1413df7a79a9SDouglas Gregor 
1414200b3289SIlya Biryukov   return MainFileBuffer;
1415be2d8c60SDouglas Gregor }
1416aa21cc40SDouglas Gregor 
RealizeTopLevelDeclsFromPreamble()1417e9db88f9SDouglas Gregor void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
1418200b3289SIlya Biryukov   assert(Preamble && "Should only be called when preamble was built");
1419200b3289SIlya Biryukov 
1420e9db88f9SDouglas Gregor   std::vector<Decl *> Resolved;
1421e9db88f9SDouglas Gregor   Resolved.reserve(TopLevelDeclsInPreamble.size());
1422e9db88f9SDouglas Gregor   ExternalASTSource &Source = *getASTContext().getExternalSource();
14234f233181SEugene Zelenko   for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {
1424e9db88f9SDouglas Gregor     // Resolve the declaration ID to an actual declaration, possibly
1425e9db88f9SDouglas Gregor     // deserializing the declaration in the process.
14266a96ae5eSBenjamin Kramer     if (Decl *D = Source.GetExternalDecl(TopLevelDecl))
1427e9db88f9SDouglas Gregor       Resolved.push_back(D);
1428e9db88f9SDouglas Gregor   }
1429e9db88f9SDouglas Gregor   TopLevelDeclsInPreamble.clear();
1430e9db88f9SDouglas Gregor   TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
1431e9db88f9SDouglas Gregor }
1432e9db88f9SDouglas Gregor 
transferASTDataFromCompilerInstance(CompilerInstance & CI)1433ac1cc934SArgyrios Kyrtzidis void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
1434749323faSBen Langmuir   // Steal the created target, context, and preprocessor if they have been
1435749323faSBen Langmuir   // created.
1436749323faSBen Langmuir   assert(CI.hasInvocation() && "missing invocation");
1437269d840eSAlp Toker   LangOpts = CI.getInvocation().LangOpts;
1438ec99b5eeSDavid Blaikie   TheSema = CI.takeSema();
14396beb6aa8SDavid Blaikie   Consumer = CI.takeASTConsumer();
1440532fdc0dSBen Langmuir   if (CI.hasASTContext())
1441ac1cc934SArgyrios Kyrtzidis     Ctx = &CI.getASTContext();
1442532fdc0dSBen Langmuir   if (CI.hasPreprocessor())
144341565463SDavid Blaikie     PP = CI.getPreprocessorPtr();
144449a2790fSCraig Topper   CI.setSourceManager(nullptr);
144549a2790fSCraig Topper   CI.setFileManager(nullptr);
1446532fdc0dSBen Langmuir   if (CI.hasTarget())
1447ac1cc934SArgyrios Kyrtzidis     Target = &CI.getTarget();
144820d51b2fSDuncan P. N. Exon Smith   Reader = CI.getASTReader();
1449dc9fdaf2SArgyrios Kyrtzidis   HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
1450ac1cc934SArgyrios Kyrtzidis }
1451ac1cc934SArgyrios Kyrtzidis 
getMainFileName() const14520e62c1ccSChris Lattner StringRef ASTUnit::getMainFileName() const {
1453928e1fdeSArgyrios Kyrtzidis   if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) {
1454928e1fdeSArgyrios Kyrtzidis     const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0];
1455928e1fdeSArgyrios Kyrtzidis     if (Input.isFile())
1456928e1fdeSArgyrios Kyrtzidis       return Input.getFile();
1457928e1fdeSArgyrios Kyrtzidis     else
145851d1d585SDuncan P. N. Exon Smith       return Input.getBuffer().getBufferIdentifier();
1459928e1fdeSArgyrios Kyrtzidis   }
1460928e1fdeSArgyrios Kyrtzidis 
1461928e1fdeSArgyrios Kyrtzidis   if (SourceMgr) {
1462928e1fdeSArgyrios Kyrtzidis     if (const FileEntry *
1463928e1fdeSArgyrios Kyrtzidis           FE = SourceMgr->getFileEntryForID(SourceMgr->getMainFileID()))
1464928e1fdeSArgyrios Kyrtzidis       return FE->getName();
1465928e1fdeSArgyrios Kyrtzidis   }
1466928e1fdeSArgyrios Kyrtzidis 
14674f233181SEugene Zelenko   return {};
146816896c45SDouglas Gregor }
146916896c45SDouglas Gregor 
getASTFileName() const147037f2ab48SArgyrios Kyrtzidis StringRef ASTUnit::getASTFileName() const {
147137f2ab48SArgyrios Kyrtzidis   if (!isMainFileAST())
14724f233181SEugene Zelenko     return {};
147337f2ab48SArgyrios Kyrtzidis 
147437f2ab48SArgyrios Kyrtzidis   serialization::ModuleFile &
147537f2ab48SArgyrios Kyrtzidis     Mod = Reader->getModuleManager().getPrimaryModule();
147637f2ab48SArgyrios Kyrtzidis   return Mod.FileName;
147737f2ab48SArgyrios Kyrtzidis }
147837f2ab48SArgyrios Kyrtzidis 
1479ea4395ebSDavid Blaikie std::unique_ptr<ASTUnit>
create(std::shared_ptr<CompilerInvocation> CI,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,CaptureDiagsKind CaptureDiagnostics,bool UserFilesAreVolatile)1480ea4395ebSDavid Blaikie ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
1481c95d8192SDylan Noblesmith                 IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
14828edd8da4SNikolai Kosjar                 CaptureDiagsKind CaptureDiagnostics,
14838edd8da4SNikolai Kosjar                 bool UserFilesAreVolatile) {
1484ea4395ebSDavid Blaikie   std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
1485dbbcb11fSJustin Bogner   ConfigureDiags(Diags, *AST, CaptureDiagnostics);
1486fc51490bSJonas Devlieghere   IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
14878832c066SBen Langmuir       createVFSFromCompilerInvocation(*CI, *Diags);
1488ea4395ebSDavid Blaikie   AST->Diagnostics = Diags;
1489ea4395ebSDavid Blaikie   AST->FileSystemOpts = CI->getFileSystemOpts();
1490ea4395ebSDavid Blaikie   AST->Invocation = std::move(CI);
14918832c066SBen Langmuir   AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
14926d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
14936d7833f1SArgyrios Kyrtzidis   AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
14946d7833f1SArgyrios Kyrtzidis                                      UserFilesAreVolatile);
14958bef5cd4SDuncan P. N. Exon Smith   AST->ModuleCache = new InMemoryModuleCache;
149635dcda79SArgyrios Kyrtzidis 
1497ea4395ebSDavid Blaikie   return AST;
149835dcda79SArgyrios Kyrtzidis }
149935dcda79SArgyrios Kyrtzidis 
LoadFromCompilerInvocationAction(std::shared_ptr<CompilerInvocation> CI,std::shared_ptr<PCHContainerOperations> PCHContainerOps,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,FrontendAction * Action,ASTUnit * Unit,bool Persistent,StringRef ResourceFilesPath,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,unsigned PrecompilePreambleAfterNParses,bool CacheCodeCompletionResults,bool UserFilesAreVolatile,std::unique_ptr<ASTUnit> * ErrAST)1500b8984329SAhmed Charles ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
1501ea4395ebSDavid Blaikie     std::shared_ptr<CompilerInvocation> CI,
1502bb165fb0SAdrian Prantl     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
1503c382abfdSArgyrios Kyrtzidis     IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action,
1504bb165fb0SAdrian Prantl     ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,
15058edd8da4SNikolai Kosjar     bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
15065c248d89SBenjamin Kramer     unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,
1507cfde3edeSDuncan P. N. Exon Smith     bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {
1508f1f67597SArgyrios Kyrtzidis   assert(CI && "A CompilerInvocation is required");
1509f1f67597SArgyrios Kyrtzidis 
1510b8984329SAhmed Charles   std::unique_ptr<ASTUnit> OwnAST;
15111ac5da10SArgyrios Kyrtzidis   ASTUnit *AST = Unit;
15121ac5da10SArgyrios Kyrtzidis   if (!AST) {
1513f1f67597SArgyrios Kyrtzidis     // Create the AST unit.
1514ea4395ebSDavid Blaikie     OwnAST = create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile);
15151ac5da10SArgyrios Kyrtzidis     AST = OwnAST.get();
15168832c066SBen Langmuir     if (!AST)
15178832c066SBen Langmuir       return nullptr;
15181ac5da10SArgyrios Kyrtzidis   }
15191ac5da10SArgyrios Kyrtzidis 
1520b11f5a4cSArgyrios Kyrtzidis   if (!ResourceFilesPath.empty()) {
1521b11f5a4cSArgyrios Kyrtzidis     // Override the resources path.
1522adcd0268SBenjamin Kramer     CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
1523b11f5a4cSArgyrios Kyrtzidis   }
1524b11f5a4cSArgyrios Kyrtzidis   AST->OnlyLocalDecls = OnlyLocalDecls;
1525b11f5a4cSArgyrios Kyrtzidis   AST->CaptureDiagnostics = CaptureDiagnostics;
15265c248d89SBenjamin Kramer   if (PrecompilePreambleAfterNParses > 0)
1527295c19e9SNikolai Kosjar     AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses;
152869f74f80SDouglas Gregor   AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
1529b11f5a4cSArgyrios Kyrtzidis   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
1530cfde3edeSDuncan P. N. Exon Smith   AST->IncludeBriefCommentsInCodeCompletion = false;
1531f1f67597SArgyrios Kyrtzidis 
1532f1f67597SArgyrios Kyrtzidis   // Recover resources if we crash before exiting this method.
1533f1f67597SArgyrios Kyrtzidis   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
15341ac5da10SArgyrios Kyrtzidis     ASTUnitCleanup(OwnAST.get());
15359c902b55SDavid Blaikie   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
15369c902b55SDavid Blaikie     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
1537f994cef8SAlp Toker     DiagCleanup(Diags.get());
1538f1f67597SArgyrios Kyrtzidis 
1539f1f67597SArgyrios Kyrtzidis   // We'll manage file buffers ourselves.
1540f1f67597SArgyrios Kyrtzidis   CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1541f1f67597SArgyrios Kyrtzidis   CI->getFrontendOpts().DisableFree = false;
1542f1f67597SArgyrios Kyrtzidis   ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
1543f1f67597SArgyrios Kyrtzidis 
1544f1f67597SArgyrios Kyrtzidis   // Create the compiler instance to use for building the AST.
1545bb165fb0SAdrian Prantl   std::unique_ptr<CompilerInstance> Clang(
1546d6da1a09SBenjamin Kramer       new CompilerInstance(std::move(PCHContainerOps)));
1547f1f67597SArgyrios Kyrtzidis 
1548f1f67597SArgyrios Kyrtzidis   // Recover resources if we crash before exiting this method.
1549f1f67597SArgyrios Kyrtzidis   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1550f1f67597SArgyrios Kyrtzidis     CICleanup(Clang.get());
1551f1f67597SArgyrios Kyrtzidis 
1552ea4395ebSDavid Blaikie   Clang->setInvocation(std::move(CI));
1553adcd0268SBenjamin Kramer   AST->OriginalSourceFile =
1554adcd0268SBenjamin Kramer       std::string(Clang->getFrontendOpts().Inputs[0].getFile());
1555f1f67597SArgyrios Kyrtzidis 
1556f1f67597SArgyrios Kyrtzidis   // Set up diagnostics, capturing any diagnostics that would
1557f1f67597SArgyrios Kyrtzidis   // otherwise be dropped.
1558f1f67597SArgyrios Kyrtzidis   Clang->setDiagnostics(&AST->getDiagnostics());
1559f1f67597SArgyrios Kyrtzidis 
1560f1f67597SArgyrios Kyrtzidis   // Create the target instance.
156114a7296cSoToToT   if (!Clang->createTarget())
156249a2790fSCraig Topper     return nullptr;
1563f1f67597SArgyrios Kyrtzidis 
1564f1f67597SArgyrios Kyrtzidis   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1565f1f67597SArgyrios Kyrtzidis          "Invocation must have exactly one source file!");
156640c0efa5SRichard Smith   assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
156740c0efa5SRichard Smith              InputKind::Source &&
1568f1f67597SArgyrios Kyrtzidis          "FIXME: AST inputs not yet supported here!");
156940c0efa5SRichard Smith   assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
157009d890d7SRainer Orth              Language::LLVM_IR &&
157140c0efa5SRichard Smith          "IR inputs not support here!");
1572f1f67597SArgyrios Kyrtzidis 
1573f1f67597SArgyrios Kyrtzidis   // Configure the various subsystems.
1574f1f67597SArgyrios Kyrtzidis   AST->TheSema.reset();
157549a2790fSCraig Topper   AST->Ctx = nullptr;
157649a2790fSCraig Topper   AST->PP = nullptr;
157749a2790fSCraig Topper   AST->Reader = nullptr;
1578f1f67597SArgyrios Kyrtzidis 
1579f1f67597SArgyrios Kyrtzidis   // Create a file manager object to provide access to and cache the filesystem.
1580f1f67597SArgyrios Kyrtzidis   Clang->setFileManager(&AST->getFileManager());
1581f1f67597SArgyrios Kyrtzidis 
1582f1f67597SArgyrios Kyrtzidis   // Create the source manager.
1583f1f67597SArgyrios Kyrtzidis   Clang->setSourceManager(&AST->getSourceManager());
1584f1f67597SArgyrios Kyrtzidis 
1585c382abfdSArgyrios Kyrtzidis   FrontendAction *Act = Action;
1586f1f67597SArgyrios Kyrtzidis 
1587b8984329SAhmed Charles   std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct;
1588f1f67597SArgyrios Kyrtzidis   if (!Act) {
1589f1f67597SArgyrios Kyrtzidis     TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));
1590f1f67597SArgyrios Kyrtzidis     Act = TrackerAct.get();
1591f1f67597SArgyrios Kyrtzidis   }
1592f1f67597SArgyrios Kyrtzidis 
1593f1f67597SArgyrios Kyrtzidis   // Recover resources if we crash before exiting this method.
1594f1f67597SArgyrios Kyrtzidis   llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
1595f1f67597SArgyrios Kyrtzidis     ActCleanup(TrackerAct.get());
1596f1f67597SArgyrios Kyrtzidis 
1597ac1cc934SArgyrios Kyrtzidis   if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
1598ac1cc934SArgyrios Kyrtzidis     AST->transferASTDataFromCompilerInstance(*Clang);
1599ac1cc934SArgyrios Kyrtzidis     if (OwnAST && ErrAST)
1600ac1cc934SArgyrios Kyrtzidis       ErrAST->swap(OwnAST);
1601ac1cc934SArgyrios Kyrtzidis 
160249a2790fSCraig Topper     return nullptr;
1603ac1cc934SArgyrios Kyrtzidis   }
1604f1f67597SArgyrios Kyrtzidis 
1605b11f5a4cSArgyrios Kyrtzidis   if (Persistent && !TrackerAct) {
1606b11f5a4cSArgyrios Kyrtzidis     Clang->getPreprocessor().addPPCallbacks(
16072b3d49b6SJonas Devlieghere         std::make_unique<MacroDefinitionTrackerPPCallbacks>(
1608b8a70530SCraig Topper                                            AST->getCurrentTopLevelHashValue()));
16096beb6aa8SDavid Blaikie     std::vector<std::unique_ptr<ASTConsumer>> Consumers;
1610b11f5a4cSArgyrios Kyrtzidis     if (Clang->hasASTConsumer())
1611b11f5a4cSArgyrios Kyrtzidis       Consumers.push_back(Clang->takeASTConsumer());
16122b3d49b6SJonas Devlieghere     Consumers.push_back(std::make_unique<TopLevelDeclTrackerConsumer>(
16136beb6aa8SDavid Blaikie         *AST, AST->getCurrentTopLevelHashValue()));
16146beb6aa8SDavid Blaikie     Clang->setASTConsumer(
16152b3d49b6SJonas Devlieghere         std::make_unique<MultiplexConsumer>(std::move(Consumers)));
1616b11f5a4cSArgyrios Kyrtzidis   }
16170e828958SJF Bastien   if (llvm::Error Err = Act->Execute()) {
16180e828958SJF Bastien     consumeError(std::move(Err)); // FIXME this drops errors on the floor.
16191416e17cSArgyrios Kyrtzidis     AST->transferASTDataFromCompilerInstance(*Clang);
16201416e17cSArgyrios Kyrtzidis     if (OwnAST && ErrAST)
16211416e17cSArgyrios Kyrtzidis       ErrAST->swap(OwnAST);
16221416e17cSArgyrios Kyrtzidis 
162349a2790fSCraig Topper     return nullptr;
16241416e17cSArgyrios Kyrtzidis   }
1625f1f67597SArgyrios Kyrtzidis 
1626f1f67597SArgyrios Kyrtzidis   // Steal the created target, context, and preprocessor.
1627ac1cc934SArgyrios Kyrtzidis   AST->transferASTDataFromCompilerInstance(*Clang);
1628f1f67597SArgyrios Kyrtzidis 
1629f1f67597SArgyrios Kyrtzidis   Act->EndSourceFile();
1630f1f67597SArgyrios Kyrtzidis 
16311ac5da10SArgyrios Kyrtzidis   if (OwnAST)
16329a16beb8SAhmed Charles     return OwnAST.release();
16331ac5da10SArgyrios Kyrtzidis   else
16341ac5da10SArgyrios Kyrtzidis     return AST;
1635f1f67597SArgyrios Kyrtzidis }
1636f1f67597SArgyrios Kyrtzidis 
LoadFromCompilerInvocation(std::shared_ptr<PCHContainerOperations> PCHContainerOps,unsigned PrecompilePreambleAfterNParses,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)1637bb165fb0SAdrian Prantl bool ASTUnit::LoadFromCompilerInvocation(
1638bb165fb0SAdrian Prantl     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
1639af69e40cSIlya Biryukov     unsigned PrecompilePreambleAfterNParses,
1640fc51490bSJonas Devlieghere     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
16417bb8af61SDouglas Gregor   if (!Invocation)
16427bb8af61SDouglas Gregor     return true;
16437bb8af61SDouglas Gregor 
1644af69e40cSIlya Biryukov   assert(VFS && "VFS is null");
1645af69e40cSIlya Biryukov 
16467bb8af61SDouglas Gregor   // We'll manage file buffers ourselves.
16477bb8af61SDouglas Gregor   Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
16487bb8af61SDouglas Gregor   Invocation->getFrontendOpts().DisableFree = false;
16498de9c9b0SBenjamin Kramer   getDiagnostics().Reset();
1650345c1bcbSDouglas Gregor   ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
16517bb8af61SDouglas Gregor 
165232482080SRafael Espindola   std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
16535c248d89SBenjamin Kramer   if (PrecompilePreambleAfterNParses > 0) {
1654295c19e9SNikolai Kosjar     PreambleRebuildCountdown = PrecompilePreambleAfterNParses;
1655bb165fb0SAdrian Prantl     OverrideMainBuffer =
1656af69e40cSIlya Biryukov         getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
16578484a326SBenjamin Kramer     getDiagnostics().Reset();
16588484a326SBenjamin Kramer     ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
16597bb8af61SDouglas Gregor   }
16607bb8af61SDouglas Gregor 
166116896c45SDouglas Gregor   SimpleTimer ParsingTimer(WantTiming);
166216896c45SDouglas Gregor   ParsingTimer.setOutput("Parsing " + getMainFileName());
16637bb8af61SDouglas Gregor 
1664022a4904STed Kremenek   // Recover resources if we crash before exiting this method.
1665022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
166632482080SRafael Espindola     MemBufferCleanup(OverrideMainBuffer.get());
1667022a4904STed Kremenek 
1668af69e40cSIlya Biryukov   return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
16697bb8af61SDouglas Gregor }
16707bb8af61SDouglas Gregor 
LoadFromCompilerInvocation(std::shared_ptr<CompilerInvocation> CI,std::shared_ptr<PCHContainerOperations> PCHContainerOps,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,FileManager * FileMgr,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,unsigned PrecompilePreambleAfterNParses,TranslationUnitKind TUKind,bool CacheCodeCompletionResults,bool IncludeBriefCommentsInCodeCompletion,bool UserFilesAreVolatile)1671103a2de0SDavid Blaikie std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
1672ea4395ebSDavid Blaikie     std::shared_ptr<CompilerInvocation> CI,
1673bb165fb0SAdrian Prantl     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
1674bc632902SBenjamin Kramer     IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
16758edd8da4SNikolai Kosjar     bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
16765c248d89SBenjamin Kramer     unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
16775c248d89SBenjamin Kramer     bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
16785c248d89SBenjamin Kramer     bool UserFilesAreVolatile) {
1679aa21cc40SDouglas Gregor   // Create the AST unit.
1680103a2de0SDavid Blaikie   std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
1681dbbcb11fSJustin Bogner   ConfigureDiags(Diags, *AST, CaptureDiagnostics);
1682aa21cc40SDouglas Gregor   AST->Diagnostics = Diags;
1683aa21cc40SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
168444c6ee77SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
168569f74f80SDouglas Gregor   AST->TUKind = TUKind;
1686b14904c4SDouglas Gregor   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
16873292d06aSDmitri Gribenko   AST->IncludeBriefCommentsInCodeCompletion
16883292d06aSDmitri Gribenko     = IncludeBriefCommentsInCodeCompletion;
1689ea4395ebSDavid Blaikie   AST->Invocation = std::move(CI);
1690bc632902SBenjamin Kramer   AST->FileSystemOpts = FileMgr->getFileSystemOpts();
1691bc632902SBenjamin Kramer   AST->FileMgr = FileMgr;
16926d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
1693aa21cc40SDouglas Gregor 
16944422bfeaSTed Kremenek   // Recover resources if we crash before exiting this method.
1695022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1696022a4904STed Kremenek     ASTUnitCleanup(AST.get());
16979c902b55SDavid Blaikie   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
16989c902b55SDavid Blaikie     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
1699f994cef8SAlp Toker     DiagCleanup(Diags.get());
17004422bfeaSTed Kremenek 
1701d6da1a09SBenjamin Kramer   if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
1702af69e40cSIlya Biryukov                                       PrecompilePreambleAfterNParses,
1703db8a7422SDuncan P. N. Exon Smith                                       &AST->FileMgr->getVirtualFileSystem()))
1704103a2de0SDavid Blaikie     return nullptr;
1705103a2de0SDavid Blaikie   return AST;
1706764c0820SDaniel Dunbar }
170755a17b66SDaniel Dunbar 
LoadFromCommandLine(const char ** ArgBegin,const char ** ArgEnd,std::shared_ptr<PCHContainerOperations> PCHContainerOps,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,StringRef ResourceFilesPath,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,ArrayRef<RemappedFile> RemappedFiles,bool RemappedFilesKeepOriginalName,unsigned PrecompilePreambleAfterNParses,TranslationUnitKind TUKind,bool CacheCodeCompletionResults,bool IncludeBriefCommentsInCodeCompletion,bool AllowPCHWithCompilerErrors,SkipFunctionBodiesScope SkipFunctionBodies,bool SingleFileParse,bool UserFilesAreVolatile,bool ForSerialization,bool RetainExcludedConditionalBlocks,llvm::Optional<StringRef> ModuleFormat,std::unique_ptr<ASTUnit> * ErrAST,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)1708b8984329SAhmed Charles ASTUnit *ASTUnit::LoadFromCommandLine(
1709b8984329SAhmed Charles     const char **ArgBegin, const char **ArgEnd,
1710bb165fb0SAdrian Prantl     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
1711b8984329SAhmed Charles     IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
17128edd8da4SNikolai Kosjar     bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
1713b8984329SAhmed Charles     ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
17145c248d89SBenjamin Kramer     unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
1715b8984329SAhmed Charles     bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
17166e89528cSIvan Donchevskii     bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
1717735e92c2SArgyrios Kyrtzidis     bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
17182ed2e624SEvgeny Mankov     bool RetainExcludedConditionalBlocks,
1719af69e40cSIlya Biryukov     llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
1720fc51490bSJonas Devlieghere     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
1721d512c1edSJustin Bogner   assert(Diags.get() && "no DiagnosticsEngine was provided");
1722d03e823fSDouglas Gregor 
17230e62c1ccSChris Lattner   SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
17247bb8af61SDouglas Gregor 
1725ea4395ebSDavid Blaikie   std::shared_ptr<CompilerInvocation> CI;
172644c6ee77SDouglas Gregor 
17277bb8af61SDouglas Gregor   {
172844c6ee77SDouglas Gregor     CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
1729200b3289SIlya Biryukov                                       &StoredDiagnostics, nullptr);
17307bb8af61SDouglas Gregor 
1731499d0b96SSam McCall     CreateInvocationOptions CIOpts;
1732499d0b96SSam McCall     CIOpts.VFS = VFS;
1733499d0b96SSam McCall     CIOpts.Diags = Diags;
173400a3c9f2SSam McCall     CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?
1735499d0b96SSam McCall     CI = createInvocation(llvm::makeArrayRef(ArgBegin, ArgEnd),
1736499d0b96SSam McCall                           std::move(CIOpts));
1737f606b82eSArgyrios Kyrtzidis     if (!CI)
173849a2790fSCraig Topper       return nullptr;
1739bc1f48f6SArgyrios Kyrtzidis   }
1740bc1f48f6SArgyrios Kyrtzidis 
1741aa98ed9aSDouglas Gregor   // Override any files that need remapping
17426a96ae5eSBenjamin Kramer   for (const auto &RemappedFile : RemappedFiles) {
17436a96ae5eSBenjamin Kramer     CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
17446a96ae5eSBenjamin Kramer                                               RemappedFile.second);
174511e6f0a6SArgyrios Kyrtzidis   }
17464a280ff4SArgyrios Kyrtzidis   PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
17474a280ff4SArgyrios Kyrtzidis   PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
17484a280ff4SArgyrios Kyrtzidis   PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
1749735e92c2SArgyrios Kyrtzidis   PPOpts.SingleFileParseMode = SingleFileParse;
17502ed2e624SEvgeny Mankov   PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;
1751aa98ed9aSDouglas Gregor 
1752a5a166d0SDaniel Dunbar   // Override the resources path.
1753adcd0268SBenjamin Kramer   CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
175455a17b66SDaniel Dunbar 
17556e89528cSIvan Donchevskii   CI->getFrontendOpts().SkipFunctionBodies =
17566e89528cSIvan Donchevskii       SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;
17576e92251fSErik Verbruggen 
1758a3e2ff19SArgyrios Kyrtzidis   if (ModuleFormat)
1759*ca4af13eSKazu Hirata     CI->getHeaderSearchOpts().ModuleFormat = std::string(*ModuleFormat);
1760a3e2ff19SArgyrios Kyrtzidis 
17617bb8af61SDouglas Gregor   // Create the AST unit.
1762b8984329SAhmed Charles   std::unique_ptr<ASTUnit> AST;
17637bb8af61SDouglas Gregor   AST.reset(new ASTUnit(false));
1764005c2e57SBen Langmuir   AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
1765005c2e57SBen Langmuir   AST->StoredDiagnostics.swap(StoredDiagnostics);
1766dbbcb11fSJustin Bogner   ConfigureDiags(Diags, *AST, CaptureDiagnostics);
17677bb8af61SDouglas Gregor   AST->Diagnostics = Diags;
1768c30dcecbSAnders Carlsson   AST->FileSystemOpts = CI->getFileSystemOpts();
1769af69e40cSIlya Biryukov   if (!VFS)
1770fc51490bSJonas Devlieghere     VFS = llvm::vfs::getRealFileSystem();
1771af69e40cSIlya Biryukov   VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
17728832c066SBen Langmuir   AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
17738bef5cd4SDuncan P. N. Exon Smith   AST->ModuleCache = new InMemoryModuleCache;
17747bb8af61SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
177544c6ee77SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
177669f74f80SDouglas Gregor   AST->TUKind = TUKind;
17777bb8af61SDouglas Gregor   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
17783292d06aSDmitri Gribenko   AST->IncludeBriefCommentsInCodeCompletion
17793292d06aSDmitri Gribenko     = IncludeBriefCommentsInCodeCompletion;
17806d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
17815e14d39aSTed Kremenek   AST->Invocation = CI;
17826e89528cSIvan Donchevskii   AST->SkipFunctionBodies = SkipFunctionBodies;
17830db720f0SArgyrios Kyrtzidis   if (ForSerialization)
17848bef5cd4SDuncan P. N. Exon Smith     AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache));
1785b4f99dd0SAlexey Samsonov   // Zero out now to ease cleanup during crash recovery.
1786b4f99dd0SAlexey Samsonov   CI = nullptr;
1787b4f99dd0SAlexey Samsonov   Diags = nullptr;
17884422bfeaSTed Kremenek 
17894422bfeaSTed Kremenek   // Recover resources if we crash before exiting this method.
1790022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1791022a4904STed Kremenek     ASTUnitCleanup(AST.get());
17924422bfeaSTed Kremenek 
1793d6da1a09SBenjamin Kramer   if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
1794af69e40cSIlya Biryukov                                       PrecompilePreambleAfterNParses,
1795af69e40cSIlya Biryukov                                       VFS)) {
1796ac1cc934SArgyrios Kyrtzidis     // Some error occurred, if caller wants to examine diagnostics, pass it the
1797ac1cc934SArgyrios Kyrtzidis     // ASTUnit.
1798ac1cc934SArgyrios Kyrtzidis     if (ErrAST) {
1799ac1cc934SArgyrios Kyrtzidis       AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
1800ac1cc934SArgyrios Kyrtzidis       ErrAST->swap(AST);
1801ac1cc934SArgyrios Kyrtzidis     }
180249a2790fSCraig Topper     return nullptr;
1803ac1cc934SArgyrios Kyrtzidis   }
1804ac1cc934SArgyrios Kyrtzidis 
18059a16beb8SAhmed Charles   return AST.release();
180655a17b66SDaniel Dunbar }
1807aa21cc40SDouglas Gregor 
Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,ArrayRef<RemappedFile> RemappedFiles,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)1808bb165fb0SAdrian Prantl bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
1809af69e40cSIlya Biryukov                       ArrayRef<RemappedFile> RemappedFiles,
1810fc51490bSJonas Devlieghere                       IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
18115e14d39aSTed Kremenek   if (!Invocation)
1812aa21cc40SDouglas Gregor     return true;
1813aa21cc40SDouglas Gregor 
1814af69e40cSIlya Biryukov   if (!VFS) {
1815af69e40cSIlya Biryukov     assert(FileMgr && "FileMgr is null on Reparse call");
1816db8a7422SDuncan P. N. Exon Smith     VFS = &FileMgr->getVirtualFileSystem();
1817af69e40cSIlya Biryukov   }
1818af69e40cSIlya Biryukov 
1819e54568d6SArgyrios Kyrtzidis   clearFileLevelDecls();
1820e54568d6SArgyrios Kyrtzidis 
182116896c45SDouglas Gregor   SimpleTimer ParsingTimer(WantTiming);
182216896c45SDouglas Gregor   ParsingTimer.setOutput("Reparsing " + getMainFileName());
182315ba0b34SDouglas Gregor 
18240e11955cSDouglas Gregor   // Remap files.
18257b02b583SDouglas Gregor   PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
18261b070d25SAlp Toker   for (const auto &RB : PPOpts.RemappedFileBuffers)
18271b070d25SAlp Toker     delete RB.second;
18281b070d25SAlp Toker 
18290e11955cSDouglas Gregor   Invocation->getPreprocessorOpts().clearRemappedFiles();
18306a96ae5eSBenjamin Kramer   for (const auto &RemappedFile : RemappedFiles) {
18316a96ae5eSBenjamin Kramer     Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
18326a96ae5eSBenjamin Kramer                                                       RemappedFile.second);
183311e6f0a6SArgyrios Kyrtzidis   }
18340e11955cSDouglas Gregor 
1835bb420abdSDouglas Gregor   // If we have a preamble file lying around, or if we might try to
1836bb420abdSDouglas Gregor   // build a precompiled preamble, do so now.
183732482080SRafael Espindola   std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
1838295c19e9SNikolai Kosjar   if (Preamble || PreambleRebuildCountdown > 0)
1839bb165fb0SAdrian Prantl     OverrideMainBuffer =
1840af69e40cSIlya Biryukov         getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
1841af69e40cSIlya Biryukov 
1842aa21cc40SDouglas Gregor   // Clear out the diagnostics state.
1843bc632902SBenjamin Kramer   FileMgr.reset();
1844aa21cc40SDouglas Gregor   getDiagnostics().Reset();
184536e3b5c7SDouglas Gregor   ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
1846462ff35dSArgyrios Kyrtzidis   if (OverrideMainBuffer)
1847462ff35dSArgyrios Kyrtzidis     getDiagnostics().setNumWarnings(NumWarningsInPreamble);
1848aa21cc40SDouglas Gregor 
18494dde7498SDouglas Gregor   // Parse the sources
1850d6da1a09SBenjamin Kramer   bool Result =
1851af69e40cSIlya Biryukov       Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
1852df7a79a9SDouglas Gregor 
18533689337cSArgyrios Kyrtzidis   // If we're caching global code-completion results, and the top-level
18543689337cSArgyrios Kyrtzidis   // declarations have changed, clear out the code-completion cache.
18553689337cSArgyrios Kyrtzidis   if (!Result && ShouldCacheCodeCompletionResults &&
18563689337cSArgyrios Kyrtzidis       CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
18573689337cSArgyrios Kyrtzidis     CacheCodeCompletionResults();
18583689337cSArgyrios Kyrtzidis 
18599d7c0fefSArgyrios Kyrtzidis   // We now need to clear out the completion info related to this translation
18609d7c0fefSArgyrios Kyrtzidis   // unit; it'll be recreated if necessary.
18619d7c0fefSArgyrios Kyrtzidis   CCTUInfo.reset();
18623f35bb2dSDouglas Gregor 
18634dde7498SDouglas Gregor   return Result;
1864aa21cc40SDouglas Gregor }
18658e984da8SDouglas Gregor 
ResetForParse()1866346066b6SErik Verbruggen void ASTUnit::ResetForParse() {
1867346066b6SErik Verbruggen   SavedMainFileBuffer.reset();
1868346066b6SErik Verbruggen 
1869346066b6SErik Verbruggen   SourceMgr.reset();
1870346066b6SErik Verbruggen   TheSema.reset();
1871346066b6SErik Verbruggen   Ctx.reset();
1872346066b6SErik Verbruggen   PP.reset();
1873346066b6SErik Verbruggen   Reader.reset();
1874346066b6SErik Verbruggen 
1875346066b6SErik Verbruggen   TopLevelDecls.clear();
1876346066b6SErik Verbruggen   clearFileLevelDecls();
1877346066b6SErik Verbruggen }
1878346066b6SErik Verbruggen 
1879b14904c4SDouglas Gregor //----------------------------------------------------------------------------//
1880b14904c4SDouglas Gregor // Code completion
1881b14904c4SDouglas Gregor //----------------------------------------------------------------------------//
1882b14904c4SDouglas Gregor 
1883b14904c4SDouglas Gregor namespace {
18844f233181SEugene Zelenko 
18859fc8faf9SAdrian Prantl   /// Code completion consumer that combines the cached code-completion
1886b14904c4SDouglas Gregor   /// results from an ASTUnit with the code-completion results provided to it,
1887b14904c4SDouglas Gregor   /// then passes the result on to
1888b14904c4SDouglas Gregor   class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
1889697cc9e6SRichard Smith     uint64_t NormalContexts;
1890b14904c4SDouglas Gregor     ASTUnit &AST;
1891b14904c4SDouglas Gregor     CodeCompleteConsumer &Next;
1892b14904c4SDouglas Gregor 
1893b14904c4SDouglas Gregor   public:
AugmentedCodeCompleteConsumer(ASTUnit & AST,CodeCompleteConsumer & Next,const CodeCompleteOptions & CodeCompleteOpts)1894b14904c4SDouglas Gregor     AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
18953292d06aSDmitri Gribenko                                   const CodeCompleteOptions &CodeCompleteOpts)
18963a75330fSSam McCall         : CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) {
1897b14904c4SDouglas Gregor       // Compute the set of contexts in which we will look when we don't have
1898b14904c4SDouglas Gregor       // any information about the specific context.
1899b14904c4SDouglas Gregor       NormalContexts
1900697cc9e6SRichard Smith         = (1LL << CodeCompletionContext::CCC_TopLevel)
1901697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCInterface)
1902697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
1903697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
1904697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Statement)
1905697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Expression)
1906697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
1907697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_DotMemberAccess)
1908697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)
1909697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)
1910697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCProtocolName)
1911697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
1912697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Recovery);
1913b14904c4SDouglas Gregor 
1914bbafb8a7SDavid Blaikie       if (AST.getASTContext().getLangOpts().CPlusPlus)
1915697cc9e6SRichard Smith         NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)
1916697cc9e6SRichard Smith                        |  (1LL << CodeCompletionContext::CCC_UnionTag)
1917697cc9e6SRichard Smith                        |  (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
1918b14904c4SDouglas Gregor     }
1919b14904c4SDouglas Gregor 
1920afa7cb3aSCraig Topper     void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
1921276321a9SJohn McCall                                     CodeCompletionResult *Results,
1922afa7cb3aSCraig Topper                                     unsigned NumResults) override;
1923d46cf182SDouglas Gregor 
ProcessOverloadCandidates(Sema & S,unsigned CurrentArg,OverloadCandidate * Candidates,unsigned NumCandidates,SourceLocation OpenParLoc,bool Braced)1924afa7cb3aSCraig Topper     void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
1925d46cf182SDouglas Gregor                                    OverloadCandidate *Candidates,
19262fab2353SIlya Biryukov                                    unsigned NumCandidates,
192792417eafSSam McCall                                    SourceLocation OpenParLoc,
192892417eafSSam McCall                                    bool Braced) override {
19292fab2353SIlya Biryukov       Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
193092417eafSSam McCall                                      OpenParLoc, Braced);
1931d46cf182SDouglas Gregor     }
1932b278aafbSDouglas Gregor 
getAllocator()1933afa7cb3aSCraig Topper     CodeCompletionAllocator &getAllocator() override {
1934b278aafbSDouglas Gregor       return Next.getAllocator();
1935b278aafbSDouglas Gregor     }
19369d7c0fefSArgyrios Kyrtzidis 
getCodeCompletionTUInfo()1937afa7cb3aSCraig Topper     CodeCompletionTUInfo &getCodeCompletionTUInfo() override {
19389d7c0fefSArgyrios Kyrtzidis       return Next.getCodeCompletionTUInfo();
19399d7c0fefSArgyrios Kyrtzidis     }
1940d46cf182SDouglas Gregor   };
19414f233181SEugene Zelenko 
19424f233181SEugene Zelenko } // namespace
1943d46cf182SDouglas Gregor 
19449fc8faf9SAdrian Prantl /// Helper function that computes which global names are hidden by the
19456199f2d1SDouglas Gregor /// local code-completion results.
CalculateHiddenNames(const CodeCompletionContext & Context,CodeCompletionResult * Results,unsigned NumResults,ASTContext & Ctx,llvm::StringSet<llvm::BumpPtrAllocator> & HiddenNames)19466a15337dSTed Kremenek static void CalculateHiddenNames(const CodeCompletionContext &Context,
1947276321a9SJohn McCall                                  CodeCompletionResult *Results,
19486199f2d1SDouglas Gregor                                  unsigned NumResults,
19496199f2d1SDouglas Gregor                                  ASTContext &Ctx,
19506a15337dSTed Kremenek                           llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){
19516199f2d1SDouglas Gregor   bool OnlyTagNames = false;
19526199f2d1SDouglas Gregor   switch (Context.getKind()) {
19530ac41389SDouglas Gregor   case CodeCompletionContext::CCC_Recovery:
19546199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_TopLevel:
19556199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCInterface:
19566199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCImplementation:
19576199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCIvarList:
19586199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ClassStructUnion:
19596199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Statement:
19606199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Expression:
19616199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCMessageReceiver:
19622132584dSDouglas Gregor   case CodeCompletionContext::CCC_DotMemberAccess:
19632132584dSDouglas Gregor   case CodeCompletionContext::CCC_ArrowMemberAccess:
19642132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCPropertyAccess:
19656199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Namespace:
19666199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Type:
1967b006e099SKadir Cetinkaya   case CodeCompletionContext::CCC_Symbol:
1968b006e099SKadir Cetinkaya   case CodeCompletionContext::CCC_SymbolOrNewName:
19695e35d591SDouglas Gregor   case CodeCompletionContext::CCC_ParenthesizedExpression:
19702c595adfSDouglas Gregor   case CodeCompletionContext::CCC_ObjCInterfaceName:
19716199f2d1SDouglas Gregor     break;
19726199f2d1SDouglas Gregor 
19736199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_EnumTag:
19746199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_UnionTag:
19756199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ClassOrStructTag:
19766199f2d1SDouglas Gregor     OnlyTagNames = true;
19776199f2d1SDouglas Gregor     break;
19786199f2d1SDouglas Gregor 
19796199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCProtocolName:
198012785108SDouglas Gregor   case CodeCompletionContext::CCC_MacroName:
198112785108SDouglas Gregor   case CodeCompletionContext::CCC_MacroNameUse:
1982ec00a268SDouglas Gregor   case CodeCompletionContext::CCC_PreprocessorExpression:
19830de55cecSDouglas Gregor   case CodeCompletionContext::CCC_PreprocessorDirective:
1984ea14705cSDouglas Gregor   case CodeCompletionContext::CCC_NaturalLanguage:
198567c692ccSDouglas Gregor   case CodeCompletionContext::CCC_SelectorName:
198628c7843eSDouglas Gregor   case CodeCompletionContext::CCC_TypeQualifiers:
19870ac41389SDouglas Gregor   case CodeCompletionContext::CCC_Other:
19883a69eafaSDouglas Gregor   case CodeCompletionContext::CCC_OtherWithMacros:
19892132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCInstanceMessage:
19902132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCClassMessage:
19912132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCCategoryName:
19923d8051abSSam McCall   case CodeCompletionContext::CCC_IncludedFile:
1993ece4e920SSam McCall   case CodeCompletionContext::CCC_Attribute:
1994b006e099SKadir Cetinkaya   case CodeCompletionContext::CCC_NewName:
19950de55cecSDouglas Gregor     // We're looking for nothing, or we're looking for names that cannot
19960de55cecSDouglas Gregor     // be hidden.
19976199f2d1SDouglas Gregor     return;
19986199f2d1SDouglas Gregor   }
19996199f2d1SDouglas Gregor 
20004f233181SEugene Zelenko   using Result = CodeCompletionResult;
20016199f2d1SDouglas Gregor   for (unsigned I = 0; I != NumResults; ++I) {
20026199f2d1SDouglas Gregor     if (Results[I].Kind != Result::RK_Declaration)
20036199f2d1SDouglas Gregor       continue;
20046199f2d1SDouglas Gregor 
20056199f2d1SDouglas Gregor     unsigned IDNS
20066199f2d1SDouglas Gregor       = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
20076199f2d1SDouglas Gregor 
20086199f2d1SDouglas Gregor     bool Hiding = false;
20096199f2d1SDouglas Gregor     if (OnlyTagNames)
20106199f2d1SDouglas Gregor       Hiding = (IDNS & Decl::IDNS_Tag);
20116199f2d1SDouglas Gregor     else {
20126199f2d1SDouglas Gregor       unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
20136199f2d1SDouglas Gregor                              Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
20146199f2d1SDouglas Gregor                              Decl::IDNS_NonMemberOperator);
2015bbafb8a7SDavid Blaikie       if (Ctx.getLangOpts().CPlusPlus)
20166199f2d1SDouglas Gregor         HiddenIDNS |= Decl::IDNS_Tag;
20176199f2d1SDouglas Gregor       Hiding = (IDNS & HiddenIDNS);
20186199f2d1SDouglas Gregor     }
20196199f2d1SDouglas Gregor 
20206199f2d1SDouglas Gregor     if (!Hiding)
20216199f2d1SDouglas Gregor       continue;
20226199f2d1SDouglas Gregor 
20236199f2d1SDouglas Gregor     DeclarationName Name = Results[I].Declaration->getDeclName();
20246199f2d1SDouglas Gregor     if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
20256199f2d1SDouglas Gregor       HiddenNames.insert(Identifier->getName());
20266199f2d1SDouglas Gregor     else
20276199f2d1SDouglas Gregor       HiddenNames.insert(Name.getAsString());
20286199f2d1SDouglas Gregor   }
20296199f2d1SDouglas Gregor }
20306199f2d1SDouglas Gregor 
ProcessCodeCompleteResults(Sema & S,CodeCompletionContext Context,CodeCompletionResult * Results,unsigned NumResults)2031d46cf182SDouglas Gregor void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
2032d46cf182SDouglas Gregor                                             CodeCompletionContext Context,
2033276321a9SJohn McCall                                             CodeCompletionResult *Results,
2034b14904c4SDouglas Gregor                                             unsigned NumResults) {
2035b14904c4SDouglas Gregor   // Merge the results we were given with the results we cached.
2036b14904c4SDouglas Gregor   bool AddedResult = false;
2037697cc9e6SRichard Smith   uint64_t InContexts =
2038697cc9e6SRichard Smith       Context.getKind() == CodeCompletionContext::CCC_Recovery
2039697cc9e6SRichard Smith         ? NormalContexts : (1LL << Context.getKind());
20406199f2d1SDouglas Gregor   // Contains the set of names that are hidden by "local" completion results.
20416a15337dSTed Kremenek   llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
20424f233181SEugene Zelenko   using Result = CodeCompletionResult;
20430e62c1ccSChris Lattner   SmallVector<Result, 8> AllResults;
2044b14904c4SDouglas Gregor   for (ASTUnit::cached_completion_iterator
2045b14904c4SDouglas Gregor             C = AST.cached_completion_begin(),
2046b14904c4SDouglas Gregor          CEnd = AST.cached_completion_end();
2047b14904c4SDouglas Gregor        C != CEnd; ++C) {
2048b14904c4SDouglas Gregor     // If the context we are in matches any of the contexts we are
2049b14904c4SDouglas Gregor     // interested in, we'll add this result.
2050b14904c4SDouglas Gregor     if ((C->ShowInContexts & InContexts) == 0)
2051b14904c4SDouglas Gregor       continue;
2052b14904c4SDouglas Gregor 
2053b14904c4SDouglas Gregor     // If we haven't added any results previously, do so now.
2054b14904c4SDouglas Gregor     if (!AddedResult) {
20556199f2d1SDouglas Gregor       CalculateHiddenNames(Context, Results, NumResults, S.Context,
20566199f2d1SDouglas Gregor                            HiddenNames);
2057b14904c4SDouglas Gregor       AllResults.insert(AllResults.end(), Results, Results + NumResults);
2058b14904c4SDouglas Gregor       AddedResult = true;
2059b14904c4SDouglas Gregor     }
2060b14904c4SDouglas Gregor 
20616199f2d1SDouglas Gregor     // Determine whether this global completion result is hidden by a local
20626199f2d1SDouglas Gregor     // completion result. If so, skip it.
20636199f2d1SDouglas Gregor     if (C->Kind != CXCursor_MacroDefinition &&
20646199f2d1SDouglas Gregor         HiddenNames.count(C->Completion->getTypedText()))
20656199f2d1SDouglas Gregor       continue;
20666199f2d1SDouglas Gregor 
20676e24033bSDouglas Gregor     // Adjust priority based on similar type classes.
20686e24033bSDouglas Gregor     unsigned Priority = C->Priority;
206912785108SDouglas Gregor     CodeCompletionString *Completion = C->Completion;
20706e24033bSDouglas Gregor     if (!Context.getPreferredType().isNull()) {
20716e24033bSDouglas Gregor       if (C->Kind == CXCursor_MacroDefinition) {
20726e24033bSDouglas Gregor         Priority = getMacroUsagePriority(C->Completion->getTypedText(),
2073bbafb8a7SDavid Blaikie                                          S.getLangOpts(),
20746e24033bSDouglas Gregor                                Context.getPreferredType()->isAnyPointerType());
2075b61c07acSDouglas Gregor       } else if (C->Type) {
20766e24033bSDouglas Gregor         CanQualType Expected
2077b61c07acSDouglas Gregor           = S.Context.getCanonicalType(
2078b61c07acSDouglas Gregor                                Context.getPreferredType().getUnqualifiedType());
20796e24033bSDouglas Gregor         SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
20806e24033bSDouglas Gregor         if (ExpectedSTC == C->TypeClass) {
2081b61c07acSDouglas Gregor           // We know this type is similar; check for an exact match.
2082b61c07acSDouglas Gregor           llvm::StringMap<unsigned> &CachedCompletionTypes
2083b61c07acSDouglas Gregor             = AST.getCachedCompletionTypes();
2084b61c07acSDouglas Gregor           llvm::StringMap<unsigned>::iterator Pos
2085b61c07acSDouglas Gregor             = CachedCompletionTypes.find(QualType(Expected).getAsString());
2086b61c07acSDouglas Gregor           if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
2087b61c07acSDouglas Gregor             Priority /= CCF_ExactTypeMatch;
2088b61c07acSDouglas Gregor           else
20896e24033bSDouglas Gregor             Priority /= CCF_SimilarTypeMatch;
20906e24033bSDouglas Gregor         }
20916e24033bSDouglas Gregor       }
20926e24033bSDouglas Gregor     }
20936e24033bSDouglas Gregor 
209412785108SDouglas Gregor     // Adjust the completion string, if required.
209512785108SDouglas Gregor     if (C->Kind == CXCursor_MacroDefinition &&
209612785108SDouglas Gregor         Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
209712785108SDouglas Gregor       // Create a new code-completion string that just contains the
209812785108SDouglas Gregor       // macro name, without its arguments.
20999d7c0fefSArgyrios Kyrtzidis       CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),
21009d7c0fefSArgyrios Kyrtzidis                                     CCP_CodePattern, C->Availability);
2101b278aafbSDouglas Gregor       Builder.AddTypedTextChunk(C->Completion->getTypedText());
21028850aa3fSDouglas Gregor       Priority = CCP_CodePattern;
2103b278aafbSDouglas Gregor       Completion = Builder.TakeString();
210412785108SDouglas Gregor     }
210512785108SDouglas Gregor 
21065c8b1cd2SArgyrios Kyrtzidis     AllResults.push_back(Result(Completion, Priority, C->Kind,
2107f757a12dSDouglas Gregor                                 C->Availability));
2108b14904c4SDouglas Gregor   }
2109b14904c4SDouglas Gregor 
2110b14904c4SDouglas Gregor   // If we did not add any cached completion results, just forward the
2111b14904c4SDouglas Gregor   // results we were given to the next consumer.
2112b14904c4SDouglas Gregor   if (!AddedResult) {
2113b14904c4SDouglas Gregor     Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
2114b14904c4SDouglas Gregor     return;
2115b14904c4SDouglas Gregor   }
2116b14904c4SDouglas Gregor 
2117b14904c4SDouglas Gregor   Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
2118b14904c4SDouglas Gregor                                   AllResults.size());
2119b14904c4SDouglas Gregor }
2120b14904c4SDouglas Gregor 
CodeComplete(StringRef File,unsigned Line,unsigned Column,ArrayRef<RemappedFile> RemappedFiles,bool IncludeMacros,bool IncludeCodePatterns,bool IncludeBriefComments,CodeCompleteConsumer & Consumer,std::shared_ptr<PCHContainerOperations> PCHContainerOps,DiagnosticsEngine & Diag,LangOptions & LangOpts,SourceManager & SourceMgr,FileManager & FileMgr,SmallVectorImpl<StoredDiagnostic> & StoredDiagnostics,SmallVectorImpl<const llvm::MemoryBuffer * > & OwnedBuffers)2121bb165fb0SAdrian Prantl void ASTUnit::CodeComplete(
2122bb165fb0SAdrian Prantl     StringRef File, unsigned Line, unsigned Column,
2123bb165fb0SAdrian Prantl     ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
2124bb165fb0SAdrian Prantl     bool IncludeCodePatterns, bool IncludeBriefComments,
21258e984da8SDouglas Gregor     CodeCompleteConsumer &Consumer,
2126bb165fb0SAdrian Prantl     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
2127bb165fb0SAdrian Prantl     DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,
2128bb165fb0SAdrian Prantl     FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
21290e62c1ccSChris Lattner     SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
21305e14d39aSTed Kremenek   if (!Invocation)
21318e984da8SDouglas Gregor     return;
21328e984da8SDouglas Gregor 
213316896c45SDouglas Gregor   SimpleTimer CompletionTimer(WantTiming);
2134f2e5a91fSBenjamin Kramer   CompletionTimer.setOutput("Code completion @ " + File + ":" +
21350e62c1ccSChris Lattner                             Twine(Line) + ":" + Twine(Column));
2136028d3e4dSDouglas Gregor 
2137ea4395ebSDavid Blaikie   auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);
21385e14d39aSTed Kremenek 
21395e14d39aSTed Kremenek   FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();
21403292d06aSDmitri Gribenko   CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;
21415e14d39aSTed Kremenek   PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
21428e984da8SDouglas Gregor 
21433292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeMacros = IncludeMacros &&
21443292d06aSDmitri Gribenko                                    CachedCompletionResults.empty();
21453292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
21463292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
21473292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
2148bb2cf63bSSam McCall   CodeCompleteOpts.LoadExternal = Consumer.loadExternal();
2149b4670fc7SIvan Donchevskii   CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts();
21503292d06aSDmitri Gribenko 
21513292d06aSDmitri Gribenko   assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);
21523292d06aSDmitri Gribenko 
2153adcd0268SBenjamin Kramer   FrontendOpts.CodeCompletionAt.FileName = std::string(File);
21548e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.Line = Line;
21558e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.Column = Column;
21568e984da8SDouglas Gregor 
21578e984da8SDouglas Gregor   // Set the language options appropriately.
21588cf47df7STed Kremenek   LangOpts = *CCInvocation->getLangOpts();
21598e984da8SDouglas Gregor 
216006e8d69aSArgyrios Kyrtzidis   // Spell-checking and warnings are wasteful during code-completion.
216106e8d69aSArgyrios Kyrtzidis   LangOpts.SpellChecking = false;
216206e8d69aSArgyrios Kyrtzidis   CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;
216306e8d69aSArgyrios Kyrtzidis 
2164bb165fb0SAdrian Prantl   std::unique_ptr<CompilerInstance> Clang(
2165bb165fb0SAdrian Prantl       new CompilerInstance(PCHContainerOps));
216684de4a17STed Kremenek 
216784de4a17STed Kremenek   // Recover resources if we crash before exiting this method.
2168022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
2169022a4904STed Kremenek     CICleanup(Clang.get());
217084de4a17STed Kremenek 
2171ea4395ebSDavid Blaikie   auto &Inv = *CCInvocation;
2172ea4395ebSDavid Blaikie   Clang->setInvocation(std::move(CCInvocation));
2173adcd0268SBenjamin Kramer   OriginalSourceFile =
2174adcd0268SBenjamin Kramer       std::string(Clang->getFrontendOpts().Inputs[0].getFile());
21758e984da8SDouglas Gregor 
21768e984da8SDouglas Gregor   // Set up diagnostics, capturing any diagnostics produced.
217784de4a17STed Kremenek   Clang->setDiagnostics(&Diag);
21788edd8da4SNikolai Kosjar   CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All,
217984de4a17STed Kremenek                                     Clang->getDiagnostics(),
2180200b3289SIlya Biryukov                                     &StoredDiagnostics, nullptr);
2181ea4395ebSDavid Blaikie   ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());
21828e984da8SDouglas Gregor 
21838e984da8SDouglas Gregor   // Create the target instance.
218414a7296cSoToToT   if (!Clang->createTarget()) {
218549a2790fSCraig Topper     Clang->setInvocation(nullptr);
21862dd19f1dSDouglas Gregor     return;
21878e984da8SDouglas Gregor   }
21888e984da8SDouglas Gregor 
218984de4a17STed Kremenek   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
21908e984da8SDouglas Gregor          "Invocation must have exactly one source file!");
219140c0efa5SRichard Smith   assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
219240c0efa5SRichard Smith              InputKind::Source &&
21938e984da8SDouglas Gregor          "FIXME: AST inputs not yet supported here!");
219440c0efa5SRichard Smith   assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
219509d890d7SRainer Orth              Language::LLVM_IR &&
21968e984da8SDouglas Gregor          "IR inputs not support here!");
21978e984da8SDouglas Gregor 
21988e984da8SDouglas Gregor   // Use the source and file managers that we were given.
219984de4a17STed Kremenek   Clang->setFileManager(&FileMgr);
220084de4a17STed Kremenek   Clang->setSourceManager(&SourceMgr);
22018e984da8SDouglas Gregor 
22028e984da8SDouglas Gregor   // Remap files.
22038e984da8SDouglas Gregor   PreprocessorOpts.clearRemappedFiles();
2204d8a5dba9SDouglas Gregor   PreprocessorOpts.RetainRemappedFileBuffers = true;
22056a96ae5eSBenjamin Kramer   for (const auto &RemappedFile : RemappedFiles) {
22066a96ae5eSBenjamin Kramer     PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second);
22076a96ae5eSBenjamin Kramer     OwnedBuffers.push_back(RemappedFile.second);
2208b97b666cSDouglas Gregor   }
22098e984da8SDouglas Gregor 
2210b14904c4SDouglas Gregor   // Use the code completion consumer we were given, but adding any cached
2211b14904c4SDouglas Gregor   // code-completion results.
2212e9186e6dSDouglas Gregor   AugmentedCodeCompleteConsumer *AugmentedConsumer
22133292d06aSDmitri Gribenko     = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);
221484de4a17STed Kremenek   Clang->setCodeCompletionConsumer(AugmentedConsumer);
22158e984da8SDouglas Gregor 
221651f3432fSDuncan P. N. Exon Smith   auto getUniqueID =
221751f3432fSDuncan P. N. Exon Smith       [&FileMgr](StringRef Filename) -> Optional<llvm::sys::fs::UniqueID> {
221851f3432fSDuncan P. N. Exon Smith     if (auto Status = FileMgr.getVirtualFileSystem().status(Filename))
221951f3432fSDuncan P. N. Exon Smith       return Status->getUniqueID();
222051f3432fSDuncan P. N. Exon Smith     return None;
222151f3432fSDuncan P. N. Exon Smith   };
222251f3432fSDuncan P. N. Exon Smith 
222351f3432fSDuncan P. N. Exon Smith   auto hasSameUniqueID = [getUniqueID](StringRef LHS, StringRef RHS) {
222451f3432fSDuncan P. N. Exon Smith     if (LHS == RHS)
222551f3432fSDuncan P. N. Exon Smith       return true;
222651f3432fSDuncan P. N. Exon Smith     if (auto LHSID = getUniqueID(LHS))
222751f3432fSDuncan P. N. Exon Smith       if (auto RHSID = getUniqueID(RHS))
222851f3432fSDuncan P. N. Exon Smith         return *LHSID == *RHSID;
222951f3432fSDuncan P. N. Exon Smith     return false;
223051f3432fSDuncan P. N. Exon Smith   };
223151f3432fSDuncan P. N. Exon Smith 
2232028d3e4dSDouglas Gregor   // If we have a precompiled preamble, try to use it. We only allow
2233028d3e4dSDouglas Gregor   // the use of the precompiled preamble if we're if the completion
2234028d3e4dSDouglas Gregor   // point is within the main file, after the end of the precompiled
2235028d3e4dSDouglas Gregor   // preamble.
22362346a375SRafael Espindola   std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
223751f3432fSDuncan P. N. Exon Smith   if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) {
22382346a375SRafael Espindola     OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(
223951f3432fSDuncan P. N. Exon Smith         PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1);
2240f9e9bb88SRafael Espindola   }
2241028d3e4dSDouglas Gregor 
2242028d3e4dSDouglas Gregor   // If the main file has been overridden due to the use of a preamble,
2243028d3e4dSDouglas Gregor   // make that override happen and introduce the preamble.
2244028d3e4dSDouglas Gregor   if (OverrideMainBuffer) {
2245417085acSIlya Biryukov     assert(Preamble &&
2246417085acSIlya Biryukov            "No preamble was built, but OverrideMainBuffer is not null");
2247417085acSIlya Biryukov 
2248db8a7422SDuncan P. N. Exon Smith     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
2249db8a7422SDuncan P. N. Exon Smith         &FileMgr.getVirtualFileSystem();
2250417085acSIlya Biryukov     Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,
2251417085acSIlya Biryukov                                   OverrideMainBuffer.get());
2252417085acSIlya Biryukov     // FIXME: there is no way to update VFS if it was changed by
2253417085acSIlya Biryukov     // AddImplicitPreamble as FileMgr is accepted as a parameter by this method.
2254417085acSIlya Biryukov     // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the
2255417085acSIlya Biryukov     // PCH files are always readable.
22562346a375SRafael Espindola     OwnedBuffers.push_back(OverrideMainBuffer.release());
22577b02b583SDouglas Gregor   } else {
22587b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
22597b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second = false;
2260028d3e4dSDouglas Gregor   }
2261028d3e4dSDouglas Gregor 
2262870704f6SArgyrios Kyrtzidis   // Disable the preprocessing record if modules are not enabled.
2263870704f6SArgyrios Kyrtzidis   if (!Clang->getLangOpts().Modules)
2264998caeadSDouglas Gregor     PreprocessorOpts.DetailedRecord = false;
2265998caeadSDouglas Gregor 
2266b8984329SAhmed Charles   std::unique_ptr<SyntaxOnlyAction> Act;
22678e984da8SDouglas Gregor   Act.reset(new SyntaxOnlyAction);
226832fbe312SDouglas Gregor   if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
22690e828958SJF Bastien     if (llvm::Error Err = Act->Execute()) {
22700e828958SJF Bastien       consumeError(std::move(Err)); // FIXME this drops errors on the floor.
22710e828958SJF Bastien     }
22728e984da8SDouglas Gregor     Act->EndSourceFile();
22738e984da8SDouglas Gregor   }
22748e984da8SDouglas Gregor }
2275e9386680SDouglas Gregor 
Save(StringRef File)227639a76387SArgyrios Kyrtzidis bool ASTUnit::Save(StringRef File) {
2277dc9fdaf2SArgyrios Kyrtzidis   if (HadModuleLoaderFatalFailure)
2278dc9fdaf2SArgyrios Kyrtzidis     return true;
2279dc9fdaf2SArgyrios Kyrtzidis 
228055e75574SArgyrios Kyrtzidis   // Write to a temporary file and later rename it to the actual file, to avoid
228155e75574SArgyrios Kyrtzidis   // possible race conditions.
22822c1dd271SDylan Noblesmith   SmallString<128> TempPath;
228308a2bfd2SArgyrios Kyrtzidis   TempPath = File;
228408a2bfd2SArgyrios Kyrtzidis   TempPath += "-%%%%%%%%";
2285e9386680SDouglas Gregor   // FIXME: Can we somehow regenerate the stat cache here, or do we need to
2286e9386680SDouglas Gregor   // unconditionally create a stat cache when we parse the file?
2287e9386680SDouglas Gregor 
2288f69c9178SJan Korous   if (llvm::Error Err = llvm::writeFileAtomically(
2289f69c9178SJan Korous           TempPath, File, [this](llvm::raw_ostream &Out) {
2290f69c9178SJan Korous             return serialize(Out) ? llvm::make_error<llvm::StringError>(
2291f69c9178SJan Korous                                         "ASTUnit serialization failed",
2292f69c9178SJan Korous                                         llvm::inconvertibleErrorCode())
2293f69c9178SJan Korous                                   : llvm::Error::success();
2294f69c9178SJan Korous           })) {
2295f69c9178SJan Korous     consumeError(std::move(Err));
229639a76387SArgyrios Kyrtzidis     return true;
2297eeea16a0SArgyrios Kyrtzidis   }
229839a76387SArgyrios Kyrtzidis   return false;
229935dcda79SArgyrios Kyrtzidis }
230035dcda79SArgyrios Kyrtzidis 
serializeUnit(ASTWriter & Writer,SmallVectorImpl<char> & Buffer,Sema & S,bool hasErrors,raw_ostream & OS)23010db720f0SArgyrios Kyrtzidis static bool serializeUnit(ASTWriter &Writer,
23020db720f0SArgyrios Kyrtzidis                           SmallVectorImpl<char> &Buffer,
23030db720f0SArgyrios Kyrtzidis                           Sema &S,
23040db720f0SArgyrios Kyrtzidis                           bool hasErrors,
23050db720f0SArgyrios Kyrtzidis                           raw_ostream &OS) {
230649a2790fSCraig Topper   Writer.WriteAST(S, std::string(), nullptr, "", hasErrors);
23070db720f0SArgyrios Kyrtzidis 
23080db720f0SArgyrios Kyrtzidis   // Write the generated bitstream to "Out".
23090db720f0SArgyrios Kyrtzidis   if (!Buffer.empty())
23100db720f0SArgyrios Kyrtzidis     OS.write(Buffer.data(), Buffer.size());
23110db720f0SArgyrios Kyrtzidis 
23120db720f0SArgyrios Kyrtzidis   return false;
23130db720f0SArgyrios Kyrtzidis }
23140db720f0SArgyrios Kyrtzidis 
serialize(raw_ostream & OS)23150e62c1ccSChris Lattner bool ASTUnit::serialize(raw_ostream &OS) {
231670ec1c7eSArgyrios Kyrtzidis   // For serialization we are lenient if the errors were only warn-as-error kind.
231770ec1c7eSArgyrios Kyrtzidis   bool hasErrors = getDiagnostics().hasUncompilableErrorOccurred();
231835dcda79SArgyrios Kyrtzidis 
23190db720f0SArgyrios Kyrtzidis   if (WriterData)
23200db720f0SArgyrios Kyrtzidis     return serializeUnit(WriterData->Writer, WriterData->Buffer,
23210db720f0SArgyrios Kyrtzidis                          getSema(), hasErrors, OS);
23220db720f0SArgyrios Kyrtzidis 
23239a96386eSDaniel Dunbar   SmallString<128> Buffer;
2324e9386680SDouglas Gregor   llvm::BitstreamWriter Stream(Buffer);
23258bef5cd4SDuncan P. N. Exon Smith   InMemoryModuleCache ModuleCache;
23268bef5cd4SDuncan P. N. Exon Smith   ASTWriter Writer(Stream, Buffer, ModuleCache, {});
23270db720f0SArgyrios Kyrtzidis   return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
2328e9386680SDouglas Gregor }
2329925296b4SDouglas Gregor 
23304f233181SEugene Zelenko using SLocRemap = ContinuousRangeMap<unsigned, int, 2>;
2331925296b4SDouglas Gregor 
TranslateStoredDiagnostics(FileManager & FileMgr,SourceManager & SrcMgr,const SmallVectorImpl<StandaloneDiagnostic> & Diags,SmallVectorImpl<StoredDiagnostic> & Out)2332925296b4SDouglas Gregor void ASTUnit::TranslateStoredDiagnostics(
233324c55228SArgyrios Kyrtzidis                           FileManager &FileMgr,
2334925296b4SDouglas Gregor                           SourceManager &SrcMgr,
233524c55228SArgyrios Kyrtzidis                           const SmallVectorImpl<StandaloneDiagnostic> &Diags,
23360e62c1ccSChris Lattner                           SmallVectorImpl<StoredDiagnostic> &Out) {
233724c55228SArgyrios Kyrtzidis   // Map the standalone diagnostic into the new source manager. We also need to
233824c55228SArgyrios Kyrtzidis   // remap all the locations to the new view. This includes the diag location,
233924c55228SArgyrios Kyrtzidis   // any associated source ranges, and the source ranges of associated fix-its.
2340925296b4SDouglas Gregor   // FIXME: There should be a cleaner way to do this.
23410e62c1ccSChris Lattner   SmallVector<StoredDiagnostic, 4> Result;
2342925296b4SDouglas Gregor   Result.reserve(Diags.size());
2343efe6fa50SErik Verbruggen 
23444f233181SEugene Zelenko   for (const auto &SD : Diags) {
2345925296b4SDouglas Gregor     // Rebuild the StoredDiagnostic.
234624c55228SArgyrios Kyrtzidis     if (SD.Filename.empty())
234724c55228SArgyrios Kyrtzidis       continue;
23488d323d15SHarlan Haskins     auto FE = FileMgr.getFile(SD.Filename);
234924c55228SArgyrios Kyrtzidis     if (!FE)
235024c55228SArgyrios Kyrtzidis       continue;
2351efe6fa50SErik Verbruggen     SourceLocation FileLoc;
2352efe6fa50SErik Verbruggen     auto ItFileID = PreambleSrcLocCache.find(SD.Filename);
2353efe6fa50SErik Verbruggen     if (ItFileID == PreambleSrcLocCache.end()) {
23548d323d15SHarlan Haskins       FileID FID = SrcMgr.translateFile(*FE);
2355efe6fa50SErik Verbruggen       FileLoc = SrcMgr.getLocForStartOfFile(FID);
2356efe6fa50SErik Verbruggen       PreambleSrcLocCache[SD.Filename] = FileLoc;
2357efe6fa50SErik Verbruggen     } else {
2358efe6fa50SErik Verbruggen       FileLoc = ItFileID->getValue();
23592c7c38d9SErik Verbruggen     }
2360efe6fa50SErik Verbruggen 
236124c55228SArgyrios Kyrtzidis     if (FileLoc.isInvalid())
236224c55228SArgyrios Kyrtzidis       continue;
236324c55228SArgyrios Kyrtzidis     SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
2364925296b4SDouglas Gregor     FullSourceLoc Loc(L, SrcMgr);
2365925296b4SDouglas Gregor 
23660e62c1ccSChris Lattner     SmallVector<CharSourceRange, 4> Ranges;
236724c55228SArgyrios Kyrtzidis     Ranges.reserve(SD.Ranges.size());
23686a96ae5eSBenjamin Kramer     for (const auto &Range : SD.Ranges) {
23696a96ae5eSBenjamin Kramer       SourceLocation BL = FileLoc.getLocWithOffset(Range.first);
23706a96ae5eSBenjamin Kramer       SourceLocation EL = FileLoc.getLocWithOffset(Range.second);
237124c55228SArgyrios Kyrtzidis       Ranges.push_back(CharSourceRange::getCharRange(BL, EL));
2372925296b4SDouglas Gregor     }
2373925296b4SDouglas Gregor 
23740e62c1ccSChris Lattner     SmallVector<FixItHint, 2> FixIts;
237524c55228SArgyrios Kyrtzidis     FixIts.reserve(SD.FixIts.size());
23764f233181SEugene Zelenko     for (const auto &FixIt : SD.FixIts) {
2377925296b4SDouglas Gregor       FixIts.push_back(FixItHint());
2378925296b4SDouglas Gregor       FixItHint &FH = FixIts.back();
23796a96ae5eSBenjamin Kramer       FH.CodeToInsert = FixIt.CodeToInsert;
23806a96ae5eSBenjamin Kramer       SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first);
23816a96ae5eSBenjamin Kramer       SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second);
238224c55228SArgyrios Kyrtzidis       FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
2383925296b4SDouglas Gregor     }
2384925296b4SDouglas Gregor 
238524c55228SArgyrios Kyrtzidis     Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
238624c55228SArgyrios Kyrtzidis                                       SD.Message, Loc, Ranges, FixIts));
2387925296b4SDouglas Gregor   }
2388925296b4SDouglas Gregor   Result.swap(Out);
2389925296b4SDouglas Gregor }
23907c06d866SArgyrios Kyrtzidis 
addFileLevelDecl(Decl * D)2391e54568d6SArgyrios Kyrtzidis void ASTUnit::addFileLevelDecl(Decl *D) {
2392e54568d6SArgyrios Kyrtzidis   assert(D);
239361d63d0fSDouglas Gregor 
239461d63d0fSDouglas Gregor   // We only care about local declarations.
239561d63d0fSDouglas Gregor   if (D->isFromASTFile())
239661d63d0fSDouglas Gregor     return;
2397e54568d6SArgyrios Kyrtzidis 
2398e54568d6SArgyrios Kyrtzidis   SourceManager &SM = *SourceMgr;
2399e54568d6SArgyrios Kyrtzidis   SourceLocation Loc = D->getLocation();
2400e54568d6SArgyrios Kyrtzidis   if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc))
2401e54568d6SArgyrios Kyrtzidis     return;
2402e54568d6SArgyrios Kyrtzidis 
2403e54568d6SArgyrios Kyrtzidis   // We only keep track of the file-level declarations of each file.
2404e54568d6SArgyrios Kyrtzidis   if (!D->getLexicalDeclContext()->isFileContext())
2405e54568d6SArgyrios Kyrtzidis     return;
2406e54568d6SArgyrios Kyrtzidis 
2407e54568d6SArgyrios Kyrtzidis   SourceLocation FileLoc = SM.getFileLoc(Loc);
2408e54568d6SArgyrios Kyrtzidis   assert(SM.isLocalSourceLocation(FileLoc));
2409e54568d6SArgyrios Kyrtzidis   FileID FID;
2410e54568d6SArgyrios Kyrtzidis   unsigned Offset;
2411867ea1d4SBenjamin Kramer   std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
2412e54568d6SArgyrios Kyrtzidis   if (FID.isInvalid())
2413e54568d6SArgyrios Kyrtzidis     return;
2414e54568d6SArgyrios Kyrtzidis 
2415d9485dfbSDavid Blaikie   std::unique_ptr<LocDeclsTy> &Decls = FileDecls[FID];
2416e54568d6SArgyrios Kyrtzidis   if (!Decls)
2417d9485dfbSDavid Blaikie     Decls = std::make_unique<LocDeclsTy>();
2418e54568d6SArgyrios Kyrtzidis 
2419e54568d6SArgyrios Kyrtzidis   std::pair<unsigned, Decl *> LocDecl(Offset, D);
2420e54568d6SArgyrios Kyrtzidis 
2421e54568d6SArgyrios Kyrtzidis   if (Decls->empty() || Decls->back().first <= Offset) {
2422e54568d6SArgyrios Kyrtzidis     Decls->push_back(LocDecl);
2423e54568d6SArgyrios Kyrtzidis     return;
2424e54568d6SArgyrios Kyrtzidis   }
2425e54568d6SArgyrios Kyrtzidis 
24267264a474SFangrui Song   LocDeclsTy::iterator I =
24277264a474SFangrui Song       llvm::upper_bound(*Decls, LocDecl, llvm::less_first());
2428e54568d6SArgyrios Kyrtzidis 
2429e54568d6SArgyrios Kyrtzidis   Decls->insert(I, LocDecl);
2430e54568d6SArgyrios Kyrtzidis }
2431e54568d6SArgyrios Kyrtzidis 
findFileRegionDecls(FileID File,unsigned Offset,unsigned Length,SmallVectorImpl<Decl * > & Decls)2432e9681525SArgyrios Kyrtzidis void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
2433e9681525SArgyrios Kyrtzidis                                   SmallVectorImpl<Decl *> &Decls) {
2434e9681525SArgyrios Kyrtzidis   if (File.isInvalid())
2435e9681525SArgyrios Kyrtzidis     return;
2436e9681525SArgyrios Kyrtzidis 
2437e9681525SArgyrios Kyrtzidis   if (SourceMgr->isLoadedFileID(File)) {
2438e9681525SArgyrios Kyrtzidis     assert(Ctx->getExternalSource() && "No external source!");
2439e9681525SArgyrios Kyrtzidis     return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length,
2440e9681525SArgyrios Kyrtzidis                                                          Decls);
2441e9681525SArgyrios Kyrtzidis   }
2442e9681525SArgyrios Kyrtzidis 
2443e9681525SArgyrios Kyrtzidis   FileDeclsTy::iterator I = FileDecls.find(File);
2444e9681525SArgyrios Kyrtzidis   if (I == FileDecls.end())
2445e9681525SArgyrios Kyrtzidis     return;
2446e9681525SArgyrios Kyrtzidis 
2447e9681525SArgyrios Kyrtzidis   LocDeclsTy &LocDecls = *I->second;
2448e9681525SArgyrios Kyrtzidis   if (LocDecls.empty())
2449e9681525SArgyrios Kyrtzidis     return;
2450e9681525SArgyrios Kyrtzidis 
2451e3e855bbSBenjamin Kramer   LocDeclsTy::iterator BeginIt =
24527264a474SFangrui Song       llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) {
24537264a474SFangrui Song         return LD.first < Offset;
24547264a474SFangrui Song       });
2455e9681525SArgyrios Kyrtzidis   if (BeginIt != LocDecls.begin())
2456e9681525SArgyrios Kyrtzidis     --BeginIt;
2457e9681525SArgyrios Kyrtzidis 
24588ad3bab5SArgyrios Kyrtzidis   // If we are pointing at a top-level decl inside an objc container, we need
24598ad3bab5SArgyrios Kyrtzidis   // to backtrack until we find it otherwise we will fail to report that the
24608ad3bab5SArgyrios Kyrtzidis   // region overlaps with an objc container.
24618ad3bab5SArgyrios Kyrtzidis   while (BeginIt != LocDecls.begin() &&
24628ad3bab5SArgyrios Kyrtzidis          BeginIt->second->isTopLevelDeclInObjCContainer())
24638ad3bab5SArgyrios Kyrtzidis     --BeginIt;
24648ad3bab5SArgyrios Kyrtzidis 
24657264a474SFangrui Song   LocDeclsTy::iterator EndIt = llvm::upper_bound(
24667264a474SFangrui Song       LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr),
24677264a474SFangrui Song       llvm::less_first());
2468e9681525SArgyrios Kyrtzidis   if (EndIt != LocDecls.end())
2469e9681525SArgyrios Kyrtzidis     ++EndIt;
2470e9681525SArgyrios Kyrtzidis 
2471e9681525SArgyrios Kyrtzidis   for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)
2472e9681525SArgyrios Kyrtzidis     Decls.push_back(DIt->second);
2473e9681525SArgyrios Kyrtzidis }
2474e9681525SArgyrios Kyrtzidis 
getLocation(const FileEntry * File,unsigned Line,unsigned Col) const24757c06d866SArgyrios Kyrtzidis SourceLocation ASTUnit::getLocation(const FileEntry *File,
24767c06d866SArgyrios Kyrtzidis                                     unsigned Line, unsigned Col) const {
24777c06d866SArgyrios Kyrtzidis   const SourceManager &SM = getSourceManager();
24784cdfcae7SArgyrios Kyrtzidis   SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);
24797c06d866SArgyrios Kyrtzidis   return SM.getMacroArgExpandedLocation(Loc);
24807c06d866SArgyrios Kyrtzidis }
24817c06d866SArgyrios Kyrtzidis 
getLocation(const FileEntry * File,unsigned Offset) const24827c06d866SArgyrios Kyrtzidis SourceLocation ASTUnit::getLocation(const FileEntry *File,
24837c06d866SArgyrios Kyrtzidis                                     unsigned Offset) const {
24847c06d866SArgyrios Kyrtzidis   const SourceManager &SM = getSourceManager();
24854cdfcae7SArgyrios Kyrtzidis   SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);
24867c06d866SArgyrios Kyrtzidis   return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
24877c06d866SArgyrios Kyrtzidis }
24887c06d866SArgyrios Kyrtzidis 
24899fc8faf9SAdrian Prantl /// If \arg Loc is a loaded location from the preamble, returns
24904cdfcae7SArgyrios Kyrtzidis /// the corresponding local location of the main file, otherwise it returns
24914cdfcae7SArgyrios Kyrtzidis /// \arg Loc.
mapLocationFromPreamble(SourceLocation Loc) const2492525a7f6bSVedant Kumar SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {
24934cdfcae7SArgyrios Kyrtzidis   FileID PreambleID;
24944cdfcae7SArgyrios Kyrtzidis   if (SourceMgr)
24954cdfcae7SArgyrios Kyrtzidis     PreambleID = SourceMgr->getPreambleFileID();
24964cdfcae7SArgyrios Kyrtzidis 
2497200b3289SIlya Biryukov   if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())
24984cdfcae7SArgyrios Kyrtzidis     return Loc;
24994cdfcae7SArgyrios Kyrtzidis 
25004cdfcae7SArgyrios Kyrtzidis   unsigned Offs;
2501200b3289SIlya Biryukov   if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) {
25024cdfcae7SArgyrios Kyrtzidis     SourceLocation FileLoc
25034cdfcae7SArgyrios Kyrtzidis         = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());
25044cdfcae7SArgyrios Kyrtzidis     return FileLoc.getLocWithOffset(Offs);
25054cdfcae7SArgyrios Kyrtzidis   }
25064cdfcae7SArgyrios Kyrtzidis 
25074cdfcae7SArgyrios Kyrtzidis   return Loc;
25084cdfcae7SArgyrios Kyrtzidis }
25094cdfcae7SArgyrios Kyrtzidis 
25109fc8faf9SAdrian Prantl /// If \arg Loc is a local location of the main file but inside the
25114cdfcae7SArgyrios Kyrtzidis /// preamble chunk, returns the corresponding loaded location from the
25124cdfcae7SArgyrios Kyrtzidis /// preamble, otherwise it returns \arg Loc.
mapLocationToPreamble(SourceLocation Loc) const2513525a7f6bSVedant Kumar SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {
25144cdfcae7SArgyrios Kyrtzidis   FileID PreambleID;
25154cdfcae7SArgyrios Kyrtzidis   if (SourceMgr)
25164cdfcae7SArgyrios Kyrtzidis     PreambleID = SourceMgr->getPreambleFileID();
25174cdfcae7SArgyrios Kyrtzidis 
2518200b3289SIlya Biryukov   if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())
25194cdfcae7SArgyrios Kyrtzidis     return Loc;
25204cdfcae7SArgyrios Kyrtzidis 
25214cdfcae7SArgyrios Kyrtzidis   unsigned Offs;
25224cdfcae7SArgyrios Kyrtzidis   if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&
2523200b3289SIlya Biryukov       Offs < Preamble->getBounds().Size) {
25244cdfcae7SArgyrios Kyrtzidis     SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);
25254cdfcae7SArgyrios Kyrtzidis     return FileLoc.getLocWithOffset(Offs);
25264cdfcae7SArgyrios Kyrtzidis   }
25274cdfcae7SArgyrios Kyrtzidis 
25284cdfcae7SArgyrios Kyrtzidis   return Loc;
25294cdfcae7SArgyrios Kyrtzidis }
25304cdfcae7SArgyrios Kyrtzidis 
isInPreambleFileID(SourceLocation Loc) const2531525a7f6bSVedant Kumar bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {
2532429ec024SArgyrios Kyrtzidis   FileID FID;
2533429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2534429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getPreambleFileID();
2535429ec024SArgyrios Kyrtzidis 
2536429ec024SArgyrios Kyrtzidis   if (Loc.isInvalid() || FID.isInvalid())
2537429ec024SArgyrios Kyrtzidis     return false;
2538429ec024SArgyrios Kyrtzidis 
2539429ec024SArgyrios Kyrtzidis   return SourceMgr->isInFileID(Loc, FID);
2540429ec024SArgyrios Kyrtzidis }
2541429ec024SArgyrios Kyrtzidis 
isInMainFileID(SourceLocation Loc) const2542525a7f6bSVedant Kumar bool ASTUnit::isInMainFileID(SourceLocation Loc) const {
2543429ec024SArgyrios Kyrtzidis   FileID FID;
2544429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2545429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getMainFileID();
2546429ec024SArgyrios Kyrtzidis 
2547429ec024SArgyrios Kyrtzidis   if (Loc.isInvalid() || FID.isInvalid())
2548429ec024SArgyrios Kyrtzidis     return false;
2549429ec024SArgyrios Kyrtzidis 
2550429ec024SArgyrios Kyrtzidis   return SourceMgr->isInFileID(Loc, FID);
2551429ec024SArgyrios Kyrtzidis }
2552429ec024SArgyrios Kyrtzidis 
getEndOfPreambleFileID() const2553525a7f6bSVedant Kumar SourceLocation ASTUnit::getEndOfPreambleFileID() const {
2554429ec024SArgyrios Kyrtzidis   FileID FID;
2555429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2556429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getPreambleFileID();
2557429ec024SArgyrios Kyrtzidis 
2558429ec024SArgyrios Kyrtzidis   if (FID.isInvalid())
25594f233181SEugene Zelenko     return {};
2560429ec024SArgyrios Kyrtzidis 
2561429ec024SArgyrios Kyrtzidis   return SourceMgr->getLocForEndOfFile(FID);
2562429ec024SArgyrios Kyrtzidis }
2563429ec024SArgyrios Kyrtzidis 
getStartOfMainFileID() const2564525a7f6bSVedant Kumar SourceLocation ASTUnit::getStartOfMainFileID() const {
2565429ec024SArgyrios Kyrtzidis   FileID FID;
2566429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2567429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getMainFileID();
2568429ec024SArgyrios Kyrtzidis 
2569429ec024SArgyrios Kyrtzidis   if (FID.isInvalid())
25704f233181SEugene Zelenko     return {};
2571429ec024SArgyrios Kyrtzidis 
2572429ec024SArgyrios Kyrtzidis   return SourceMgr->getLocForStartOfFile(FID);
2573429ec024SArgyrios Kyrtzidis }
2574429ec024SArgyrios Kyrtzidis 
2575b4ef6683SBenjamin Kramer llvm::iterator_range<PreprocessingRecord::iterator>
getLocalPreprocessingEntities() const2576d4fcf580SArgyrios Kyrtzidis ASTUnit::getLocalPreprocessingEntities() const {
2577d4fcf580SArgyrios Kyrtzidis   if (isMainFileAST()) {
2578d4fcf580SArgyrios Kyrtzidis     serialization::ModuleFile &
2579d4fcf580SArgyrios Kyrtzidis       Mod = Reader->getModuleManager().getPrimaryModule();
2580d4fcf580SArgyrios Kyrtzidis     return Reader->getModulePreprocessedEntities(Mod);
2581d4fcf580SArgyrios Kyrtzidis   }
2582d4fcf580SArgyrios Kyrtzidis 
2583d4fcf580SArgyrios Kyrtzidis   if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
2584b4ef6683SBenjamin Kramer     return llvm::make_range(PPRec->local_begin(), PPRec->local_end());
2585d4fcf580SArgyrios Kyrtzidis 
2586b4ef6683SBenjamin Kramer   return llvm::make_range(PreprocessingRecord::iterator(),
2587d4fcf580SArgyrios Kyrtzidis                           PreprocessingRecord::iterator());
2588d4fcf580SArgyrios Kyrtzidis }
2589d4fcf580SArgyrios Kyrtzidis 
visitLocalTopLevelDecls(void * context,DeclVisitorFn Fn)2590e514b200SArgyrios Kyrtzidis bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
259110e7846aSArgyrios Kyrtzidis   if (isMainFileAST()) {
259210e7846aSArgyrios Kyrtzidis     serialization::ModuleFile &
259310e7846aSArgyrios Kyrtzidis       Mod = Reader->getModuleManager().getPrimaryModule();
25944f233181SEugene Zelenko     for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {
2595b4ef6683SBenjamin Kramer       if (!Fn(context, D))
259610e7846aSArgyrios Kyrtzidis         return false;
259710e7846aSArgyrios Kyrtzidis     }
259810e7846aSArgyrios Kyrtzidis 
259910e7846aSArgyrios Kyrtzidis     return true;
260010e7846aSArgyrios Kyrtzidis   }
260110e7846aSArgyrios Kyrtzidis 
260210e7846aSArgyrios Kyrtzidis   for (ASTUnit::top_level_iterator TL = top_level_begin(),
260310e7846aSArgyrios Kyrtzidis                                 TLEnd = top_level_end();
260410e7846aSArgyrios Kyrtzidis          TL != TLEnd; ++TL) {
260510e7846aSArgyrios Kyrtzidis     if (!Fn(context, *TL))
260610e7846aSArgyrios Kyrtzidis       return false;
260710e7846aSArgyrios Kyrtzidis   }
260810e7846aSArgyrios Kyrtzidis 
260910e7846aSArgyrios Kyrtzidis   return true;
261010e7846aSArgyrios Kyrtzidis }
261110e7846aSArgyrios Kyrtzidis 
getPCHFile()26129a9efbafSBenjamin Kramer const FileEntry *ASTUnit::getPCHFile() {
26139a9efbafSBenjamin Kramer   if (!Reader)
26149a9efbafSBenjamin Kramer     return nullptr;
2615f484b139SArgyrios Kyrtzidis 
26169a9efbafSBenjamin Kramer   serialization::ModuleFile *Mod = nullptr;
26179a9efbafSBenjamin Kramer   Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) {
2618f484b139SArgyrios Kyrtzidis     switch (M.Kind) {
2619e842a474SRichard Smith     case serialization::MK_ImplicitModule:
2620e842a474SRichard Smith     case serialization::MK_ExplicitModule:
262111f2a477SManman Ren     case serialization::MK_PrebuiltModule:
2622f484b139SArgyrios Kyrtzidis       return true; // skip dependencies.
2623f484b139SArgyrios Kyrtzidis     case serialization::MK_PCH:
26249a9efbafSBenjamin Kramer       Mod = &M;
2625f484b139SArgyrios Kyrtzidis       return true; // found it.
2626f484b139SArgyrios Kyrtzidis     case serialization::MK_Preamble:
2627f484b139SArgyrios Kyrtzidis       return false; // look in dependencies.
2628f484b139SArgyrios Kyrtzidis     case serialization::MK_MainFile:
2629f484b139SArgyrios Kyrtzidis       return false; // look in dependencies.
2630f484b139SArgyrios Kyrtzidis     }
2631f484b139SArgyrios Kyrtzidis 
2632f484b139SArgyrios Kyrtzidis     return true;
26339a9efbafSBenjamin Kramer   });
26349a9efbafSBenjamin Kramer   if (Mod)
26359a9efbafSBenjamin Kramer     return Mod->File;
2636f484b139SArgyrios Kyrtzidis 
263749a2790fSCraig Topper   return nullptr;
2638f484b139SArgyrios Kyrtzidis }
2639f484b139SArgyrios Kyrtzidis 
isModuleFile() const2640525a7f6bSVedant Kumar bool ASTUnit::isModuleFile() const {
2641ab75597dSRichard Smith   return isMainFileAST() && getLangOpts().isCompilingModule();
2642ab75597dSRichard Smith }
2643ab75597dSRichard Smith 
getInputKind() const2644ab75597dSRichard Smith InputKind ASTUnit::getInputKind() const {
2645ab75597dSRichard Smith   auto &LangOpts = getLangOpts();
2646ab75597dSRichard Smith 
264709d890d7SRainer Orth   Language Lang;
2648ab75597dSRichard Smith   if (LangOpts.OpenCL)
264909d890d7SRainer Orth     Lang = Language::OpenCL;
2650ab75597dSRichard Smith   else if (LangOpts.CUDA)
265109d890d7SRainer Orth     Lang = Language::CUDA;
2652ab75597dSRichard Smith   else if (LangOpts.RenderScript)
265309d890d7SRainer Orth     Lang = Language::RenderScript;
2654ab75597dSRichard Smith   else if (LangOpts.CPlusPlus)
265509d890d7SRainer Orth     Lang = LangOpts.ObjC ? Language::ObjCXX : Language::CXX;
2656ab75597dSRichard Smith   else
265709d890d7SRainer Orth     Lang = LangOpts.ObjC ? Language::ObjC : Language::C;
2658ab75597dSRichard Smith 
2659ab75597dSRichard Smith   InputKind::Format Fmt = InputKind::Source;
2660ab75597dSRichard Smith   if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)
2661ab75597dSRichard Smith     Fmt = InputKind::ModuleMap;
2662ab75597dSRichard Smith 
2663ab75597dSRichard Smith   // We don't know if input was preprocessed. Assume not.
2664ab75597dSRichard Smith   bool PP = false;
2665ab75597dSRichard Smith 
2666ab75597dSRichard Smith   return InputKind(Lang, Fmt, PP);
2667e445c723SArgyrios Kyrtzidis }
2668e445c723SArgyrios Kyrtzidis 
2669ebf01369SArgyrios Kyrtzidis #ifndef NDEBUG
ConcurrencyState()2670ebf01369SArgyrios Kyrtzidis ASTUnit::ConcurrencyState::ConcurrencyState() {
2671e57b60f3SBenjamin Kramer   Mutex = new std::recursive_mutex;
2672ebf01369SArgyrios Kyrtzidis }
2673ebf01369SArgyrios Kyrtzidis 
~ConcurrencyState()2674ebf01369SArgyrios Kyrtzidis ASTUnit::ConcurrencyState::~ConcurrencyState() {
2675e57b60f3SBenjamin Kramer   delete static_cast<std::recursive_mutex *>(Mutex);
2676ebf01369SArgyrios Kyrtzidis }
2677ebf01369SArgyrios Kyrtzidis 
start()2678ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::start() {
2679e57b60f3SBenjamin Kramer   bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock();
2680ebf01369SArgyrios Kyrtzidis   assert(acquired && "Concurrent access to ASTUnit!");
2681ebf01369SArgyrios Kyrtzidis }
2682ebf01369SArgyrios Kyrtzidis 
finish()2683ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::finish() {
2684e57b60f3SBenjamin Kramer   static_cast<std::recursive_mutex *>(Mutex)->unlock();
2685ebf01369SArgyrios Kyrtzidis }
2686ebf01369SArgyrios Kyrtzidis 
2687ebf01369SArgyrios Kyrtzidis #else // NDEBUG
2688ebf01369SArgyrios Kyrtzidis 
ConcurrencyState()2689dcfba334SHans Wennborg ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; }
~ConcurrencyState()2690637d1e66SAngel Garcia Gomez ASTUnit::ConcurrencyState::~ConcurrencyState() {}
start()2691ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::start() {}
finish()2692ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::finish() {}
2693ebf01369SArgyrios Kyrtzidis 
2694dcfba334SHans Wennborg #endif // NDEBUG
2695