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