13a08ec16SArgyrios Kyrtzidis //===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
23a08ec16SArgyrios Kyrtzidis //
33a08ec16SArgyrios Kyrtzidis //                     The LLVM Compiler Infrastructure
43a08ec16SArgyrios Kyrtzidis //
53a08ec16SArgyrios Kyrtzidis // This file is distributed under the University of Illinois Open Source
63a08ec16SArgyrios Kyrtzidis // License. See LICENSE.TXT for details.
73a08ec16SArgyrios Kyrtzidis //
83a08ec16SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
93a08ec16SArgyrios Kyrtzidis //
103a08ec16SArgyrios Kyrtzidis // ASTUnit Implementation.
113a08ec16SArgyrios Kyrtzidis //
123a08ec16SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
133a08ec16SArgyrios Kyrtzidis 
14ce379752SArgyrios Kyrtzidis #include "clang/Frontend/ASTUnit.h"
15ce379752SArgyrios Kyrtzidis #include "clang/AST/ASTContext.h"
16764c0820SDaniel Dunbar #include "clang/AST/ASTConsumer.h"
17ce379752SArgyrios Kyrtzidis #include "clang/AST/DeclVisitor.h"
18b61c07acSDouglas Gregor #include "clang/AST/TypeOrdering.h"
19ce379752SArgyrios Kyrtzidis #include "clang/AST/StmtVisitor.h"
20764c0820SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h"
21764c0820SDaniel Dunbar #include "clang/Frontend/FrontendActions.h"
2255a17b66SDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h"
23764c0820SDaniel Dunbar #include "clang/Frontend/FrontendOptions.h"
24b11f5a4cSArgyrios Kyrtzidis #include "clang/Frontend/MultiplexConsumer.h"
2536e3b5c7SDouglas Gregor #include "clang/Frontend/Utils.h"
26f5b13467SSebastian Redl #include "clang/Serialization/ASTReader.h"
271914c6feSSebastian Redl #include "clang/Serialization/ASTWriter.h"
28ce379752SArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
29ce379752SArgyrios Kyrtzidis #include "clang/Lex/Preprocessor.h"
30b9bbd54fSDaniel Dunbar #include "clang/Basic/TargetOptions.h"
31ce379752SArgyrios Kyrtzidis #include "clang/Basic/TargetInfo.h"
32ce379752SArgyrios Kyrtzidis #include "clang/Basic/Diagnostic.h"
33ce6c42f6SChris Lattner #include "llvm/ADT/ArrayRef.h"
34df7a79a9SDouglas Gregor #include "llvm/ADT/StringExtras.h"
3540a5a7deSDouglas Gregor #include "llvm/ADT/StringSet.h"
369aeaa4d6SDouglas Gregor #include "llvm/Support/Atomic.h"
37aa98ed9aSDouglas Gregor #include "llvm/Support/MemoryBuffer.h"
388aaf4995SMichael J. Spencer #include "llvm/Support/Host.h"
398aaf4995SMichael J. Spencer #include "llvm/Support/Path.h"
40028d3e4dSDouglas Gregor #include "llvm/Support/raw_ostream.h"
4115ba0b34SDouglas Gregor #include "llvm/Support/Timer.h"
4255e75574SArgyrios Kyrtzidis #include "llvm/Support/FileSystem.h"
43ebf01369SArgyrios Kyrtzidis #include "llvm/Support/Mutex.h"
44bd307a53STed Kremenek #include "llvm/Support/MutexGuard.h"
454422bfeaSTed Kremenek #include "llvm/Support/CrashRecoveryContext.h"
46be2d8c60SDouglas Gregor #include <cstdlib>
47318e4036SZhongxing Xu #include <cstdio>
480e11955cSDouglas Gregor #include <sys/stat.h>
49ce379752SArgyrios Kyrtzidis using namespace clang;
50ce379752SArgyrios Kyrtzidis 
5116896c45SDouglas Gregor using llvm::TimeRecord;
5216896c45SDouglas Gregor 
5316896c45SDouglas Gregor namespace {
5416896c45SDouglas Gregor   class SimpleTimer {
5516896c45SDouglas Gregor     bool WantTiming;
5616896c45SDouglas Gregor     TimeRecord Start;
5716896c45SDouglas Gregor     std::string Output;
5816896c45SDouglas Gregor 
5916896c45SDouglas Gregor   public:
601cbdd951SDouglas Gregor     explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {
61f2e5a91fSBenjamin Kramer       if (WantTiming)
6216896c45SDouglas Gregor         Start = TimeRecord::getCurrentTime();
6316896c45SDouglas Gregor     }
6416896c45SDouglas Gregor 
650e62c1ccSChris Lattner     void setOutput(const Twine &Output) {
6616896c45SDouglas Gregor       if (WantTiming)
6716896c45SDouglas Gregor         this->Output = Output.str();
6816896c45SDouglas Gregor     }
6916896c45SDouglas Gregor 
7016896c45SDouglas Gregor     ~SimpleTimer() {
7116896c45SDouglas Gregor       if (WantTiming) {
7216896c45SDouglas Gregor         TimeRecord Elapsed = TimeRecord::getCurrentTime();
7316896c45SDouglas Gregor         Elapsed -= Start;
7416896c45SDouglas Gregor         llvm::errs() << Output << ':';
7516896c45SDouglas Gregor         Elapsed.print(Elapsed, llvm::errs());
7616896c45SDouglas Gregor         llvm::errs() << '\n';
7716896c45SDouglas Gregor       }
7816896c45SDouglas Gregor     }
7916896c45SDouglas Gregor   };
8006b4f919STed Kremenek 
8106b4f919STed Kremenek   struct OnDiskData {
8206b4f919STed Kremenek     /// \brief The file in which the precompiled preamble is stored.
8306b4f919STed Kremenek     std::string PreambleFile;
8406b4f919STed Kremenek 
8506b4f919STed Kremenek     /// \brief Temporary files that should be removed when the ASTUnit is
8606b4f919STed Kremenek     /// destroyed.
8706b4f919STed Kremenek     SmallVector<llvm::sys::Path, 4> TemporaryFiles;
8806b4f919STed Kremenek 
8906b4f919STed Kremenek     /// \brief Erase temporary files.
9006b4f919STed Kremenek     void CleanTemporaryFiles();
9106b4f919STed Kremenek 
9206b4f919STed Kremenek     /// \brief Erase the preamble file.
9306b4f919STed Kremenek     void CleanPreambleFile();
9406b4f919STed Kremenek 
9506b4f919STed Kremenek     /// \brief Erase temporary files and the preamble file.
9606b4f919STed Kremenek     void Cleanup();
9706b4f919STed Kremenek   };
9806b4f919STed Kremenek }
9906b4f919STed Kremenek 
100bd307a53STed Kremenek static llvm::sys::SmartMutex<false> &getOnDiskMutex() {
101bd307a53STed Kremenek   static llvm::sys::SmartMutex<false> M(/* recursive = */ true);
102bd307a53STed Kremenek   return M;
103bd307a53STed Kremenek }
104bd307a53STed Kremenek 
10506b4f919STed Kremenek static void cleanupOnDiskMapAtExit(void);
10606b4f919STed Kremenek 
10706b4f919STed Kremenek typedef llvm::DenseMap<const ASTUnit *, OnDiskData *> OnDiskDataMap;
10806b4f919STed Kremenek static OnDiskDataMap &getOnDiskDataMap() {
10906b4f919STed Kremenek   static OnDiskDataMap M;
11006b4f919STed Kremenek   static bool hasRegisteredAtExit = false;
11106b4f919STed Kremenek   if (!hasRegisteredAtExit) {
11206b4f919STed Kremenek     hasRegisteredAtExit = true;
11306b4f919STed Kremenek     atexit(cleanupOnDiskMapAtExit);
11406b4f919STed Kremenek   }
11506b4f919STed Kremenek   return M;
11606b4f919STed Kremenek }
11706b4f919STed Kremenek 
11806b4f919STed Kremenek static void cleanupOnDiskMapAtExit(void) {
1194cf2ffe2SArgyrios Kyrtzidis   // Use the mutex because there can be an alive thread destroying an ASTUnit.
1204cf2ffe2SArgyrios Kyrtzidis   llvm::MutexGuard Guard(getOnDiskMutex());
12106b4f919STed Kremenek   OnDiskDataMap &M = getOnDiskDataMap();
12206b4f919STed Kremenek   for (OnDiskDataMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
12306b4f919STed Kremenek     // We don't worry about freeing the memory associated with OnDiskDataMap.
12406b4f919STed Kremenek     // All we care about is erasing stale files.
12506b4f919STed Kremenek     I->second->Cleanup();
12606b4f919STed Kremenek   }
12706b4f919STed Kremenek }
12806b4f919STed Kremenek 
12906b4f919STed Kremenek static OnDiskData &getOnDiskData(const ASTUnit *AU) {
130bd307a53STed Kremenek   // We require the mutex since we are modifying the structure of the
131bd307a53STed Kremenek   // DenseMap.
132bd307a53STed Kremenek   llvm::MutexGuard Guard(getOnDiskMutex());
13306b4f919STed Kremenek   OnDiskDataMap &M = getOnDiskDataMap();
13406b4f919STed Kremenek   OnDiskData *&D = M[AU];
13506b4f919STed Kremenek   if (!D)
13606b4f919STed Kremenek     D = new OnDiskData();
13706b4f919STed Kremenek   return *D;
13806b4f919STed Kremenek }
13906b4f919STed Kremenek 
14006b4f919STed Kremenek static void erasePreambleFile(const ASTUnit *AU) {
14106b4f919STed Kremenek   getOnDiskData(AU).CleanPreambleFile();
14206b4f919STed Kremenek }
14306b4f919STed Kremenek 
14406b4f919STed Kremenek static void removeOnDiskEntry(const ASTUnit *AU) {
145bd307a53STed Kremenek   // We require the mutex since we are modifying the structure of the
146bd307a53STed Kremenek   // DenseMap.
147bd307a53STed Kremenek   llvm::MutexGuard Guard(getOnDiskMutex());
14806b4f919STed Kremenek   OnDiskDataMap &M = getOnDiskDataMap();
14906b4f919STed Kremenek   OnDiskDataMap::iterator I = M.find(AU);
15006b4f919STed Kremenek   if (I != M.end()) {
15106b4f919STed Kremenek     I->second->Cleanup();
15206b4f919STed Kremenek     delete I->second;
15306b4f919STed Kremenek     M.erase(AU);
15406b4f919STed Kremenek   }
15506b4f919STed Kremenek }
15606b4f919STed Kremenek 
15706b4f919STed Kremenek static void setPreambleFile(const ASTUnit *AU, llvm::StringRef preambleFile) {
15806b4f919STed Kremenek   getOnDiskData(AU).PreambleFile = preambleFile;
15906b4f919STed Kremenek }
16006b4f919STed Kremenek 
16106b4f919STed Kremenek static const std::string &getPreambleFile(const ASTUnit *AU) {
16206b4f919STed Kremenek   return getOnDiskData(AU).PreambleFile;
16306b4f919STed Kremenek }
16406b4f919STed Kremenek 
16506b4f919STed Kremenek void OnDiskData::CleanTemporaryFiles() {
16606b4f919STed Kremenek   for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
16706b4f919STed Kremenek     TemporaryFiles[I].eraseFromDisk();
16806b4f919STed Kremenek   TemporaryFiles.clear();
16906b4f919STed Kremenek }
17006b4f919STed Kremenek 
17106b4f919STed Kremenek void OnDiskData::CleanPreambleFile() {
17206b4f919STed Kremenek   if (!PreambleFile.empty()) {
17306b4f919STed Kremenek     llvm::sys::Path(PreambleFile).eraseFromDisk();
17406b4f919STed Kremenek     PreambleFile.clear();
17506b4f919STed Kremenek   }
17606b4f919STed Kremenek }
17706b4f919STed Kremenek 
17806b4f919STed Kremenek void OnDiskData::Cleanup() {
17906b4f919STed Kremenek   CleanTemporaryFiles();
18006b4f919STed Kremenek   CleanPreambleFile();
18106b4f919STed Kremenek }
18206b4f919STed Kremenek 
183e54568d6SArgyrios Kyrtzidis void ASTUnit::clearFileLevelDecls() {
184e54568d6SArgyrios Kyrtzidis   for (FileDeclsTy::iterator
185e54568d6SArgyrios Kyrtzidis          I = FileDecls.begin(), E = FileDecls.end(); I != E; ++I)
186e54568d6SArgyrios Kyrtzidis     delete I->second;
187e54568d6SArgyrios Kyrtzidis   FileDecls.clear();
188e54568d6SArgyrios Kyrtzidis }
189e54568d6SArgyrios Kyrtzidis 
19006b4f919STed Kremenek void ASTUnit::CleanTemporaryFiles() {
19106b4f919STed Kremenek   getOnDiskData(this).CleanTemporaryFiles();
19206b4f919STed Kremenek }
19306b4f919STed Kremenek 
19406b4f919STed Kremenek void ASTUnit::addTemporaryFile(const llvm::sys::Path &TempFile) {
19506b4f919STed Kremenek   getOnDiskData(this).TemporaryFiles.push_back(TempFile);
19616896c45SDouglas Gregor }
19716896c45SDouglas Gregor 
198bb420abdSDouglas Gregor /// \brief After failing to build a precompiled preamble (due to
199bb420abdSDouglas Gregor /// errors in the source that occurs in the preamble), the number of
200bb420abdSDouglas Gregor /// reparses during which we'll skip even trying to precompile the
201bb420abdSDouglas Gregor /// preamble.
202bb420abdSDouglas Gregor const unsigned DefaultPreambleRebuildInterval = 5;
203bb420abdSDouglas Gregor 
20468dbaeadSDouglas Gregor /// \brief Tracks the number of ASTUnit objects that are currently active.
20568dbaeadSDouglas Gregor ///
20668dbaeadSDouglas Gregor /// Used for debugging purposes only.
2079aeaa4d6SDouglas Gregor static llvm::sys::cas_flag ActiveASTUnitObjects;
20868dbaeadSDouglas Gregor 
209d03e823fSDouglas Gregor ASTUnit::ASTUnit(bool _MainFileIsAST)
210244ce8b2SArgyrios Kyrtzidis   : Reader(0), OnlyLocalDecls(false), CaptureDiagnostics(false),
21135dcda79SArgyrios Kyrtzidis     MainFileIsAST(_MainFileIsAST),
21269f74f80SDouglas Gregor     TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
2134954bc1dSArgyrios Kyrtzidis     OwnsRemappedFileBuffers(true),
21416896c45SDouglas Gregor     NumStoredDiagnosticsFromDriver(0),
215a0734c5fSDouglas Gregor     PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
21685b4a37dSArgyrios Kyrtzidis     NumWarningsInPreamble(0),
2172c8bd47aSDouglas Gregor     ShouldCacheCodeCompletionResults(false),
2186d7833f1SArgyrios Kyrtzidis     IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
219df7a79a9SDouglas Gregor     CompletionCacheTopLevelHashValue(0),
220df7a79a9SDouglas Gregor     PreambleTopLevelHashValue(0),
221df7a79a9SDouglas Gregor     CurrentTopLevelHashValue(0),
2224740c450SDouglas Gregor     UnsafeToFree(false) {
22368dbaeadSDouglas Gregor   if (getenv("LIBCLANG_OBJTRACKING")) {
2249aeaa4d6SDouglas Gregor     llvm::sys::AtomicIncrement(&ActiveASTUnitObjects);
22568dbaeadSDouglas Gregor     fprintf(stderr, "+++ %d translation units\n", ActiveASTUnitObjects);
22668dbaeadSDouglas Gregor   }
22715ba0b34SDouglas Gregor }
228d03e823fSDouglas Gregor 
22944cd60eeSSteve Naroff ASTUnit::~ASTUnit() {
230e54568d6SArgyrios Kyrtzidis   clearFileLevelDecls();
231e54568d6SArgyrios Kyrtzidis 
23206b4f919STed Kremenek   // Clean up the temporary files and the preamble file.
23306b4f919STed Kremenek   removeOnDiskEntry(this);
2343f4bea06SDouglas Gregor 
2353f4bea06SDouglas Gregor   // Free the buffers associated with remapped files. We are required to
2363f4bea06SDouglas Gregor   // perform this operation here because we explicitly request that the
2373f4bea06SDouglas Gregor   // compiler instance *not* free these buffers for each invocation of the
2383f4bea06SDouglas Gregor   // parser.
2395e14d39aSTed Kremenek   if (Invocation.getPtr() && OwnsRemappedFileBuffers) {
2403f4bea06SDouglas Gregor     PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
2413f4bea06SDouglas Gregor     for (PreprocessorOptions::remapped_file_buffer_iterator
2423f4bea06SDouglas Gregor            FB = PPOpts.remapped_file_buffer_begin(),
2433f4bea06SDouglas Gregor            FBEnd = PPOpts.remapped_file_buffer_end();
2443f4bea06SDouglas Gregor          FB != FBEnd;
2453f4bea06SDouglas Gregor          ++FB)
2463f4bea06SDouglas Gregor       delete FB->second;
2473f4bea06SDouglas Gregor   }
24896c04261SDouglas Gregor 
24996c04261SDouglas Gregor   delete SavedMainFileBuffer;
250a0734c5fSDouglas Gregor   delete PreambleBuffer;
25115ba0b34SDouglas Gregor 
252b14904c4SDouglas Gregor   ClearCachedCompletionResults();
25368dbaeadSDouglas Gregor 
25468dbaeadSDouglas Gregor   if (getenv("LIBCLANG_OBJTRACKING")) {
2559aeaa4d6SDouglas Gregor     llvm::sys::AtomicDecrement(&ActiveASTUnitObjects);
25668dbaeadSDouglas Gregor     fprintf(stderr, "--- %d translation units\n", ActiveASTUnitObjects);
25768dbaeadSDouglas Gregor   }
258aa21cc40SDouglas Gregor }
259aa21cc40SDouglas Gregor 
260da6e0547SArgyrios Kyrtzidis void ASTUnit::setPreprocessor(Preprocessor *pp) { PP = pp; }
261da6e0547SArgyrios Kyrtzidis 
26239982197SDouglas Gregor /// \brief Determine the set of code-completion contexts in which this
26339982197SDouglas Gregor /// declaration should be shown.
26439982197SDouglas Gregor static unsigned getDeclShowContexts(NamedDecl *ND,
26559cab556SDouglas Gregor                                     const LangOptions &LangOpts,
26659cab556SDouglas Gregor                                     bool &IsNestedNameSpecifier) {
26759cab556SDouglas Gregor   IsNestedNameSpecifier = false;
26859cab556SDouglas Gregor 
26939982197SDouglas Gregor   if (isa<UsingShadowDecl>(ND))
27039982197SDouglas Gregor     ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
27139982197SDouglas Gregor   if (!ND)
27239982197SDouglas Gregor     return 0;
27339982197SDouglas Gregor 
274697cc9e6SRichard Smith   uint64_t Contexts = 0;
27539982197SDouglas Gregor   if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
27639982197SDouglas Gregor       isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
27739982197SDouglas Gregor     // Types can appear in these contexts.
27839982197SDouglas Gregor     if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
279697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
280697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_ObjCIvarList)
281697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_ClassStructUnion)
282697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_Statement)
283697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_Type)
284697cc9e6SRichard Smith                |  (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
28539982197SDouglas Gregor 
28639982197SDouglas Gregor     // In C++, types can appear in expressions contexts (for functional casts).
28739982197SDouglas Gregor     if (LangOpts.CPlusPlus)
288697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
28939982197SDouglas Gregor 
29039982197SDouglas Gregor     // In Objective-C, message sends can send interfaces. In Objective-C++,
29139982197SDouglas Gregor     // all types are available due to functional casts.
29239982197SDouglas Gregor     if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
293697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
29439982197SDouglas Gregor 
2952132584dSDouglas Gregor     // In Objective-C, you can only be a subclass of another Objective-C class
2962132584dSDouglas Gregor     if (isa<ObjCInterfaceDecl>(ND))
297697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
2982132584dSDouglas Gregor 
29939982197SDouglas Gregor     // Deal with tag names.
30039982197SDouglas Gregor     if (isa<EnumDecl>(ND)) {
301697cc9e6SRichard Smith       Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);
30239982197SDouglas Gregor 
30359cab556SDouglas Gregor       // Part of the nested-name-specifier in C++0x.
30439982197SDouglas Gregor       if (LangOpts.CPlusPlus0x)
30559cab556SDouglas Gregor         IsNestedNameSpecifier = true;
30639982197SDouglas Gregor     } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
30739982197SDouglas Gregor       if (Record->isUnion())
308697cc9e6SRichard Smith         Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
30939982197SDouglas Gregor       else
310697cc9e6SRichard Smith         Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
31139982197SDouglas Gregor 
31239982197SDouglas Gregor       if (LangOpts.CPlusPlus)
31359cab556SDouglas Gregor         IsNestedNameSpecifier = true;
3140ac41389SDouglas Gregor     } else if (isa<ClassTemplateDecl>(ND))
31559cab556SDouglas Gregor       IsNestedNameSpecifier = true;
31639982197SDouglas Gregor   } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
31739982197SDouglas Gregor     // Values can appear in these contexts.
318697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_Statement)
319697cc9e6SRichard Smith              | (1LL << CodeCompletionContext::CCC_Expression)
320697cc9e6SRichard Smith              | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
321697cc9e6SRichard Smith              | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
32239982197SDouglas Gregor   } else if (isa<ObjCProtocolDecl>(ND)) {
323697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);
3242132584dSDouglas Gregor   } else if (isa<ObjCCategoryDecl>(ND)) {
325697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);
32639982197SDouglas Gregor   } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
327697cc9e6SRichard Smith     Contexts = (1LL << CodeCompletionContext::CCC_Namespace);
32839982197SDouglas Gregor 
32939982197SDouglas Gregor     // Part of the nested-name-specifier.
33059cab556SDouglas Gregor     IsNestedNameSpecifier = true;
33139982197SDouglas Gregor   }
33239982197SDouglas Gregor 
33339982197SDouglas Gregor   return Contexts;
33439982197SDouglas Gregor }
33539982197SDouglas Gregor 
336b14904c4SDouglas Gregor void ASTUnit::CacheCodeCompletionResults() {
337b14904c4SDouglas Gregor   if (!TheSema)
338b14904c4SDouglas Gregor     return;
339b14904c4SDouglas Gregor 
34016896c45SDouglas Gregor   SimpleTimer Timer(WantTiming);
34116896c45SDouglas Gregor   Timer.setOutput("Cache global code completions for " + getMainFileName());
342b14904c4SDouglas Gregor 
343b14904c4SDouglas Gregor   // Clear out the previous results.
344b14904c4SDouglas Gregor   ClearCachedCompletionResults();
345b14904c4SDouglas Gregor 
346b14904c4SDouglas Gregor   // Gather the set of global code completions.
347276321a9SJohn McCall   typedef CodeCompletionResult Result;
3480e62c1ccSChris Lattner   SmallVector<Result, 8> Results;
349162b712dSDouglas Gregor   CachedCompletionAllocator = new GlobalCodeCompletionAllocator;
3509d7c0fefSArgyrios Kyrtzidis   TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator,
3519d7c0fefSArgyrios Kyrtzidis                                        getCodeCompletionTUInfo(), Results);
352b14904c4SDouglas Gregor 
353b14904c4SDouglas Gregor   // Translate global code completions into cached completions.
354b61c07acSDouglas Gregor   llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
355b61c07acSDouglas Gregor 
356b14904c4SDouglas Gregor   for (unsigned I = 0, N = Results.size(); I != N; ++I) {
357b14904c4SDouglas Gregor     switch (Results[I].Kind) {
35839982197SDouglas Gregor     case Result::RK_Declaration: {
35959cab556SDouglas Gregor       bool IsNestedNameSpecifier = false;
36039982197SDouglas Gregor       CachedCodeCompletionResult CachedResult;
361b278aafbSDouglas Gregor       CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
3629d7c0fefSArgyrios Kyrtzidis                                                     *CachedCompletionAllocator,
3633292d06aSDmitri Gribenko                                                     getCodeCompletionTUInfo(),
3643292d06aSDmitri Gribenko                                           IncludeBriefCommentsInCodeCompletion);
36539982197SDouglas Gregor       CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
366bbafb8a7SDavid Blaikie                                                         Ctx->getLangOpts(),
36759cab556SDouglas Gregor                                                         IsNestedNameSpecifier);
36839982197SDouglas Gregor       CachedResult.Priority = Results[I].Priority;
36939982197SDouglas Gregor       CachedResult.Kind = Results[I].CursorKind;
370f757a12dSDouglas Gregor       CachedResult.Availability = Results[I].Availability;
37124747408SDouglas Gregor 
372b61c07acSDouglas Gregor       // Keep track of the type of this completion in an ASTContext-agnostic
373b61c07acSDouglas Gregor       // way.
37424747408SDouglas Gregor       QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
375b61c07acSDouglas Gregor       if (UsageType.isNull()) {
37624747408SDouglas Gregor         CachedResult.TypeClass = STC_Void;
377b61c07acSDouglas Gregor         CachedResult.Type = 0;
378b61c07acSDouglas Gregor       } else {
379b61c07acSDouglas Gregor         CanQualType CanUsageType
380b61c07acSDouglas Gregor           = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
381b61c07acSDouglas Gregor         CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
382b61c07acSDouglas Gregor 
383b61c07acSDouglas Gregor         // Determine whether we have already seen this type. If so, we save
384b61c07acSDouglas Gregor         // ourselves the work of formatting the type string by using the
385b61c07acSDouglas Gregor         // temporary, CanQualType-based hash table to find the associated value.
386b61c07acSDouglas Gregor         unsigned &TypeValue = CompletionTypes[CanUsageType];
387b61c07acSDouglas Gregor         if (TypeValue == 0) {
388b61c07acSDouglas Gregor           TypeValue = CompletionTypes.size();
389b61c07acSDouglas Gregor           CachedCompletionTypes[QualType(CanUsageType).getAsString()]
390b61c07acSDouglas Gregor             = TypeValue;
39124747408SDouglas Gregor         }
392b61c07acSDouglas Gregor 
393b61c07acSDouglas Gregor         CachedResult.Type = TypeValue;
394b61c07acSDouglas Gregor       }
395b61c07acSDouglas Gregor 
39639982197SDouglas Gregor       CachedCompletionResults.push_back(CachedResult);
39759cab556SDouglas Gregor 
39859cab556SDouglas Gregor       /// Handle nested-name-specifiers in C++.
399bbafb8a7SDavid Blaikie       if (TheSema->Context.getLangOpts().CPlusPlus &&
40059cab556SDouglas Gregor           IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
40159cab556SDouglas Gregor         // The contexts in which a nested-name-specifier can appear in C++.
402697cc9e6SRichard Smith         uint64_t NNSContexts
403697cc9e6SRichard Smith           = (1LL << CodeCompletionContext::CCC_TopLevel)
404697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
405697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
406697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_Statement)
407697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_Expression)
408697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
409697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_EnumTag)
410697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_UnionTag)
411697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ClassOrStructTag)
412697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_Type)
413697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_PotentiallyQualifiedName)
414697cc9e6SRichard Smith           | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
41559cab556SDouglas Gregor 
41659cab556SDouglas Gregor         if (isa<NamespaceDecl>(Results[I].Declaration) ||
41759cab556SDouglas Gregor             isa<NamespaceAliasDecl>(Results[I].Declaration))
418697cc9e6SRichard Smith           NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
41959cab556SDouglas Gregor 
42059cab556SDouglas Gregor         if (unsigned RemainingContexts
42159cab556SDouglas Gregor                                 = NNSContexts & ~CachedResult.ShowInContexts) {
42259cab556SDouglas Gregor           // If there any contexts where this completion can be a
42359cab556SDouglas Gregor           // nested-name-specifier but isn't already an option, create a
42459cab556SDouglas Gregor           // nested-name-specifier completion.
42559cab556SDouglas Gregor           Results[I].StartsNestedNameSpecifier = true;
426b278aafbSDouglas Gregor           CachedResult.Completion
427b278aafbSDouglas Gregor             = Results[I].CreateCodeCompletionString(*TheSema,
4289d7c0fefSArgyrios Kyrtzidis                                                     *CachedCompletionAllocator,
4293292d06aSDmitri Gribenko                                                     getCodeCompletionTUInfo(),
4303292d06aSDmitri Gribenko                                         IncludeBriefCommentsInCodeCompletion);
43159cab556SDouglas Gregor           CachedResult.ShowInContexts = RemainingContexts;
43259cab556SDouglas Gregor           CachedResult.Priority = CCP_NestedNameSpecifier;
43359cab556SDouglas Gregor           CachedResult.TypeClass = STC_Void;
43459cab556SDouglas Gregor           CachedResult.Type = 0;
43559cab556SDouglas Gregor           CachedCompletionResults.push_back(CachedResult);
43659cab556SDouglas Gregor         }
43759cab556SDouglas Gregor       }
438b14904c4SDouglas Gregor       break;
43939982197SDouglas Gregor     }
440b14904c4SDouglas Gregor 
441b14904c4SDouglas Gregor     case Result::RK_Keyword:
442b14904c4SDouglas Gregor     case Result::RK_Pattern:
443b14904c4SDouglas Gregor       // Ignore keywords and patterns; we don't care, since they are so
444b14904c4SDouglas Gregor       // easily regenerated.
445b14904c4SDouglas Gregor       break;
446b14904c4SDouglas Gregor 
447b14904c4SDouglas Gregor     case Result::RK_Macro: {
448b14904c4SDouglas Gregor       CachedCodeCompletionResult CachedResult;
449b278aafbSDouglas Gregor       CachedResult.Completion
450b278aafbSDouglas Gregor         = Results[I].CreateCodeCompletionString(*TheSema,
4519d7c0fefSArgyrios Kyrtzidis                                                 *CachedCompletionAllocator,
4523292d06aSDmitri Gribenko                                                 getCodeCompletionTUInfo(),
4533292d06aSDmitri Gribenko                                           IncludeBriefCommentsInCodeCompletion);
454b14904c4SDouglas Gregor       CachedResult.ShowInContexts
455697cc9e6SRichard Smith         = (1LL << CodeCompletionContext::CCC_TopLevel)
456697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCInterface)
457697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
458697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
459697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
460697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Statement)
461697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Expression)
462697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
463697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_MacroNameUse)
464697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_PreprocessorExpression)
465697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
466697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_OtherWithMacros);
467c49f5b2fSDouglas Gregor 
468b14904c4SDouglas Gregor       CachedResult.Priority = Results[I].Priority;
469b14904c4SDouglas Gregor       CachedResult.Kind = Results[I].CursorKind;
470f757a12dSDouglas Gregor       CachedResult.Availability = Results[I].Availability;
4716e24033bSDouglas Gregor       CachedResult.TypeClass = STC_Void;
472b61c07acSDouglas Gregor       CachedResult.Type = 0;
473b14904c4SDouglas Gregor       CachedCompletionResults.push_back(CachedResult);
474b14904c4SDouglas Gregor       break;
475b14904c4SDouglas Gregor     }
476b14904c4SDouglas Gregor     }
477b14904c4SDouglas Gregor   }
478b14904c4SDouglas Gregor 
479df7a79a9SDouglas Gregor   // Save the current top-level hash value.
480df7a79a9SDouglas Gregor   CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
481b14904c4SDouglas Gregor }
482b14904c4SDouglas Gregor 
483b14904c4SDouglas Gregor void ASTUnit::ClearCachedCompletionResults() {
484b14904c4SDouglas Gregor   CachedCompletionResults.clear();
485b61c07acSDouglas Gregor   CachedCompletionTypes.clear();
486162b712dSDouglas Gregor   CachedCompletionAllocator = 0;
487b14904c4SDouglas Gregor }
488b14904c4SDouglas Gregor 
489ce379752SArgyrios Kyrtzidis namespace {
490ce379752SArgyrios Kyrtzidis 
4912c499f65SSebastian Redl /// \brief Gathers information from ASTReader that will be used to initialize
492ce379752SArgyrios Kyrtzidis /// a Preprocessor.
493d44cd6adSSebastian Redl class ASTInfoCollector : public ASTReaderListener {
49483297dfcSDouglas Gregor   Preprocessor &PP;
495e8bbc121SDouglas Gregor   ASTContext &Context;
496ce379752SArgyrios Kyrtzidis   LangOptions &LangOpt;
497ce379752SArgyrios Kyrtzidis   HeaderSearch &HSI;
498c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<TargetInfo> &Target;
499ce379752SArgyrios Kyrtzidis   std::string &Predefines;
500ce379752SArgyrios Kyrtzidis   unsigned &Counter;
501ce379752SArgyrios Kyrtzidis 
502ce379752SArgyrios Kyrtzidis   unsigned NumHeaderInfos;
503ce379752SArgyrios Kyrtzidis 
504e8bbc121SDouglas Gregor   bool InitializedLanguage;
505ce379752SArgyrios Kyrtzidis public:
506e8bbc121SDouglas Gregor   ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
507e8bbc121SDouglas Gregor                    HeaderSearch &HSI,
508c95d8192SDylan Noblesmith                    IntrusiveRefCntPtr<TargetInfo> &Target,
50983297dfcSDouglas Gregor                    std::string &Predefines,
510ce379752SArgyrios Kyrtzidis                    unsigned &Counter)
511e8bbc121SDouglas Gregor     : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target),
51283297dfcSDouglas Gregor       Predefines(Predefines), Counter(Counter), NumHeaderInfos(0),
513e8bbc121SDouglas Gregor       InitializedLanguage(false) {}
514ce379752SArgyrios Kyrtzidis 
515ce379752SArgyrios Kyrtzidis   virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
516e8bbc121SDouglas Gregor     if (InitializedLanguage)
51783297dfcSDouglas Gregor       return false;
51883297dfcSDouglas Gregor 
519ce379752SArgyrios Kyrtzidis     LangOpt = LangOpts;
52083297dfcSDouglas Gregor 
52183297dfcSDouglas Gregor     // Initialize the preprocessor.
52283297dfcSDouglas Gregor     PP.Initialize(*Target);
523e8bbc121SDouglas Gregor 
524e8bbc121SDouglas Gregor     // Initialize the ASTContext
525e8bbc121SDouglas Gregor     Context.InitBuiltinTypes(*Target);
526e8bbc121SDouglas Gregor 
527e8bbc121SDouglas Gregor     InitializedLanguage = true;
5289e1fb563SArgyrios Kyrtzidis 
5299e1fb563SArgyrios Kyrtzidis     applyLangOptsToTarget();
530ce379752SArgyrios Kyrtzidis     return false;
531ce379752SArgyrios Kyrtzidis   }
532ce379752SArgyrios Kyrtzidis 
5330e62c1ccSChris Lattner   virtual bool ReadTargetTriple(StringRef Triple) {
53483297dfcSDouglas Gregor     // If we've already initialized the target, don't do it again.
53583297dfcSDouglas Gregor     if (Target)
53683297dfcSDouglas Gregor       return false;
53783297dfcSDouglas Gregor 
53883297dfcSDouglas Gregor     // FIXME: This is broken, we should store the TargetOptions in the AST file.
53983297dfcSDouglas Gregor     TargetOptions TargetOpts;
54083297dfcSDouglas Gregor     TargetOpts.ABI = "";
54183297dfcSDouglas Gregor     TargetOpts.CXXABI = "";
54283297dfcSDouglas Gregor     TargetOpts.CPU = "";
54383297dfcSDouglas Gregor     TargetOpts.Features.clear();
54483297dfcSDouglas Gregor     TargetOpts.Triple = Triple;
54583297dfcSDouglas Gregor     Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
5469e1fb563SArgyrios Kyrtzidis 
5479e1fb563SArgyrios Kyrtzidis     applyLangOptsToTarget();
548ce379752SArgyrios Kyrtzidis     return false;
549ce379752SArgyrios Kyrtzidis   }
550ce379752SArgyrios Kyrtzidis 
5518b41f300SSebastian Redl   virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
5520e62c1ccSChris Lattner                                     StringRef OriginalFileName,
55336079898SNick Lewycky                                     std::string &SuggestedPredefines,
55436079898SNick Lewycky                                     FileManager &FileMgr) {
5558b41f300SSebastian Redl     Predefines = Buffers[0].Data;
5568b41f300SSebastian Redl     for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
5578b41f300SSebastian Redl       Predefines += Buffers[I].Data;
5588b41f300SSebastian Redl     }
559ce379752SArgyrios Kyrtzidis     return false;
560ce379752SArgyrios Kyrtzidis   }
561ce379752SArgyrios Kyrtzidis 
562a2f49450SDouglas Gregor   virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
563ce379752SArgyrios Kyrtzidis     HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
564ce379752SArgyrios Kyrtzidis   }
565ce379752SArgyrios Kyrtzidis 
566ce379752SArgyrios Kyrtzidis   virtual void ReadCounter(unsigned Value) {
567ce379752SArgyrios Kyrtzidis     Counter = Value;
568ce379752SArgyrios Kyrtzidis   }
5699e1fb563SArgyrios Kyrtzidis 
5709e1fb563SArgyrios Kyrtzidis private:
5719e1fb563SArgyrios Kyrtzidis   void applyLangOptsToTarget() {
5729e1fb563SArgyrios Kyrtzidis     if (Target && InitializedLanguage) {
5739e1fb563SArgyrios Kyrtzidis       // Inform the target of the language options.
5749e1fb563SArgyrios Kyrtzidis       //
5759e1fb563SArgyrios Kyrtzidis       // FIXME: We shouldn't need to do this, the target should be immutable once
5769e1fb563SArgyrios Kyrtzidis       // created. This complexity should be lifted elsewhere.
5779e1fb563SArgyrios Kyrtzidis       Target->setForcedLangOptions(LangOpt);
5789e1fb563SArgyrios Kyrtzidis     }
5799e1fb563SArgyrios Kyrtzidis   }
580ce379752SArgyrios Kyrtzidis };
581ce379752SArgyrios Kyrtzidis 
582f18d91a4SDavid Blaikie class StoredDiagnosticConsumer : public DiagnosticConsumer {
5830e62c1ccSChris Lattner   SmallVectorImpl<StoredDiagnostic> &StoredDiags;
58433cdd810SDouglas Gregor 
58533cdd810SDouglas Gregor public:
586f18d91a4SDavid Blaikie   explicit StoredDiagnosticConsumer(
5870e62c1ccSChris Lattner                           SmallVectorImpl<StoredDiagnostic> &StoredDiags)
58833cdd810SDouglas Gregor     : StoredDiags(StoredDiags) { }
58933cdd810SDouglas Gregor 
5909c902b55SDavid Blaikie   virtual void HandleDiagnostic(DiagnosticsEngine::Level Level,
591b5784324SDavid Blaikie                                 const Diagnostic &Info);
592d0e9e3a6SDouglas Gregor 
593d0e9e3a6SDouglas Gregor   DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
594d0e9e3a6SDouglas Gregor     // Just drop any diagnostics that come from cloned consumers; they'll
595d0e9e3a6SDouglas Gregor     // have different source managers anyway.
596e1fbde55SDouglas Gregor     // FIXME: We'd like to be able to capture these somehow, even if it's just
597e1fbde55SDouglas Gregor     // file/line/column, because they could occur when parsing module maps or
598e1fbde55SDouglas Gregor     // building modules on-demand.
599d0e9e3a6SDouglas Gregor     return new IgnoringDiagConsumer();
600d0e9e3a6SDouglas Gregor   }
60133cdd810SDouglas Gregor };
60233cdd810SDouglas Gregor 
60333cdd810SDouglas Gregor /// \brief RAII object that optionally captures diagnostics, if
60433cdd810SDouglas Gregor /// there is no diagnostic client to capture them already.
60533cdd810SDouglas Gregor class CaptureDroppedDiagnostics {
6069c902b55SDavid Blaikie   DiagnosticsEngine &Diags;
607f18d91a4SDavid Blaikie   StoredDiagnosticConsumer Client;
608e2eefaecSDavid Blaikie   DiagnosticConsumer *PreviousClient;
60933cdd810SDouglas Gregor 
61033cdd810SDouglas Gregor public:
6119c902b55SDavid Blaikie   CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags,
6120e62c1ccSChris Lattner                           SmallVectorImpl<StoredDiagnostic> &StoredDiags)
6132dd19f1dSDouglas Gregor     : Diags(Diags), Client(StoredDiags), PreviousClient(0)
61433cdd810SDouglas Gregor   {
6152dd19f1dSDouglas Gregor     if (RequestCapture || Diags.getClient() == 0) {
6162dd19f1dSDouglas Gregor       PreviousClient = Diags.takeClient();
61733cdd810SDouglas Gregor       Diags.setClient(&Client);
61833cdd810SDouglas Gregor     }
6192dd19f1dSDouglas Gregor   }
62033cdd810SDouglas Gregor 
62133cdd810SDouglas Gregor   ~CaptureDroppedDiagnostics() {
6222dd19f1dSDouglas Gregor     if (Diags.getClient() == &Client) {
6232dd19f1dSDouglas Gregor       Diags.takeClient();
62433cdd810SDouglas Gregor       Diags.setClient(PreviousClient);
62533cdd810SDouglas Gregor     }
6262dd19f1dSDouglas Gregor   }
62733cdd810SDouglas Gregor };
62833cdd810SDouglas Gregor 
629ce379752SArgyrios Kyrtzidis } // anonymous namespace
630ce379752SArgyrios Kyrtzidis 
631f18d91a4SDavid Blaikie void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
632b5784324SDavid Blaikie                                               const Diagnostic &Info) {
633c79346a5SArgyrios Kyrtzidis   // Default implementation (Warnings/errors count).
634e2eefaecSDavid Blaikie   DiagnosticConsumer::HandleDiagnostic(Level, Info);
635c79346a5SArgyrios Kyrtzidis 
63633cdd810SDouglas Gregor   StoredDiags.push_back(StoredDiagnostic(Level, Info));
63733cdd810SDouglas Gregor }
63833cdd810SDouglas Gregor 
639c0683b90SSteve Naroff const std::string &ASTUnit::getOriginalSourceFileName() {
640a8a50937SDaniel Dunbar   return OriginalSourceFile;
641c0683b90SSteve Naroff }
642ce379752SArgyrios Kyrtzidis 
6430e62c1ccSChris Lattner llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename,
64426b5c190SChris Lattner                                               std::string *ErrorStr) {
6455159f616SChris Lattner   assert(FileMgr);
64626b5c190SChris Lattner   return FileMgr->getBufferForFile(Filename, ErrorStr);
64771731d6bSArgyrios Kyrtzidis }
64871731d6bSArgyrios Kyrtzidis 
64944c6ee77SDouglas Gregor /// \brief Configure the diagnostics object for use with ASTUnit.
650c95d8192SDylan Noblesmith void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
651345c1bcbSDouglas Gregor                              const char **ArgBegin, const char **ArgEnd,
65244c6ee77SDouglas Gregor                              ASTUnit &AST, bool CaptureDiagnostics) {
65344c6ee77SDouglas Gregor   if (!Diags.getPtr()) {
65444c6ee77SDouglas Gregor     // No diagnostics engine was provided, so create our own diagnostics object
65544c6ee77SDouglas Gregor     // with the default options.
65644c6ee77SDouglas Gregor     DiagnosticOptions DiagOpts;
657e2eefaecSDavid Blaikie     DiagnosticConsumer *Client = 0;
65844c6ee77SDouglas Gregor     if (CaptureDiagnostics)
659f18d91a4SDavid Blaikie       Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
660345c1bcbSDouglas Gregor     Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd-ArgBegin,
661ffe7c7f4SBenjamin Kramer                                                 ArgBegin, Client,
662ffe7c7f4SBenjamin Kramer                                                 /*ShouldOwnClient=*/true,
663ffe7c7f4SBenjamin Kramer                                                 /*ShouldCloneClient=*/false);
66444c6ee77SDouglas Gregor   } else if (CaptureDiagnostics) {
665f18d91a4SDavid Blaikie     Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics));
66644c6ee77SDouglas Gregor   }
66744c6ee77SDouglas Gregor }
66844c6ee77SDouglas Gregor 
669d44cd6adSSebastian Redl ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
670c95d8192SDylan Noblesmith                               IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
67171731d6bSArgyrios Kyrtzidis                                   const FileSystemOptions &FileSystemOpts,
6728bcb1c68STed Kremenek                                   bool OnlyLocalDecls,
673aa98ed9aSDouglas Gregor                                   RemappedFile *RemappedFiles,
67433cdd810SDouglas Gregor                                   unsigned NumRemappedFiles,
6754a280ff4SArgyrios Kyrtzidis                                   bool CaptureDiagnostics,
6766d7833f1SArgyrios Kyrtzidis                                   bool AllowPCHWithCompilerErrors,
6776d7833f1SArgyrios Kyrtzidis                                   bool UserFilesAreVolatile) {
678e2778999SDylan Noblesmith   OwningPtr<ASTUnit> AST(new ASTUnit(true));
6794422bfeaSTed Kremenek 
6804422bfeaSTed Kremenek   // Recover resources if we crash before exiting this method.
681022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
682022a4904STed Kremenek     ASTUnitCleanup(AST.get());
6839c902b55SDavid Blaikie   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
6849c902b55SDavid Blaikie     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
685022a4904STed Kremenek     DiagCleanup(Diags.getPtr());
6864422bfeaSTed Kremenek 
687345c1bcbSDouglas Gregor   ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
688d03e823fSDouglas Gregor 
68916bef857SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
69044c6ee77SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
6917f95d26eSDouglas Gregor   AST->Diagnostics = Diags;
6925e14d39aSTed Kremenek   AST->FileMgr = new FileManager(FileSystemOpts);
6936d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
6945e14d39aSTed Kremenek   AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
6956d7833f1SArgyrios Kyrtzidis                                      AST->getFileManager(),
6966d7833f1SArgyrios Kyrtzidis                                      UserFilesAreVolatile);
697197ac203SDouglas Gregor   AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(),
6981fb5c3a6SDouglas Gregor                                          AST->getDiagnostics(),
69989929282SDouglas Gregor                                          AST->ASTFileLangOpts,
70089929282SDouglas Gregor                                          /*Target=*/0));
701ce379752SArgyrios Kyrtzidis 
702aa98ed9aSDouglas Gregor   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
70311e6f0a6SArgyrios Kyrtzidis     FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
70411e6f0a6SArgyrios Kyrtzidis     if (const llvm::MemoryBuffer *
70511e6f0a6SArgyrios Kyrtzidis           memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
706aa98ed9aSDouglas Gregor       // Create the file entry for the file that we're mapping from.
707aa98ed9aSDouglas Gregor       const FileEntry *FromFile
708aa98ed9aSDouglas Gregor         = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
70911e6f0a6SArgyrios Kyrtzidis                                                memBuf->getBufferSize(),
7105159f616SChris Lattner                                                0);
711aa98ed9aSDouglas Gregor       if (!FromFile) {
712d03e823fSDouglas Gregor         AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
713aa98ed9aSDouglas Gregor           << RemappedFiles[I].first;
71411e6f0a6SArgyrios Kyrtzidis         delete memBuf;
715aa98ed9aSDouglas Gregor         continue;
716aa98ed9aSDouglas Gregor       }
717aa98ed9aSDouglas Gregor 
718aa98ed9aSDouglas Gregor       // Override the contents of the "from" file with the contents of
719aa98ed9aSDouglas Gregor       // the "to" file.
72011e6f0a6SArgyrios Kyrtzidis       AST->getSourceManager().overrideFileContents(FromFile, memBuf);
72111e6f0a6SArgyrios Kyrtzidis 
72211e6f0a6SArgyrios Kyrtzidis     } else {
72311e6f0a6SArgyrios Kyrtzidis       const char *fname = fileOrBuf.get<const char *>();
72411e6f0a6SArgyrios Kyrtzidis       const FileEntry *ToFile = AST->FileMgr->getFile(fname);
72511e6f0a6SArgyrios Kyrtzidis       if (!ToFile) {
72611e6f0a6SArgyrios Kyrtzidis         AST->getDiagnostics().Report(diag::err_fe_remap_missing_to_file)
72711e6f0a6SArgyrios Kyrtzidis         << RemappedFiles[I].first << fname;
72811e6f0a6SArgyrios Kyrtzidis         continue;
72911e6f0a6SArgyrios Kyrtzidis       }
73011e6f0a6SArgyrios Kyrtzidis 
73111e6f0a6SArgyrios Kyrtzidis       // Create the file entry for the file that we're mapping from.
73211e6f0a6SArgyrios Kyrtzidis       const FileEntry *FromFile
73311e6f0a6SArgyrios Kyrtzidis         = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
73411e6f0a6SArgyrios Kyrtzidis                                                ToFile->getSize(),
73511e6f0a6SArgyrios Kyrtzidis                                                0);
73611e6f0a6SArgyrios Kyrtzidis       if (!FromFile) {
73711e6f0a6SArgyrios Kyrtzidis         AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
73811e6f0a6SArgyrios Kyrtzidis           << RemappedFiles[I].first;
73911e6f0a6SArgyrios Kyrtzidis         delete memBuf;
74011e6f0a6SArgyrios Kyrtzidis         continue;
74111e6f0a6SArgyrios Kyrtzidis       }
74211e6f0a6SArgyrios Kyrtzidis 
74311e6f0a6SArgyrios Kyrtzidis       // Override the contents of the "from" file with the contents of
74411e6f0a6SArgyrios Kyrtzidis       // the "to" file.
74511e6f0a6SArgyrios Kyrtzidis       AST->getSourceManager().overrideFileContents(FromFile, ToFile);
74611e6f0a6SArgyrios Kyrtzidis     }
747aa98ed9aSDouglas Gregor   }
748aa98ed9aSDouglas Gregor 
749ce379752SArgyrios Kyrtzidis   // Gather Info for preprocessor construction later on.
750ce379752SArgyrios Kyrtzidis 
751ce379752SArgyrios Kyrtzidis   HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
752ce379752SArgyrios Kyrtzidis   std::string Predefines;
753ce379752SArgyrios Kyrtzidis   unsigned Counter;
754ce379752SArgyrios Kyrtzidis 
755e2778999SDylan Noblesmith   OwningPtr<ASTReader> Reader;
756ce379752SArgyrios Kyrtzidis 
75783297dfcSDouglas Gregor   AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts,
75883297dfcSDouglas Gregor                              /*Target=*/0, AST->getSourceManager(), HeaderInfo,
75983297dfcSDouglas Gregor                              *AST,
76083297dfcSDouglas Gregor                              /*IILookup=*/0,
76183297dfcSDouglas Gregor                              /*OwnsHeaderSearch=*/false,
76283297dfcSDouglas Gregor                              /*DelayInitialization=*/true);
763e8bbc121SDouglas Gregor   Preprocessor &PP = *AST->PP;
764e8bbc121SDouglas Gregor 
765e8bbc121SDouglas Gregor   AST->Ctx = new ASTContext(AST->ASTFileLangOpts,
766e8bbc121SDouglas Gregor                             AST->getSourceManager(),
767e8bbc121SDouglas Gregor                             /*Target=*/0,
768e8bbc121SDouglas Gregor                             PP.getIdentifierTable(),
769e8bbc121SDouglas Gregor                             PP.getSelectorTable(),
770e8bbc121SDouglas Gregor                             PP.getBuiltinInfo(),
771e8bbc121SDouglas Gregor                             /* size_reserve = */0,
772e8bbc121SDouglas Gregor                             /*DelayInitialization=*/true);
773e8bbc121SDouglas Gregor   ASTContext &Context = *AST->Ctx;
77483297dfcSDouglas Gregor 
775945a8193SArgyrios Kyrtzidis   bool disableValid = false;
776945a8193SArgyrios Kyrtzidis   if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
777945a8193SArgyrios Kyrtzidis     disableValid = true;
7784a280ff4SArgyrios Kyrtzidis   Reader.reset(new ASTReader(PP, Context,
7794a280ff4SArgyrios Kyrtzidis                              /*isysroot=*/"",
780945a8193SArgyrios Kyrtzidis                              /*DisableValidation=*/disableValid,
7814a280ff4SArgyrios Kyrtzidis                              /*DisableStatCache=*/false,
7824a280ff4SArgyrios Kyrtzidis                              AllowPCHWithCompilerErrors));
7832159b8d2STed Kremenek 
7842159b8d2STed Kremenek   // Recover resources if we crash before exiting this method.
7852159b8d2STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTReader>
7862159b8d2STed Kremenek     ReaderCleanup(Reader.get());
7872159b8d2STed Kremenek 
788e8bbc121SDouglas Gregor   Reader->setListener(new ASTInfoCollector(*AST->PP, Context,
78983297dfcSDouglas Gregor                                            AST->ASTFileLangOpts, HeaderInfo,
79083297dfcSDouglas Gregor                                            AST->Target, Predefines, Counter));
7912d9c740cSDaniel Dunbar 
792a6895d8aSDouglas Gregor   switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) {
7932c499f65SSebastian Redl   case ASTReader::Success:
794ce379752SArgyrios Kyrtzidis     break;
795ce379752SArgyrios Kyrtzidis 
7962c499f65SSebastian Redl   case ASTReader::Failure:
7972c499f65SSebastian Redl   case ASTReader::IgnorePCH:
798d03e823fSDouglas Gregor     AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
799ce379752SArgyrios Kyrtzidis     return NULL;
800ce379752SArgyrios Kyrtzidis   }
801ce379752SArgyrios Kyrtzidis 
802a8a50937SDaniel Dunbar   AST->OriginalSourceFile = Reader->getOriginalSourceFile();
803a8a50937SDaniel Dunbar 
804b7bbfdd9SDaniel Dunbar   PP.setPredefines(Reader->getSuggestedPredefines());
805ce379752SArgyrios Kyrtzidis   PP.setCounterValue(Counter);
806ce379752SArgyrios Kyrtzidis 
8072c499f65SSebastian Redl   // Attach the AST reader to the AST context as an external AST
808ce379752SArgyrios Kyrtzidis   // source, so that declarations will be deserialized from the
809d44cd6adSSebastian Redl   // AST file as needed.
8102c499f65SSebastian Redl   ASTReader *ReaderPtr = Reader.get();
811e2778999SDylan Noblesmith   OwningPtr<ExternalASTSource> Source(Reader.take());
8122159b8d2STed Kremenek 
8132159b8d2STed Kremenek   // Unregister the cleanup for ASTReader.  It will get cleaned up
8142159b8d2STed Kremenek   // by the ASTUnit cleanup.
8152159b8d2STed Kremenek   ReaderCleanup.unregister();
8162159b8d2STed Kremenek 
817ce379752SArgyrios Kyrtzidis   Context.setExternalSource(Source);
818ce379752SArgyrios Kyrtzidis 
8196fd55e06SDouglas Gregor   // Create an AST consumer, even though it isn't used.
8206fd55e06SDouglas Gregor   AST->Consumer.reset(new ASTConsumer);
8216fd55e06SDouglas Gregor 
8222c499f65SSebastian Redl   // Create a semantic analysis object and tell the AST reader about it.
8236fd55e06SDouglas Gregor   AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
8246fd55e06SDouglas Gregor   AST->TheSema->Initialize();
8256fd55e06SDouglas Gregor   ReaderPtr->InitializeSema(*AST->TheSema);
826244ce8b2SArgyrios Kyrtzidis   AST->Reader = ReaderPtr;
8276fd55e06SDouglas Gregor 
828ce379752SArgyrios Kyrtzidis   return AST.take();
829ce379752SArgyrios Kyrtzidis }
830764c0820SDaniel Dunbar 
831764c0820SDaniel Dunbar namespace {
832764c0820SDaniel Dunbar 
833df7a79a9SDouglas Gregor /// \brief Preprocessor callback class that updates a hash value with the names
834df7a79a9SDouglas Gregor /// of all macros that have been defined by the translation unit.
835df7a79a9SDouglas Gregor class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
836df7a79a9SDouglas Gregor   unsigned &Hash;
837644dca07SDaniel Dunbar 
838644dca07SDaniel Dunbar public:
839df7a79a9SDouglas Gregor   explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
840df7a79a9SDouglas Gregor 
841df7a79a9SDouglas Gregor   virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
842df7a79a9SDouglas Gregor     Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash);
843df7a79a9SDouglas Gregor   }
844df7a79a9SDouglas Gregor };
845df7a79a9SDouglas Gregor 
846df7a79a9SDouglas Gregor /// \brief Add the given declaration to the hash of all top-level entities.
847df7a79a9SDouglas Gregor void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
848df7a79a9SDouglas Gregor   if (!D)
849df7a79a9SDouglas Gregor     return;
850df7a79a9SDouglas Gregor 
851df7a79a9SDouglas Gregor   DeclContext *DC = D->getDeclContext();
852df7a79a9SDouglas Gregor   if (!DC)
853df7a79a9SDouglas Gregor     return;
854df7a79a9SDouglas Gregor 
855df7a79a9SDouglas Gregor   if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
856df7a79a9SDouglas Gregor     return;
857df7a79a9SDouglas Gregor 
858df7a79a9SDouglas Gregor   if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
859df7a79a9SDouglas Gregor     if (ND->getIdentifier())
860df7a79a9SDouglas Gregor       Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash);
861df7a79a9SDouglas Gregor     else if (DeclarationName Name = ND->getDeclName()) {
862df7a79a9SDouglas Gregor       std::string NameStr = Name.getAsString();
863df7a79a9SDouglas Gregor       Hash = llvm::HashString(NameStr, Hash);
864df7a79a9SDouglas Gregor     }
865df7a79a9SDouglas Gregor     return;
866df7a79a9SDouglas Gregor   }
867df7a79a9SDouglas Gregor }
868df7a79a9SDouglas Gregor 
869df7a79a9SDouglas Gregor class TopLevelDeclTrackerConsumer : public ASTConsumer {
870df7a79a9SDouglas Gregor   ASTUnit &Unit;
871df7a79a9SDouglas Gregor   unsigned &Hash;
872df7a79a9SDouglas Gregor 
873df7a79a9SDouglas Gregor public:
874df7a79a9SDouglas Gregor   TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
875df7a79a9SDouglas Gregor     : Unit(_Unit), Hash(Hash) {
876df7a79a9SDouglas Gregor     Hash = 0;
877df7a79a9SDouglas Gregor   }
878644dca07SDaniel Dunbar 
879e54568d6SArgyrios Kyrtzidis   void handleTopLevelDecl(Decl *D) {
880516eec2dSArgyrios Kyrtzidis     if (!D)
881516eec2dSArgyrios Kyrtzidis       return;
882516eec2dSArgyrios Kyrtzidis 
883acc59c3eSTed Kremenek     // FIXME: Currently ObjC method declarations are incorrectly being
884acc59c3eSTed Kremenek     // reported as top-level declarations, even though their DeclContext
885acc59c3eSTed Kremenek     // is the containing ObjC @interface/@implementation.  This is a
886acc59c3eSTed Kremenek     // fundamental problem in the parser right now.
887acc59c3eSTed Kremenek     if (isa<ObjCMethodDecl>(D))
888e54568d6SArgyrios Kyrtzidis       return;
889df7a79a9SDouglas Gregor 
890df7a79a9SDouglas Gregor     AddTopLevelDeclarationToHash(D, Hash);
891e9db88f9SDouglas Gregor     Unit.addTopLevelDecl(D);
892e54568d6SArgyrios Kyrtzidis 
893e54568d6SArgyrios Kyrtzidis     handleFileLevelDecl(D);
894acc59c3eSTed Kremenek   }
895e54568d6SArgyrios Kyrtzidis 
896e54568d6SArgyrios Kyrtzidis   void handleFileLevelDecl(Decl *D) {
897e54568d6SArgyrios Kyrtzidis     Unit.addFileLevelDecl(D);
898e54568d6SArgyrios Kyrtzidis     if (NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(D)) {
899e54568d6SArgyrios Kyrtzidis       for (NamespaceDecl::decl_iterator
900e54568d6SArgyrios Kyrtzidis              I = NSD->decls_begin(), E = NSD->decls_end(); I != E; ++I)
901e54568d6SArgyrios Kyrtzidis         handleFileLevelDecl(*I);
902e54568d6SArgyrios Kyrtzidis     }
903e54568d6SArgyrios Kyrtzidis   }
904e54568d6SArgyrios Kyrtzidis 
905841dd886SArgyrios Kyrtzidis   bool HandleTopLevelDecl(DeclGroupRef D) {
906e54568d6SArgyrios Kyrtzidis     for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
907e54568d6SArgyrios Kyrtzidis       handleTopLevelDecl(*it);
908841dd886SArgyrios Kyrtzidis     return true;
909644dca07SDaniel Dunbar   }
910eaa4ade8SSebastian Redl 
911eaa4ade8SSebastian Redl   // We're not interested in "interesting" decls.
912eaa4ade8SSebastian Redl   void HandleInterestingDecl(DeclGroupRef) {}
913e54568d6SArgyrios Kyrtzidis 
914e54568d6SArgyrios Kyrtzidis   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {
915e54568d6SArgyrios Kyrtzidis     for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
916e54568d6SArgyrios Kyrtzidis       handleTopLevelDecl(*it);
917e54568d6SArgyrios Kyrtzidis   }
918644dca07SDaniel Dunbar };
919644dca07SDaniel Dunbar 
920644dca07SDaniel Dunbar class TopLevelDeclTrackerAction : public ASTFrontendAction {
921644dca07SDaniel Dunbar public:
922644dca07SDaniel Dunbar   ASTUnit &Unit;
923644dca07SDaniel Dunbar 
924764c0820SDaniel Dunbar   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
9250e62c1ccSChris Lattner                                          StringRef InFile) {
926df7a79a9SDouglas Gregor     CI.getPreprocessor().addPPCallbacks(
927df7a79a9SDouglas Gregor      new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
928df7a79a9SDouglas Gregor     return new TopLevelDeclTrackerConsumer(Unit,
929df7a79a9SDouglas Gregor                                            Unit.getCurrentTopLevelHashValue());
930764c0820SDaniel Dunbar   }
931764c0820SDaniel Dunbar 
932764c0820SDaniel Dunbar public:
933644dca07SDaniel Dunbar   TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
934644dca07SDaniel Dunbar 
935764c0820SDaniel Dunbar   virtual bool hasCodeCompletionSupport() const { return false; }
93669f74f80SDouglas Gregor   virtual TranslationUnitKind getTranslationUnitKind()  {
93769f74f80SDouglas Gregor     return Unit.getTranslationUnitKind();
938028d3e4dSDouglas Gregor   }
939764c0820SDaniel Dunbar };
940764c0820SDaniel Dunbar 
94157332719SArgyrios Kyrtzidis class PrecompilePreambleConsumer : public PCHGenerator {
94248c8cd3fSDouglas Gregor   ASTUnit &Unit;
943df7a79a9SDouglas Gregor   unsigned &Hash;
944e9db88f9SDouglas Gregor   std::vector<Decl *> TopLevelDecls;
94548c8cd3fSDouglas Gregor 
94648c8cd3fSDouglas Gregor public:
94736db4f96SDouglas Gregor   PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP,
9480e62c1ccSChris Lattner                              StringRef isysroot, raw_ostream *Out)
949f7a700fdSDouglas Gregor     : PCHGenerator(PP, "", 0, isysroot, Out), Unit(Unit),
950df7a79a9SDouglas Gregor       Hash(Unit.getCurrentTopLevelHashValue()) {
951df7a79a9SDouglas Gregor     Hash = 0;
952df7a79a9SDouglas Gregor   }
95348c8cd3fSDouglas Gregor 
954841dd886SArgyrios Kyrtzidis   virtual bool HandleTopLevelDecl(DeclGroupRef D) {
95548c8cd3fSDouglas Gregor     for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
95648c8cd3fSDouglas Gregor       Decl *D = *it;
95748c8cd3fSDouglas Gregor       // FIXME: Currently ObjC method declarations are incorrectly being
95848c8cd3fSDouglas Gregor       // reported as top-level declarations, even though their DeclContext
95948c8cd3fSDouglas Gregor       // is the containing ObjC @interface/@implementation.  This is a
96048c8cd3fSDouglas Gregor       // fundamental problem in the parser right now.
96148c8cd3fSDouglas Gregor       if (isa<ObjCMethodDecl>(D))
96248c8cd3fSDouglas Gregor         continue;
963df7a79a9SDouglas Gregor       AddTopLevelDeclarationToHash(D, Hash);
964e9db88f9SDouglas Gregor       TopLevelDecls.push_back(D);
965e9db88f9SDouglas Gregor     }
966841dd886SArgyrios Kyrtzidis     return true;
967e9db88f9SDouglas Gregor   }
968e9db88f9SDouglas Gregor 
969e9db88f9SDouglas Gregor   virtual void HandleTranslationUnit(ASTContext &Ctx) {
970e9db88f9SDouglas Gregor     PCHGenerator::HandleTranslationUnit(Ctx);
971e9db88f9SDouglas Gregor     if (!Unit.getDiagnostics().hasErrorOccurred()) {
972e9db88f9SDouglas Gregor       // Translate the top-level declarations we captured during
973e9db88f9SDouglas Gregor       // parsing into declaration IDs in the precompiled
974e9db88f9SDouglas Gregor       // preamble. This will allow us to deserialize those top-level
975e9db88f9SDouglas Gregor       // declarations when requested.
976e9db88f9SDouglas Gregor       for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
977e9db88f9SDouglas Gregor         Unit.addTopLevelDeclFromPreamble(
978e9db88f9SDouglas Gregor                                       getWriter().getDeclID(TopLevelDecls[I]));
97948c8cd3fSDouglas Gregor     }
98048c8cd3fSDouglas Gregor   }
98148c8cd3fSDouglas Gregor };
98248c8cd3fSDouglas Gregor 
98348c8cd3fSDouglas Gregor class PrecompilePreambleAction : public ASTFrontendAction {
98448c8cd3fSDouglas Gregor   ASTUnit &Unit;
98548c8cd3fSDouglas Gregor 
98648c8cd3fSDouglas Gregor public:
98748c8cd3fSDouglas Gregor   explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
98848c8cd3fSDouglas Gregor 
98948c8cd3fSDouglas Gregor   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
9900e62c1ccSChris Lattner                                          StringRef InFile) {
99148c8cd3fSDouglas Gregor     std::string Sysroot;
99210b2368eSArgyrios Kyrtzidis     std::string OutputFile;
9930e62c1ccSChris Lattner     raw_ostream *OS = 0;
99448c8cd3fSDouglas Gregor     if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
99510b2368eSArgyrios Kyrtzidis                                                        OutputFile,
99636db4f96SDouglas Gregor                                                        OS))
99748c8cd3fSDouglas Gregor       return 0;
99848c8cd3fSDouglas Gregor 
999c567ba26SDouglas Gregor     if (!CI.getFrontendOpts().RelocatablePCH)
1000c567ba26SDouglas Gregor       Sysroot.clear();
1001c567ba26SDouglas Gregor 
1002df7a79a9SDouglas Gregor     CI.getPreprocessor().addPPCallbacks(
1003df7a79a9SDouglas Gregor      new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
100436db4f96SDouglas Gregor     return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Sysroot,
100536db4f96SDouglas Gregor                                           OS);
100648c8cd3fSDouglas Gregor   }
100748c8cd3fSDouglas Gregor 
100848c8cd3fSDouglas Gregor   virtual bool hasCodeCompletionSupport() const { return false; }
100948c8cd3fSDouglas Gregor   virtual bool hasASTFileSupport() const { return false; }
101069f74f80SDouglas Gregor   virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; }
101148c8cd3fSDouglas Gregor };
101248c8cd3fSDouglas Gregor 
1013764c0820SDaniel Dunbar }
1014764c0820SDaniel Dunbar 
101538bacf34SArgyrios Kyrtzidis static void checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &
101638bacf34SArgyrios Kyrtzidis                                                             StoredDiagnostics) {
101738bacf34SArgyrios Kyrtzidis   // Get rid of stored diagnostics except the ones from the driver which do not
101838bacf34SArgyrios Kyrtzidis   // have a source location.
101938bacf34SArgyrios Kyrtzidis   for (unsigned I = 0; I < StoredDiagnostics.size(); ++I) {
102038bacf34SArgyrios Kyrtzidis     if (StoredDiagnostics[I].getLocation().isValid()) {
102138bacf34SArgyrios Kyrtzidis       StoredDiagnostics.erase(StoredDiagnostics.begin()+I);
102238bacf34SArgyrios Kyrtzidis       --I;
102338bacf34SArgyrios Kyrtzidis     }
102438bacf34SArgyrios Kyrtzidis   }
102538bacf34SArgyrios Kyrtzidis }
102638bacf34SArgyrios Kyrtzidis 
102738bacf34SArgyrios Kyrtzidis static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
102838bacf34SArgyrios Kyrtzidis                                                               StoredDiagnostics,
102938bacf34SArgyrios Kyrtzidis                                   SourceManager &SM) {
103038bacf34SArgyrios Kyrtzidis   // The stored diagnostic has the old source manager in it; update
103138bacf34SArgyrios Kyrtzidis   // the locations to refer into the new source manager. Since we've
103238bacf34SArgyrios Kyrtzidis   // been careful to make sure that the source manager's state
103338bacf34SArgyrios Kyrtzidis   // before and after are identical, so that we can reuse the source
103438bacf34SArgyrios Kyrtzidis   // location itself.
103538bacf34SArgyrios Kyrtzidis   for (unsigned I = 0, N = StoredDiagnostics.size(); I < N; ++I) {
103638bacf34SArgyrios Kyrtzidis     if (StoredDiagnostics[I].getLocation().isValid()) {
103738bacf34SArgyrios Kyrtzidis       FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SM);
103838bacf34SArgyrios Kyrtzidis       StoredDiagnostics[I].setLocation(Loc);
103938bacf34SArgyrios Kyrtzidis     }
104038bacf34SArgyrios Kyrtzidis   }
104138bacf34SArgyrios Kyrtzidis }
104238bacf34SArgyrios Kyrtzidis 
1043aa21cc40SDouglas Gregor /// Parse the source file into a translation unit using the given compiler
1044aa21cc40SDouglas Gregor /// invocation, replacing the current translation unit.
1045aa21cc40SDouglas Gregor ///
1046aa21cc40SDouglas Gregor /// \returns True if a failure occurred that causes the ASTUnit not to
1047aa21cc40SDouglas Gregor /// contain any translation-unit information, false otherwise.
10486481ef1fSDouglas Gregor bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
104996c04261SDouglas Gregor   delete SavedMainFileBuffer;
105096c04261SDouglas Gregor   SavedMainFileBuffer = 0;
105196c04261SDouglas Gregor 
10525e14d39aSTed Kremenek   if (!Invocation) {
1053a0734c5fSDouglas Gregor     delete OverrideMainBuffer;
1054aa21cc40SDouglas Gregor     return true;
1055a0734c5fSDouglas Gregor   }
1056aa21cc40SDouglas Gregor 
1057764c0820SDaniel Dunbar   // Create the compiler instance to use for building the AST.
1058e2778999SDylan Noblesmith   OwningPtr<CompilerInstance> Clang(new CompilerInstance());
105984de4a17STed Kremenek 
106084de4a17STed Kremenek   // Recover resources if we crash before exiting this method.
1061022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1062022a4904STed Kremenek     CICleanup(Clang.get());
106384de4a17STed Kremenek 
1064c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<CompilerInvocation>
106514c32e88SArgyrios Kyrtzidis     CCInvocation(new CompilerInvocation(*Invocation));
106614c32e88SArgyrios Kyrtzidis 
106714c32e88SArgyrios Kyrtzidis   Clang->setInvocation(CCInvocation.getPtr());
106832fbe312SDouglas Gregor   OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
1069764c0820SDaniel Dunbar 
10708e984da8SDouglas Gregor   // Set up diagnostics, capturing any diagnostics that would
10718e984da8SDouglas Gregor   // otherwise be dropped.
107284de4a17STed Kremenek   Clang->setDiagnostics(&getDiagnostics());
1073764c0820SDaniel Dunbar 
1074764c0820SDaniel Dunbar   // Create the target instance.
107584de4a17STed Kremenek   Clang->getTargetOpts().Features = TargetFeatures;
107684de4a17STed Kremenek   Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
107784de4a17STed Kremenek                    Clang->getTargetOpts()));
107884de4a17STed Kremenek   if (!Clang->hasTarget()) {
1079a0734c5fSDouglas Gregor     delete OverrideMainBuffer;
1080aa21cc40SDouglas Gregor     return true;
1081a0734c5fSDouglas Gregor   }
1082764c0820SDaniel Dunbar 
1083764c0820SDaniel Dunbar   // Inform the target of the language options.
1084764c0820SDaniel Dunbar   //
1085764c0820SDaniel Dunbar   // FIXME: We shouldn't need to do this, the target should be immutable once
1086764c0820SDaniel Dunbar   // created. This complexity should be lifted elsewhere.
108784de4a17STed Kremenek   Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
1088764c0820SDaniel Dunbar 
108984de4a17STed Kremenek   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1090764c0820SDaniel Dunbar          "Invocation must have exactly one source file!");
109132fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
1092764c0820SDaniel Dunbar          "FIXME: AST inputs not yet supported here!");
109332fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
10949507f9ccSDaniel Dunbar          "IR inputs not support here!");
1095764c0820SDaniel Dunbar 
1096aa21cc40SDouglas Gregor   // Configure the various subsystems.
1097aa21cc40SDouglas Gregor   // FIXME: Should we retain the previous file manager?
10988cf47df7STed Kremenek   LangOpts = &Clang->getLangOpts();
109984de4a17STed Kremenek   FileSystemOpts = Clang->getFileSystemOpts();
11005e14d39aSTed Kremenek   FileMgr = new FileManager(FileSystemOpts);
11016d7833f1SArgyrios Kyrtzidis   SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
11026d7833f1SArgyrios Kyrtzidis                                 UserFilesAreVolatile);
11036fd55e06SDouglas Gregor   TheSema.reset();
11045e14d39aSTed Kremenek   Ctx = 0;
11055e14d39aSTed Kremenek   PP = 0;
1106244ce8b2SArgyrios Kyrtzidis   Reader = 0;
1107aa21cc40SDouglas Gregor 
1108aa21cc40SDouglas Gregor   // Clear out old caches and data.
1109aa21cc40SDouglas Gregor   TopLevelDecls.clear();
1110e54568d6SArgyrios Kyrtzidis   clearFileLevelDecls();
1111aa21cc40SDouglas Gregor   CleanTemporaryFiles();
1112a8a50937SDaniel Dunbar 
11137b02b583SDouglas Gregor   if (!OverrideMainBuffer) {
111438bacf34SArgyrios Kyrtzidis     checkAndRemoveNonDriverDiags(StoredDiagnostics);
11157b02b583SDouglas Gregor     TopLevelDeclsInPreamble.clear();
11167b02b583SDouglas Gregor   }
1117d9a30af2SDouglas Gregor 
1118764c0820SDaniel Dunbar   // Create a file manager object to provide access to and cache the filesystem.
111984de4a17STed Kremenek   Clang->setFileManager(&getFileManager());
1120764c0820SDaniel Dunbar 
1121764c0820SDaniel Dunbar   // Create the source manager.
112284de4a17STed Kremenek   Clang->setSourceManager(&getSourceManager());
1123764c0820SDaniel Dunbar 
11243f4bea06SDouglas Gregor   // If the main file has been overridden due to the use of a preamble,
11253f4bea06SDouglas Gregor   // make that override happen and introduce the preamble.
112684de4a17STed Kremenek   PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts();
11273f4bea06SDouglas Gregor   if (OverrideMainBuffer) {
11283f4bea06SDouglas Gregor     PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
11293f4bea06SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
11303f4bea06SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second
11313f4bea06SDouglas Gregor                                                     = PreambleEndsAtStartOfLine;
113206b4f919STed Kremenek     PreprocessorOpts.ImplicitPCHInclude = getPreambleFile(this);
1133ce3a8293SDouglas Gregor     PreprocessorOpts.DisablePCHValidation = true;
113496c04261SDouglas Gregor 
1135d9a30af2SDouglas Gregor     // The stored diagnostic has the old source manager in it; update
1136d9a30af2SDouglas Gregor     // the locations to refer into the new source manager. Since we've
1137d9a30af2SDouglas Gregor     // been careful to make sure that the source manager's state
1138d9a30af2SDouglas Gregor     // before and after are identical, so that we can reuse the source
1139d9a30af2SDouglas Gregor     // location itself.
114038bacf34SArgyrios Kyrtzidis     checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());
11417bb8af61SDouglas Gregor 
11427bb8af61SDouglas Gregor     // Keep track of the override buffer;
11437bb8af61SDouglas Gregor     SavedMainFileBuffer = OverrideMainBuffer;
11443f4bea06SDouglas Gregor   }
11453f4bea06SDouglas Gregor 
1146e2778999SDylan Noblesmith   OwningPtr<TopLevelDeclTrackerAction> Act(
1147022a4904STed Kremenek     new TopLevelDeclTrackerAction(*this));
1148022a4904STed Kremenek 
1149022a4904STed Kremenek   // Recover resources if we crash before exiting this method.
1150022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
1151022a4904STed Kremenek     ActCleanup(Act.get());
1152022a4904STed Kremenek 
115332fbe312SDouglas Gregor   if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
1154764c0820SDaniel Dunbar     goto error;
1155764c0820SDaniel Dunbar 
1156925296b4SDouglas Gregor   if (OverrideMainBuffer) {
115706b4f919STed Kremenek     std::string ModName = getPreambleFile(this);
1158925296b4SDouglas Gregor     TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
1159925296b4SDouglas Gregor                                getSourceManager(), PreambleDiagnostics,
1160925296b4SDouglas Gregor                                StoredDiagnostics);
1161925296b4SDouglas Gregor   }
1162925296b4SDouglas Gregor 
11631416e17cSArgyrios Kyrtzidis   if (!Act->Execute())
11641416e17cSArgyrios Kyrtzidis     goto error;
1165764c0820SDaniel Dunbar 
1166ac1cc934SArgyrios Kyrtzidis   transferASTDataFromCompilerInstance(*Clang);
1167764c0820SDaniel Dunbar 
1168644dca07SDaniel Dunbar   Act->EndSourceFile();
1169764c0820SDaniel Dunbar 
1170ac1cc934SArgyrios Kyrtzidis   FailedParseDiagnostics.clear();
1171ac1cc934SArgyrios Kyrtzidis 
1172aa21cc40SDouglas Gregor   return false;
1173764c0820SDaniel Dunbar 
1174764c0820SDaniel Dunbar error:
11753f4bea06SDouglas Gregor   // Remove the overridden buffer we used for the preamble.
1176ce3a8293SDouglas Gregor   if (OverrideMainBuffer) {
1177a0734c5fSDouglas Gregor     delete OverrideMainBuffer;
1178a3d3ba1cSDouglas Gregor     SavedMainFileBuffer = 0;
1179ce3a8293SDouglas Gregor   }
11803f4bea06SDouglas Gregor 
1181ac1cc934SArgyrios Kyrtzidis   // Keep the ownership of the data in the ASTUnit because the client may
1182ac1cc934SArgyrios Kyrtzidis   // want to see the diagnostics.
1183ac1cc934SArgyrios Kyrtzidis   transferASTDataFromCompilerInstance(*Clang);
1184ac1cc934SArgyrios Kyrtzidis   FailedParseDiagnostics.swap(StoredDiagnostics);
1185efc46958SDouglas Gregor   StoredDiagnostics.clear();
1186067cbfa2SArgyrios Kyrtzidis   NumStoredDiagnosticsFromDriver = 0;
1187aa21cc40SDouglas Gregor   return true;
1188aa21cc40SDouglas Gregor }
1189aa21cc40SDouglas Gregor 
1190be2d8c60SDouglas Gregor /// \brief Simple function to retrieve a path for a preamble precompiled header.
1191be2d8c60SDouglas Gregor static std::string GetPreamblePCHPath() {
1192be2d8c60SDouglas Gregor   // FIXME: This is lame; sys::Path should provide this function (in particular,
1193be2d8c60SDouglas Gregor   // it should know how to find the temporary files dir).
1194be2d8c60SDouglas Gregor   // FIXME: This is really lame. I copied this code from the Driver!
1195250ab1dcSDouglas Gregor   // FIXME: This is a hack so that we can override the preamble file during
1196250ab1dcSDouglas Gregor   // crash-recovery testing, which is the only case where the preamble files
1197250ab1dcSDouglas Gregor   // are not necessarily cleaned up.
1198250ab1dcSDouglas Gregor   const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
1199250ab1dcSDouglas Gregor   if (TmpFile)
1200250ab1dcSDouglas Gregor     return TmpFile;
1201250ab1dcSDouglas Gregor 
1202be2d8c60SDouglas Gregor   std::string Error;
1203be2d8c60SDouglas Gregor   const char *TmpDir = ::getenv("TMPDIR");
1204be2d8c60SDouglas Gregor   if (!TmpDir)
1205be2d8c60SDouglas Gregor     TmpDir = ::getenv("TEMP");
1206be2d8c60SDouglas Gregor   if (!TmpDir)
1207be2d8c60SDouglas Gregor     TmpDir = ::getenv("TMP");
1208ce3449f5SDouglas Gregor #ifdef LLVM_ON_WIN32
1209ce3449f5SDouglas Gregor   if (!TmpDir)
1210ce3449f5SDouglas Gregor     TmpDir = ::getenv("USERPROFILE");
1211ce3449f5SDouglas Gregor #endif
1212be2d8c60SDouglas Gregor   if (!TmpDir)
1213be2d8c60SDouglas Gregor     TmpDir = "/tmp";
1214be2d8c60SDouglas Gregor   llvm::sys::Path P(TmpDir);
1215ce3449f5SDouglas Gregor   P.createDirectoryOnDisk(true);
1216be2d8c60SDouglas Gregor   P.appendComponent("preamble");
121720975b25SDouglas Gregor   P.appendSuffix("pch");
1218ff9a5506SArgyrios Kyrtzidis   if (P.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0))
1219be2d8c60SDouglas Gregor     return std::string();
1220be2d8c60SDouglas Gregor 
1221be2d8c60SDouglas Gregor   return P.str();
1222be2d8c60SDouglas Gregor }
1223be2d8c60SDouglas Gregor 
12243f4bea06SDouglas Gregor /// \brief Compute the preamble for the main file, providing the source buffer
12253f4bea06SDouglas Gregor /// that corresponds to the main file along with a pair (bytes, start-of-line)
12263f4bea06SDouglas Gregor /// that describes the preamble.
12273f4bea06SDouglas Gregor std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
1228028d3e4dSDouglas Gregor ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
1229028d3e4dSDouglas Gregor                          unsigned MaxLines, bool &CreatedBuffer) {
12304dde7498SDouglas Gregor   FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
12315159f616SChris Lattner   PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
12324dde7498SDouglas Gregor   CreatedBuffer = false;
1233be2d8c60SDouglas Gregor 
1234be2d8c60SDouglas Gregor   // Try to determine if the main file has been remapped, either from the
1235be2d8c60SDouglas Gregor   // command line (to another file) or directly through the compiler invocation
1236be2d8c60SDouglas Gregor   // (to a memory buffer).
1237be2d8c60SDouglas Gregor   llvm::MemoryBuffer *Buffer = 0;
123832fbe312SDouglas Gregor   llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File);
1239be2d8c60SDouglas Gregor   if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
1240be2d8c60SDouglas Gregor     // Check whether there is a file-file remapping of the main file
1241be2d8c60SDouglas Gregor     for (PreprocessorOptions::remapped_file_iterator
1242be2d8c60SDouglas Gregor           M = PreprocessorOpts.remapped_file_begin(),
1243be2d8c60SDouglas Gregor           E = PreprocessorOpts.remapped_file_end();
1244be2d8c60SDouglas Gregor          M != E;
1245be2d8c60SDouglas Gregor          ++M) {
1246be2d8c60SDouglas Gregor       llvm::sys::PathWithStatus MPath(M->first);
1247be2d8c60SDouglas Gregor       if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
1248be2d8c60SDouglas Gregor         if (MainFileStatus->uniqueID == MStatus->uniqueID) {
1249be2d8c60SDouglas Gregor           // We found a remapping. Try to load the resulting, remapped source.
12504dde7498SDouglas Gregor           if (CreatedBuffer) {
1251be2d8c60SDouglas Gregor             delete Buffer;
12524dde7498SDouglas Gregor             CreatedBuffer = false;
12534dde7498SDouglas Gregor           }
12544dde7498SDouglas Gregor 
125571731d6bSArgyrios Kyrtzidis           Buffer = getBufferForFile(M->second);
1256be2d8c60SDouglas Gregor           if (!Buffer)
12573f4bea06SDouglas Gregor             return std::make_pair((llvm::MemoryBuffer*)0,
12583f4bea06SDouglas Gregor                                   std::make_pair(0, true));
12594dde7498SDouglas Gregor           CreatedBuffer = true;
1260be2d8c60SDouglas Gregor         }
1261be2d8c60SDouglas Gregor       }
1262be2d8c60SDouglas Gregor     }
1263be2d8c60SDouglas Gregor 
1264be2d8c60SDouglas Gregor     // Check whether there is a file-buffer remapping. It supercedes the
1265be2d8c60SDouglas Gregor     // file-file remapping.
1266be2d8c60SDouglas Gregor     for (PreprocessorOptions::remapped_file_buffer_iterator
1267be2d8c60SDouglas Gregor            M = PreprocessorOpts.remapped_file_buffer_begin(),
1268be2d8c60SDouglas Gregor            E = PreprocessorOpts.remapped_file_buffer_end();
1269be2d8c60SDouglas Gregor          M != E;
1270be2d8c60SDouglas Gregor          ++M) {
1271be2d8c60SDouglas Gregor       llvm::sys::PathWithStatus MPath(M->first);
1272be2d8c60SDouglas Gregor       if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
1273be2d8c60SDouglas Gregor         if (MainFileStatus->uniqueID == MStatus->uniqueID) {
1274be2d8c60SDouglas Gregor           // We found a remapping.
12754dde7498SDouglas Gregor           if (CreatedBuffer) {
1276be2d8c60SDouglas Gregor             delete Buffer;
12774dde7498SDouglas Gregor             CreatedBuffer = false;
12784dde7498SDouglas Gregor           }
12794dde7498SDouglas Gregor 
1280be2d8c60SDouglas Gregor           Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
1281be2d8c60SDouglas Gregor         }
1282be2d8c60SDouglas Gregor       }
1283be2d8c60SDouglas Gregor     }
1284be2d8c60SDouglas Gregor   }
1285be2d8c60SDouglas Gregor 
1286be2d8c60SDouglas Gregor   // If the main source file was not remapped, load it now.
1287be2d8c60SDouglas Gregor   if (!Buffer) {
128832fbe312SDouglas Gregor     Buffer = getBufferForFile(FrontendOpts.Inputs[0].File);
1289be2d8c60SDouglas Gregor     if (!Buffer)
12903f4bea06SDouglas Gregor       return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
12914dde7498SDouglas Gregor 
12924dde7498SDouglas Gregor     CreatedBuffer = true;
1293be2d8c60SDouglas Gregor   }
1294be2d8c60SDouglas Gregor 
12957aecbc76SArgyrios Kyrtzidis   return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer,
12968cf47df7STed Kremenek                                                        *Invocation.getLangOpts(),
12977aecbc76SArgyrios Kyrtzidis                                                        MaxLines));
12984dde7498SDouglas Gregor }
12994dde7498SDouglas Gregor 
13006481ef1fSDouglas Gregor static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
13016481ef1fSDouglas Gregor                                                       unsigned NewSize,
13020e62c1ccSChris Lattner                                                       StringRef NewName) {
13036481ef1fSDouglas Gregor   llvm::MemoryBuffer *Result
13046481ef1fSDouglas Gregor     = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
13056481ef1fSDouglas Gregor   memcpy(const_cast<char*>(Result->getBufferStart()),
13066481ef1fSDouglas Gregor          Old->getBufferStart(), Old->getBufferSize());
13076481ef1fSDouglas Gregor   memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
13083f4bea06SDouglas Gregor          ' ', NewSize - Old->getBufferSize() - 1);
13093f4bea06SDouglas Gregor   const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
13106481ef1fSDouglas Gregor 
13116481ef1fSDouglas Gregor   return Result;
13126481ef1fSDouglas Gregor }
13136481ef1fSDouglas Gregor 
13144dde7498SDouglas Gregor /// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
13154dde7498SDouglas Gregor /// the source file.
13164dde7498SDouglas Gregor ///
13174dde7498SDouglas Gregor /// This routine will compute the preamble of the main source file. If a
13184dde7498SDouglas Gregor /// non-trivial preamble is found, it will precompile that preamble into a
13194dde7498SDouglas Gregor /// precompiled header so that the precompiled preamble can be used to reduce
13204dde7498SDouglas Gregor /// reparsing time. If a precompiled preamble has already been constructed,
13214dde7498SDouglas Gregor /// this routine will determine if it is still valid and, if so, avoid
13224dde7498SDouglas Gregor /// rebuilding the precompiled preamble.
13234dde7498SDouglas Gregor ///
1324028d3e4dSDouglas Gregor /// \param AllowRebuild When true (the default), this routine is
1325028d3e4dSDouglas Gregor /// allowed to rebuild the precompiled preamble if it is found to be
1326028d3e4dSDouglas Gregor /// out-of-date.
1327028d3e4dSDouglas Gregor ///
1328028d3e4dSDouglas Gregor /// \param MaxLines When non-zero, the maximum number of lines that
1329028d3e4dSDouglas Gregor /// can occur within the preamble.
1330028d3e4dSDouglas Gregor ///
13316481ef1fSDouglas Gregor /// \returns If the precompiled preamble can be used, returns a newly-allocated
13326481ef1fSDouglas Gregor /// buffer that should be used in place of the main file when doing so.
13336481ef1fSDouglas Gregor /// Otherwise, returns a NULL pointer.
1334028d3e4dSDouglas Gregor llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
13353cc15810SDouglas Gregor                               const CompilerInvocation &PreambleInvocationIn,
1336028d3e4dSDouglas Gregor                                                            bool AllowRebuild,
1337028d3e4dSDouglas Gregor                                                            unsigned MaxLines) {
13383cc15810SDouglas Gregor 
1339c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<CompilerInvocation>
13403cc15810SDouglas Gregor     PreambleInvocation(new CompilerInvocation(PreambleInvocationIn));
13413cc15810SDouglas Gregor   FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
13424dde7498SDouglas Gregor   PreprocessorOptions &PreprocessorOpts
13433cc15810SDouglas Gregor     = PreambleInvocation->getPreprocessorOpts();
13444dde7498SDouglas Gregor 
13454dde7498SDouglas Gregor   bool CreatedPreambleBuffer = false;
13463f4bea06SDouglas Gregor   std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
13473cc15810SDouglas Gregor     = ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer);
13484dde7498SDouglas Gregor 
1349925296b4SDouglas Gregor   // If ComputePreamble() Take ownership of the preamble buffer.
1350e2778999SDylan Noblesmith   OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer;
13513edb1676SDouglas Gregor   if (CreatedPreambleBuffer)
13523edb1676SDouglas Gregor     OwnedPreambleBuffer.reset(NewPreamble.first);
13533edb1676SDouglas Gregor 
13543f4bea06SDouglas Gregor   if (!NewPreamble.second.first) {
13554dde7498SDouglas Gregor     // We couldn't find a preamble in the main source. Clear out the current
13564dde7498SDouglas Gregor     // preamble, if we have one. It's obviously no good any more.
13574dde7498SDouglas Gregor     Preamble.clear();
135806b4f919STed Kremenek     erasePreambleFile(this);
13594dde7498SDouglas Gregor 
1360bb420abdSDouglas Gregor     // The next time we actually see a preamble, precompile it.
1361bb420abdSDouglas Gregor     PreambleRebuildCounter = 1;
13626481ef1fSDouglas Gregor     return 0;
13634dde7498SDouglas Gregor   }
13644dde7498SDouglas Gregor 
13654dde7498SDouglas Gregor   if (!Preamble.empty()) {
13664dde7498SDouglas Gregor     // We've previously computed a preamble. Check whether we have the same
13674dde7498SDouglas Gregor     // preamble now that we did before, and that there's enough space in
13684dde7498SDouglas Gregor     // the main-file buffer within the precompiled preamble to fit the
13694dde7498SDouglas Gregor     // new main file.
13703f4bea06SDouglas Gregor     if (Preamble.size() == NewPreamble.second.first &&
13713f4bea06SDouglas Gregor         PreambleEndsAtStartOfLine == NewPreamble.second.second &&
1372f5275a83SDouglas Gregor         NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
13737c06d866SArgyrios Kyrtzidis         memcmp(Preamble.getBufferStart(), NewPreamble.first->getBufferStart(),
13743f4bea06SDouglas Gregor                NewPreamble.second.first) == 0) {
13754dde7498SDouglas Gregor       // The preamble has not changed. We may be able to re-use the precompiled
13764dde7498SDouglas Gregor       // preamble.
13774dde7498SDouglas Gregor 
13780e11955cSDouglas Gregor       // Check that none of the files used by the preamble have changed.
13790e11955cSDouglas Gregor       bool AnyFileChanged = false;
13804dde7498SDouglas Gregor 
13810e11955cSDouglas Gregor       // First, make a record of those files that have been overridden via
13820e11955cSDouglas Gregor       // remapping or unsaved_files.
13830e11955cSDouglas Gregor       llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
13840e11955cSDouglas Gregor       for (PreprocessorOptions::remapped_file_iterator
13850e11955cSDouglas Gregor                 R = PreprocessorOpts.remapped_file_begin(),
13860e11955cSDouglas Gregor              REnd = PreprocessorOpts.remapped_file_end();
13870e11955cSDouglas Gregor            !AnyFileChanged && R != REnd;
13880e11955cSDouglas Gregor            ++R) {
13890e11955cSDouglas Gregor         struct stat StatBuf;
13909583f794SAnders Carlsson         if (FileMgr->getNoncachedStatValue(R->second, StatBuf)) {
13910e11955cSDouglas Gregor           // If we can't stat the file we're remapping to, assume that something
13920e11955cSDouglas Gregor           // horrible happened.
13930e11955cSDouglas Gregor           AnyFileChanged = true;
13940e11955cSDouglas Gregor           break;
13950e11955cSDouglas Gregor         }
13960e11955cSDouglas Gregor 
13970e11955cSDouglas Gregor         OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
13980e11955cSDouglas Gregor                                                    StatBuf.st_mtime);
13990e11955cSDouglas Gregor       }
14000e11955cSDouglas Gregor       for (PreprocessorOptions::remapped_file_buffer_iterator
14010e11955cSDouglas Gregor                 R = PreprocessorOpts.remapped_file_buffer_begin(),
14020e11955cSDouglas Gregor              REnd = PreprocessorOpts.remapped_file_buffer_end();
14030e11955cSDouglas Gregor            !AnyFileChanged && R != REnd;
14040e11955cSDouglas Gregor            ++R) {
14050e11955cSDouglas Gregor         // FIXME: Should we actually compare the contents of file->buffer
14060e11955cSDouglas Gregor         // remappings?
14070e11955cSDouglas Gregor         OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
14080e11955cSDouglas Gregor                                                    0);
14090e11955cSDouglas Gregor       }
14100e11955cSDouglas Gregor 
14110e11955cSDouglas Gregor       // Check whether anything has changed.
14120e11955cSDouglas Gregor       for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
14130e11955cSDouglas Gregor              F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
14140e11955cSDouglas Gregor            !AnyFileChanged && F != FEnd;
14150e11955cSDouglas Gregor            ++F) {
14160e11955cSDouglas Gregor         llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
14170e11955cSDouglas Gregor           = OverriddenFiles.find(F->first());
14180e11955cSDouglas Gregor         if (Overridden != OverriddenFiles.end()) {
14190e11955cSDouglas Gregor           // This file was remapped; check whether the newly-mapped file
14200e11955cSDouglas Gregor           // matches up with the previous mapping.
14210e11955cSDouglas Gregor           if (Overridden->second != F->second)
14220e11955cSDouglas Gregor             AnyFileChanged = true;
14230e11955cSDouglas Gregor           continue;
14240e11955cSDouglas Gregor         }
14250e11955cSDouglas Gregor 
14260e11955cSDouglas Gregor         // The file was not remapped; check whether it has changed on disk.
14270e11955cSDouglas Gregor         struct stat StatBuf;
14289583f794SAnders Carlsson         if (FileMgr->getNoncachedStatValue(F->first(), StatBuf)) {
14290e11955cSDouglas Gregor           // If we can't stat the file, assume that something horrible happened.
14300e11955cSDouglas Gregor           AnyFileChanged = true;
14310e11955cSDouglas Gregor         } else if (StatBuf.st_size != F->second.first ||
14320e11955cSDouglas Gregor                    StatBuf.st_mtime != F->second.second)
14330e11955cSDouglas Gregor           AnyFileChanged = true;
14340e11955cSDouglas Gregor       }
14350e11955cSDouglas Gregor 
14360e11955cSDouglas Gregor       if (!AnyFileChanged) {
1437d9a30af2SDouglas Gregor         // Okay! We can re-use the precompiled preamble.
1438d9a30af2SDouglas Gregor 
1439d9a30af2SDouglas Gregor         // Set the state of the diagnostic object to mimic its state
1440d9a30af2SDouglas Gregor         // after parsing the preamble.
1441d9a30af2SDouglas Gregor         getDiagnostics().Reset();
144236e3b5c7SDouglas Gregor         ProcessWarningOptions(getDiagnostics(),
14433cc15810SDouglas Gregor                               PreambleInvocation->getDiagnosticOpts());
1444d9a30af2SDouglas Gregor         getDiagnostics().setNumWarnings(NumWarningsInPreamble);
1445d9a30af2SDouglas Gregor 
1446d9a30af2SDouglas Gregor         // Create a version of the main file buffer that is padded to
1447d9a30af2SDouglas Gregor         // buffer size we reserved when creating the preamble.
14486481ef1fSDouglas Gregor         return CreatePaddedMainFileBuffer(NewPreamble.first,
14496481ef1fSDouglas Gregor                                           PreambleReservedSize,
145032fbe312SDouglas Gregor                                           FrontendOpts.Inputs[0].File);
14514dde7498SDouglas Gregor       }
14520e11955cSDouglas Gregor     }
14534dde7498SDouglas Gregor 
1454028d3e4dSDouglas Gregor     // If we aren't allowed to rebuild the precompiled preamble, just
1455028d3e4dSDouglas Gregor     // return now.
1456028d3e4dSDouglas Gregor     if (!AllowRebuild)
1457028d3e4dSDouglas Gregor       return 0;
1458028d3e4dSDouglas Gregor 
14594dde7498SDouglas Gregor     // We can't reuse the previously-computed preamble. Build a new one.
14604dde7498SDouglas Gregor     Preamble.clear();
1461925296b4SDouglas Gregor     PreambleDiagnostics.clear();
146206b4f919STed Kremenek     erasePreambleFile(this);
1463bb420abdSDouglas Gregor     PreambleRebuildCounter = 1;
1464028d3e4dSDouglas Gregor   } else if (!AllowRebuild) {
1465028d3e4dSDouglas Gregor     // We aren't allowed to rebuild the precompiled preamble; just
1466028d3e4dSDouglas Gregor     // return now.
1467028d3e4dSDouglas Gregor     return 0;
1468bb420abdSDouglas Gregor   }
1469bb420abdSDouglas Gregor 
1470bb420abdSDouglas Gregor   // If the preamble rebuild counter > 1, it's because we previously
1471bb420abdSDouglas Gregor   // failed to build a preamble and we're not yet ready to try
1472bb420abdSDouglas Gregor   // again. Decrement the counter and return a failure.
1473bb420abdSDouglas Gregor   if (PreambleRebuildCounter > 1) {
1474bb420abdSDouglas Gregor     --PreambleRebuildCounter;
1475bb420abdSDouglas Gregor     return 0;
14764dde7498SDouglas Gregor   }
14774dde7498SDouglas Gregor 
1478e10f0e56SDouglas Gregor   // Create a temporary file for the precompiled preamble. In rare
1479e10f0e56SDouglas Gregor   // circumstances, this can fail.
1480e10f0e56SDouglas Gregor   std::string PreamblePCHPath = GetPreamblePCHPath();
1481e10f0e56SDouglas Gregor   if (PreamblePCHPath.empty()) {
1482e10f0e56SDouglas Gregor     // Try again next time.
1483e10f0e56SDouglas Gregor     PreambleRebuildCounter = 1;
1484e10f0e56SDouglas Gregor     return 0;
1485e10f0e56SDouglas Gregor   }
1486e10f0e56SDouglas Gregor 
14874dde7498SDouglas Gregor   // We did not previously compute a preamble, or it can't be reused anyway.
148816896c45SDouglas Gregor   SimpleTimer PreambleTimer(WantTiming);
148916896c45SDouglas Gregor   PreambleTimer.setOutput("Precompiling preamble");
1490be2d8c60SDouglas Gregor 
1491be2d8c60SDouglas Gregor   // Create a new buffer that stores the preamble. The buffer also contains
1492be2d8c60SDouglas Gregor   // extra space for the original contents of the file (which will be present
1493be2d8c60SDouglas Gregor   // when we actually parse the file) along with more room in case the file
1494be2d8c60SDouglas Gregor   // grows.
14954dde7498SDouglas Gregor   PreambleReservedSize = NewPreamble.first->getBufferSize();
14964dde7498SDouglas Gregor   if (PreambleReservedSize < 4096)
14973f4bea06SDouglas Gregor     PreambleReservedSize = 8191;
1498be2d8c60SDouglas Gregor   else
14994dde7498SDouglas Gregor     PreambleReservedSize *= 2;
1500be2d8c60SDouglas Gregor 
1501d9a30af2SDouglas Gregor   // Save the preamble text for later; we'll need to compare against it for
1502d9a30af2SDouglas Gregor   // subsequent reparses.
150332fbe312SDouglas Gregor   StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].File;
15047c06d866SArgyrios Kyrtzidis   Preamble.assign(FileMgr->getFile(MainFilename),
15057c06d866SArgyrios Kyrtzidis                   NewPreamble.first->getBufferStart(),
1506d9a30af2SDouglas Gregor                   NewPreamble.first->getBufferStart()
1507d9a30af2SDouglas Gregor                                                   + NewPreamble.second.first);
1508d9a30af2SDouglas Gregor   PreambleEndsAtStartOfLine = NewPreamble.second.second;
1509d9a30af2SDouglas Gregor 
1510a0734c5fSDouglas Gregor   delete PreambleBuffer;
1511a0734c5fSDouglas Gregor   PreambleBuffer
15124dde7498SDouglas Gregor     = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
151332fbe312SDouglas Gregor                                                 FrontendOpts.Inputs[0].File);
1514be2d8c60SDouglas Gregor   memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
15154dde7498SDouglas Gregor          NewPreamble.first->getBufferStart(), Preamble.size());
15164dde7498SDouglas Gregor   memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
15173f4bea06SDouglas Gregor          ' ', PreambleReservedSize - Preamble.size() - 1);
15183f4bea06SDouglas Gregor   const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
15194dde7498SDouglas Gregor 
1520be2d8c60SDouglas Gregor   // Remap the main source file to the preamble buffer.
152132fbe312SDouglas Gregor   llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File);
1522be2d8c60SDouglas Gregor   PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
1523be2d8c60SDouglas Gregor 
1524be2d8c60SDouglas Gregor   // Tell the compiler invocation to generate a temporary precompiled header.
1525be2d8c60SDouglas Gregor   FrontendOpts.ProgramAction = frontend::GeneratePCH;
1526be2d8c60SDouglas Gregor   // FIXME: Generate the precompiled header into memory?
1527e10f0e56SDouglas Gregor   FrontendOpts.OutputFile = PreamblePCHPath;
1528bb6a8818SDouglas Gregor   PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
1529bb6a8818SDouglas Gregor   PreprocessorOpts.PrecompiledPreambleBytes.second = false;
1530be2d8c60SDouglas Gregor 
1531be2d8c60SDouglas Gregor   // Create the compiler instance to use for building the precompiled preamble.
1532e2778999SDylan Noblesmith   OwningPtr<CompilerInstance> Clang(new CompilerInstance());
153384de4a17STed Kremenek 
153484de4a17STed Kremenek   // Recover resources if we crash before exiting this method.
1535022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1536022a4904STed Kremenek     CICleanup(Clang.get());
153784de4a17STed Kremenek 
15383cc15810SDouglas Gregor   Clang->setInvocation(&*PreambleInvocation);
153932fbe312SDouglas Gregor   OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
1540be2d8c60SDouglas Gregor 
15418e984da8SDouglas Gregor   // Set up diagnostics, capturing all of the diagnostics produced.
154284de4a17STed Kremenek   Clang->setDiagnostics(&getDiagnostics());
1543be2d8c60SDouglas Gregor 
1544be2d8c60SDouglas Gregor   // Create the target instance.
154584de4a17STed Kremenek   Clang->getTargetOpts().Features = TargetFeatures;
154684de4a17STed Kremenek   Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
154784de4a17STed Kremenek                                                Clang->getTargetOpts()));
154884de4a17STed Kremenek   if (!Clang->hasTarget()) {
15494dde7498SDouglas Gregor     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
15504dde7498SDouglas Gregor     Preamble.clear();
1551bb420abdSDouglas Gregor     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
1552a0734c5fSDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
1553a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
15546481ef1fSDouglas Gregor     return 0;
1555be2d8c60SDouglas Gregor   }
1556be2d8c60SDouglas Gregor 
1557be2d8c60SDouglas Gregor   // Inform the target of the language options.
1558be2d8c60SDouglas Gregor   //
1559be2d8c60SDouglas Gregor   // FIXME: We shouldn't need to do this, the target should be immutable once
1560be2d8c60SDouglas Gregor   // created. This complexity should be lifted elsewhere.
156184de4a17STed Kremenek   Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
1562be2d8c60SDouglas Gregor 
156384de4a17STed Kremenek   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1564be2d8c60SDouglas Gregor          "Invocation must have exactly one source file!");
156532fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
1566be2d8c60SDouglas Gregor          "FIXME: AST inputs not yet supported here!");
156732fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
1568be2d8c60SDouglas Gregor          "IR inputs not support here!");
1569be2d8c60SDouglas Gregor 
1570be2d8c60SDouglas Gregor   // Clear out old caches and data.
1571bb6a8818SDouglas Gregor   getDiagnostics().Reset();
157284de4a17STed Kremenek   ProcessWarningOptions(getDiagnostics(), Clang->getDiagnosticOpts());
157338bacf34SArgyrios Kyrtzidis   checkAndRemoveNonDriverDiags(StoredDiagnostics);
1574e9db88f9SDouglas Gregor   TopLevelDecls.clear();
1575e9db88f9SDouglas Gregor   TopLevelDeclsInPreamble.clear();
1576be2d8c60SDouglas Gregor 
1577be2d8c60SDouglas Gregor   // Create a file manager object to provide access to and cache the filesystem.
157884de4a17STed Kremenek   Clang->setFileManager(new FileManager(Clang->getFileSystemOpts()));
1579be2d8c60SDouglas Gregor 
1580be2d8c60SDouglas Gregor   // Create the source manager.
158184de4a17STed Kremenek   Clang->setSourceManager(new SourceManager(getDiagnostics(),
158284de4a17STed Kremenek                                             Clang->getFileManager()));
1583be2d8c60SDouglas Gregor 
1584e2778999SDylan Noblesmith   OwningPtr<PrecompilePreambleAction> Act;
158548c8cd3fSDouglas Gregor   Act.reset(new PrecompilePreambleAction(*this));
158632fbe312SDouglas Gregor   if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
15874dde7498SDouglas Gregor     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
15884dde7498SDouglas Gregor     Preamble.clear();
1589bb420abdSDouglas Gregor     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
1590a0734c5fSDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
1591a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
15926481ef1fSDouglas Gregor     return 0;
1593be2d8c60SDouglas Gregor   }
1594be2d8c60SDouglas Gregor 
1595be2d8c60SDouglas Gregor   Act->Execute();
1596be2d8c60SDouglas Gregor   Act->EndSourceFile();
1597be2d8c60SDouglas Gregor 
1598e9db88f9SDouglas Gregor   if (Diagnostics->hasErrorOccurred()) {
15994dde7498SDouglas Gregor     // There were errors parsing the preamble, so no precompiled header was
16004dde7498SDouglas Gregor     // generated. Forget that we even tried.
1601a6f74e27SDouglas Gregor     // FIXME: Should we leave a note for ourselves to try again?
16024dde7498SDouglas Gregor     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
16034dde7498SDouglas Gregor     Preamble.clear();
1604e9db88f9SDouglas Gregor     TopLevelDeclsInPreamble.clear();
1605bb420abdSDouglas Gregor     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
1606a0734c5fSDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
1607a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
16086481ef1fSDouglas Gregor     return 0;
16094dde7498SDouglas Gregor   }
16104dde7498SDouglas Gregor 
1611925296b4SDouglas Gregor   // Transfer any diagnostics generated when parsing the preamble into the set
1612925296b4SDouglas Gregor   // of preamble diagnostics.
1613925296b4SDouglas Gregor   PreambleDiagnostics.clear();
1614925296b4SDouglas Gregor   PreambleDiagnostics.insert(PreambleDiagnostics.end(),
1615067cbfa2SArgyrios Kyrtzidis                             stored_diag_afterDriver_begin(), stored_diag_end());
161638bacf34SArgyrios Kyrtzidis   checkAndRemoveNonDriverDiags(StoredDiagnostics);
1617925296b4SDouglas Gregor 
16184dde7498SDouglas Gregor   // Keep track of the preamble we precompiled.
161906b4f919STed Kremenek   setPreambleFile(this, FrontendOpts.OutputFile);
1620d9a30af2SDouglas Gregor   NumWarningsInPreamble = getDiagnostics().getNumWarnings();
16210e11955cSDouglas Gregor 
16220e11955cSDouglas Gregor   // Keep track of all of the files that the source manager knows about,
16230e11955cSDouglas Gregor   // so we can verify whether they have changed or not.
16240e11955cSDouglas Gregor   FilesInPreamble.clear();
162584de4a17STed Kremenek   SourceManager &SourceMgr = Clang->getSourceManager();
16260e11955cSDouglas Gregor   const llvm::MemoryBuffer *MainFileBuffer
16270e11955cSDouglas Gregor     = SourceMgr.getBuffer(SourceMgr.getMainFileID());
16280e11955cSDouglas Gregor   for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
16290e11955cSDouglas Gregor                                      FEnd = SourceMgr.fileinfo_end();
16300e11955cSDouglas Gregor        F != FEnd;
16310e11955cSDouglas Gregor        ++F) {
163211e6f0a6SArgyrios Kyrtzidis     const FileEntry *File = F->second->OrigEntry;
16330e11955cSDouglas Gregor     if (!File || F->second->getRawBuffer() == MainFileBuffer)
16340e11955cSDouglas Gregor       continue;
16350e11955cSDouglas Gregor 
16360e11955cSDouglas Gregor     FilesInPreamble[File->getName()]
16370e11955cSDouglas Gregor       = std::make_pair(F->second->getSize(), File->getModificationTime());
16380e11955cSDouglas Gregor   }
16390e11955cSDouglas Gregor 
1640bb420abdSDouglas Gregor   PreambleRebuildCounter = 1;
1641a0734c5fSDouglas Gregor   PreprocessorOpts.eraseRemappedFile(
1642a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
1643df7a79a9SDouglas Gregor 
1644df7a79a9SDouglas Gregor   // If the hash of top-level entities differs from the hash of the top-level
1645df7a79a9SDouglas Gregor   // entities the last time we rebuilt the preamble, clear out the completion
1646df7a79a9SDouglas Gregor   // cache.
1647df7a79a9SDouglas Gregor   if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {
1648df7a79a9SDouglas Gregor     CompletionCacheTopLevelHashValue = 0;
1649df7a79a9SDouglas Gregor     PreambleTopLevelHashValue = CurrentTopLevelHashValue;
1650df7a79a9SDouglas Gregor   }
1651df7a79a9SDouglas Gregor 
16526481ef1fSDouglas Gregor   return CreatePaddedMainFileBuffer(NewPreamble.first,
16536481ef1fSDouglas Gregor                                     PreambleReservedSize,
165432fbe312SDouglas Gregor                                     FrontendOpts.Inputs[0].File);
1655be2d8c60SDouglas Gregor }
1656aa21cc40SDouglas Gregor 
1657e9db88f9SDouglas Gregor void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
1658e9db88f9SDouglas Gregor   std::vector<Decl *> Resolved;
1659e9db88f9SDouglas Gregor   Resolved.reserve(TopLevelDeclsInPreamble.size());
1660e9db88f9SDouglas Gregor   ExternalASTSource &Source = *getASTContext().getExternalSource();
1661e9db88f9SDouglas Gregor   for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
1662e9db88f9SDouglas Gregor     // Resolve the declaration ID to an actual declaration, possibly
1663e9db88f9SDouglas Gregor     // deserializing the declaration in the process.
1664e9db88f9SDouglas Gregor     Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
1665e9db88f9SDouglas Gregor     if (D)
1666e9db88f9SDouglas Gregor       Resolved.push_back(D);
1667e9db88f9SDouglas Gregor   }
1668e9db88f9SDouglas Gregor   TopLevelDeclsInPreamble.clear();
1669e9db88f9SDouglas Gregor   TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
1670e9db88f9SDouglas Gregor }
1671e9db88f9SDouglas Gregor 
1672ac1cc934SArgyrios Kyrtzidis void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
1673ac1cc934SArgyrios Kyrtzidis   // Steal the created target, context, and preprocessor.
1674ac1cc934SArgyrios Kyrtzidis   TheSema.reset(CI.takeSema());
1675ac1cc934SArgyrios Kyrtzidis   Consumer.reset(CI.takeASTConsumer());
1676ac1cc934SArgyrios Kyrtzidis   Ctx = &CI.getASTContext();
1677ac1cc934SArgyrios Kyrtzidis   PP = &CI.getPreprocessor();
1678ac1cc934SArgyrios Kyrtzidis   CI.setSourceManager(0);
1679ac1cc934SArgyrios Kyrtzidis   CI.setFileManager(0);
1680ac1cc934SArgyrios Kyrtzidis   Target = &CI.getTarget();
1681ac1cc934SArgyrios Kyrtzidis   Reader = CI.getModuleManager();
1682ac1cc934SArgyrios Kyrtzidis }
1683ac1cc934SArgyrios Kyrtzidis 
16840e62c1ccSChris Lattner StringRef ASTUnit::getMainFileName() const {
168532fbe312SDouglas Gregor   return Invocation->getFrontendOpts().Inputs[0].File;
168616896c45SDouglas Gregor }
168716896c45SDouglas Gregor 
168835dcda79SArgyrios Kyrtzidis ASTUnit *ASTUnit::create(CompilerInvocation *CI,
1689c95d8192SDylan Noblesmith                          IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
16906d7833f1SArgyrios Kyrtzidis                          bool CaptureDiagnostics,
16916d7833f1SArgyrios Kyrtzidis                          bool UserFilesAreVolatile) {
1692e2778999SDylan Noblesmith   OwningPtr<ASTUnit> AST;
169335dcda79SArgyrios Kyrtzidis   AST.reset(new ASTUnit(false));
169467aa7db0SArgyrios Kyrtzidis   ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
169535dcda79SArgyrios Kyrtzidis   AST->Diagnostics = Diags;
16965e14d39aSTed Kremenek   AST->Invocation = CI;
1697c30dcecbSAnders Carlsson   AST->FileSystemOpts = CI->getFileSystemOpts();
16985e14d39aSTed Kremenek   AST->FileMgr = new FileManager(AST->FileSystemOpts);
16996d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
17006d7833f1SArgyrios Kyrtzidis   AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
17016d7833f1SArgyrios Kyrtzidis                                      UserFilesAreVolatile);
170235dcda79SArgyrios Kyrtzidis 
170335dcda79SArgyrios Kyrtzidis   return AST.take();
170435dcda79SArgyrios Kyrtzidis }
170535dcda79SArgyrios Kyrtzidis 
1706f1f67597SArgyrios Kyrtzidis ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
1707c95d8192SDylan Noblesmith                               IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
17081ac5da10SArgyrios Kyrtzidis                                              ASTFrontendAction *Action,
1709b11f5a4cSArgyrios Kyrtzidis                                              ASTUnit *Unit,
1710b11f5a4cSArgyrios Kyrtzidis                                              bool Persistent,
1711b11f5a4cSArgyrios Kyrtzidis                                              StringRef ResourceFilesPath,
1712b11f5a4cSArgyrios Kyrtzidis                                              bool OnlyLocalDecls,
1713b11f5a4cSArgyrios Kyrtzidis                                              bool CaptureDiagnostics,
1714b11f5a4cSArgyrios Kyrtzidis                                              bool PrecompilePreamble,
1715ac1cc934SArgyrios Kyrtzidis                                              bool CacheCodeCompletionResults,
17163292d06aSDmitri Gribenko                                     bool IncludeBriefCommentsInCodeCompletion,
17176d7833f1SArgyrios Kyrtzidis                                              bool UserFilesAreVolatile,
1718ac1cc934SArgyrios Kyrtzidis                                              OwningPtr<ASTUnit> *ErrAST) {
1719f1f67597SArgyrios Kyrtzidis   assert(CI && "A CompilerInvocation is required");
1720f1f67597SArgyrios Kyrtzidis 
1721e2778999SDylan Noblesmith   OwningPtr<ASTUnit> OwnAST;
17221ac5da10SArgyrios Kyrtzidis   ASTUnit *AST = Unit;
17231ac5da10SArgyrios Kyrtzidis   if (!AST) {
1724f1f67597SArgyrios Kyrtzidis     // Create the AST unit.
17256d7833f1SArgyrios Kyrtzidis     OwnAST.reset(create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile));
17261ac5da10SArgyrios Kyrtzidis     AST = OwnAST.get();
17271ac5da10SArgyrios Kyrtzidis   }
17281ac5da10SArgyrios Kyrtzidis 
1729b11f5a4cSArgyrios Kyrtzidis   if (!ResourceFilesPath.empty()) {
1730b11f5a4cSArgyrios Kyrtzidis     // Override the resources path.
1731b11f5a4cSArgyrios Kyrtzidis     CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
1732b11f5a4cSArgyrios Kyrtzidis   }
1733b11f5a4cSArgyrios Kyrtzidis   AST->OnlyLocalDecls = OnlyLocalDecls;
1734b11f5a4cSArgyrios Kyrtzidis   AST->CaptureDiagnostics = CaptureDiagnostics;
1735b11f5a4cSArgyrios Kyrtzidis   if (PrecompilePreamble)
1736b11f5a4cSArgyrios Kyrtzidis     AST->PreambleRebuildCounter = 2;
173769f74f80SDouglas Gregor   AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
1738b11f5a4cSArgyrios Kyrtzidis   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
17393292d06aSDmitri Gribenko   AST->IncludeBriefCommentsInCodeCompletion
17403292d06aSDmitri Gribenko     = IncludeBriefCommentsInCodeCompletion;
1741f1f67597SArgyrios Kyrtzidis 
1742f1f67597SArgyrios Kyrtzidis   // Recover resources if we crash before exiting this method.
1743f1f67597SArgyrios Kyrtzidis   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
17441ac5da10SArgyrios Kyrtzidis     ASTUnitCleanup(OwnAST.get());
17459c902b55SDavid Blaikie   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
17469c902b55SDavid Blaikie     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
1747f1f67597SArgyrios Kyrtzidis     DiagCleanup(Diags.getPtr());
1748f1f67597SArgyrios Kyrtzidis 
1749f1f67597SArgyrios Kyrtzidis   // We'll manage file buffers ourselves.
1750f1f67597SArgyrios Kyrtzidis   CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1751f1f67597SArgyrios Kyrtzidis   CI->getFrontendOpts().DisableFree = false;
1752f1f67597SArgyrios Kyrtzidis   ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
1753f1f67597SArgyrios Kyrtzidis 
1754f1f67597SArgyrios Kyrtzidis   // Save the target features.
1755f1f67597SArgyrios Kyrtzidis   AST->TargetFeatures = CI->getTargetOpts().Features;
1756f1f67597SArgyrios Kyrtzidis 
1757f1f67597SArgyrios Kyrtzidis   // Create the compiler instance to use for building the AST.
1758e2778999SDylan Noblesmith   OwningPtr<CompilerInstance> Clang(new CompilerInstance());
1759f1f67597SArgyrios Kyrtzidis 
1760f1f67597SArgyrios Kyrtzidis   // Recover resources if we crash before exiting this method.
1761f1f67597SArgyrios Kyrtzidis   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1762f1f67597SArgyrios Kyrtzidis     CICleanup(Clang.get());
1763f1f67597SArgyrios Kyrtzidis 
1764f1f67597SArgyrios Kyrtzidis   Clang->setInvocation(CI);
176532fbe312SDouglas Gregor   AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
1766f1f67597SArgyrios Kyrtzidis 
1767f1f67597SArgyrios Kyrtzidis   // Set up diagnostics, capturing any diagnostics that would
1768f1f67597SArgyrios Kyrtzidis   // otherwise be dropped.
1769f1f67597SArgyrios Kyrtzidis   Clang->setDiagnostics(&AST->getDiagnostics());
1770f1f67597SArgyrios Kyrtzidis 
1771f1f67597SArgyrios Kyrtzidis   // Create the target instance.
1772f1f67597SArgyrios Kyrtzidis   Clang->getTargetOpts().Features = AST->TargetFeatures;
1773f1f67597SArgyrios Kyrtzidis   Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
1774f1f67597SArgyrios Kyrtzidis                    Clang->getTargetOpts()));
1775f1f67597SArgyrios Kyrtzidis   if (!Clang->hasTarget())
1776f1f67597SArgyrios Kyrtzidis     return 0;
1777f1f67597SArgyrios Kyrtzidis 
1778f1f67597SArgyrios Kyrtzidis   // Inform the target of the language options.
1779f1f67597SArgyrios Kyrtzidis   //
1780f1f67597SArgyrios Kyrtzidis   // FIXME: We shouldn't need to do this, the target should be immutable once
1781f1f67597SArgyrios Kyrtzidis   // created. This complexity should be lifted elsewhere.
1782f1f67597SArgyrios Kyrtzidis   Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
1783f1f67597SArgyrios Kyrtzidis 
1784f1f67597SArgyrios Kyrtzidis   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1785f1f67597SArgyrios Kyrtzidis          "Invocation must have exactly one source file!");
178632fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
1787f1f67597SArgyrios Kyrtzidis          "FIXME: AST inputs not yet supported here!");
178832fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
1789f1f67597SArgyrios Kyrtzidis          "IR inputs not supported here!");
1790f1f67597SArgyrios Kyrtzidis 
1791f1f67597SArgyrios Kyrtzidis   // Configure the various subsystems.
1792f1f67597SArgyrios Kyrtzidis   AST->TheSema.reset();
1793f1f67597SArgyrios Kyrtzidis   AST->Ctx = 0;
1794f1f67597SArgyrios Kyrtzidis   AST->PP = 0;
1795244ce8b2SArgyrios Kyrtzidis   AST->Reader = 0;
1796f1f67597SArgyrios Kyrtzidis 
1797f1f67597SArgyrios Kyrtzidis   // Create a file manager object to provide access to and cache the filesystem.
1798f1f67597SArgyrios Kyrtzidis   Clang->setFileManager(&AST->getFileManager());
1799f1f67597SArgyrios Kyrtzidis 
1800f1f67597SArgyrios Kyrtzidis   // Create the source manager.
1801f1f67597SArgyrios Kyrtzidis   Clang->setSourceManager(&AST->getSourceManager());
1802f1f67597SArgyrios Kyrtzidis 
1803f1f67597SArgyrios Kyrtzidis   ASTFrontendAction *Act = Action;
1804f1f67597SArgyrios Kyrtzidis 
1805e2778999SDylan Noblesmith   OwningPtr<TopLevelDeclTrackerAction> TrackerAct;
1806f1f67597SArgyrios Kyrtzidis   if (!Act) {
1807f1f67597SArgyrios Kyrtzidis     TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));
1808f1f67597SArgyrios Kyrtzidis     Act = TrackerAct.get();
1809f1f67597SArgyrios Kyrtzidis   }
1810f1f67597SArgyrios Kyrtzidis 
1811f1f67597SArgyrios Kyrtzidis   // Recover resources if we crash before exiting this method.
1812f1f67597SArgyrios Kyrtzidis   llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
1813f1f67597SArgyrios Kyrtzidis     ActCleanup(TrackerAct.get());
1814f1f67597SArgyrios Kyrtzidis 
1815ac1cc934SArgyrios Kyrtzidis   if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
1816ac1cc934SArgyrios Kyrtzidis     AST->transferASTDataFromCompilerInstance(*Clang);
1817ac1cc934SArgyrios Kyrtzidis     if (OwnAST && ErrAST)
1818ac1cc934SArgyrios Kyrtzidis       ErrAST->swap(OwnAST);
1819ac1cc934SArgyrios Kyrtzidis 
1820f1f67597SArgyrios Kyrtzidis     return 0;
1821ac1cc934SArgyrios Kyrtzidis   }
1822f1f67597SArgyrios Kyrtzidis 
1823b11f5a4cSArgyrios Kyrtzidis   if (Persistent && !TrackerAct) {
1824b11f5a4cSArgyrios Kyrtzidis     Clang->getPreprocessor().addPPCallbacks(
1825b11f5a4cSArgyrios Kyrtzidis      new MacroDefinitionTrackerPPCallbacks(AST->getCurrentTopLevelHashValue()));
1826b11f5a4cSArgyrios Kyrtzidis     std::vector<ASTConsumer*> Consumers;
1827b11f5a4cSArgyrios Kyrtzidis     if (Clang->hasASTConsumer())
1828b11f5a4cSArgyrios Kyrtzidis       Consumers.push_back(Clang->takeASTConsumer());
1829b11f5a4cSArgyrios Kyrtzidis     Consumers.push_back(new TopLevelDeclTrackerConsumer(*AST,
1830b11f5a4cSArgyrios Kyrtzidis                                            AST->getCurrentTopLevelHashValue()));
1831b11f5a4cSArgyrios Kyrtzidis     Clang->setASTConsumer(new MultiplexConsumer(Consumers));
1832b11f5a4cSArgyrios Kyrtzidis   }
18331416e17cSArgyrios Kyrtzidis   if (!Act->Execute()) {
18341416e17cSArgyrios Kyrtzidis     AST->transferASTDataFromCompilerInstance(*Clang);
18351416e17cSArgyrios Kyrtzidis     if (OwnAST && ErrAST)
18361416e17cSArgyrios Kyrtzidis       ErrAST->swap(OwnAST);
18371416e17cSArgyrios Kyrtzidis 
18381416e17cSArgyrios Kyrtzidis     return 0;
18391416e17cSArgyrios Kyrtzidis   }
1840f1f67597SArgyrios Kyrtzidis 
1841f1f67597SArgyrios Kyrtzidis   // Steal the created target, context, and preprocessor.
1842ac1cc934SArgyrios Kyrtzidis   AST->transferASTDataFromCompilerInstance(*Clang);
1843f1f67597SArgyrios Kyrtzidis 
1844f1f67597SArgyrios Kyrtzidis   Act->EndSourceFile();
1845f1f67597SArgyrios Kyrtzidis 
18461ac5da10SArgyrios Kyrtzidis   if (OwnAST)
18471ac5da10SArgyrios Kyrtzidis     return OwnAST.take();
18481ac5da10SArgyrios Kyrtzidis   else
18491ac5da10SArgyrios Kyrtzidis     return AST;
1850f1f67597SArgyrios Kyrtzidis }
1851f1f67597SArgyrios Kyrtzidis 
18527bb8af61SDouglas Gregor bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
18537bb8af61SDouglas Gregor   if (!Invocation)
18547bb8af61SDouglas Gregor     return true;
18557bb8af61SDouglas Gregor 
18567bb8af61SDouglas Gregor   // We'll manage file buffers ourselves.
18577bb8af61SDouglas Gregor   Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
18587bb8af61SDouglas Gregor   Invocation->getFrontendOpts().DisableFree = false;
1859345c1bcbSDouglas Gregor   ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
18607bb8af61SDouglas Gregor 
1861ffd6dc43SDouglas Gregor   // Save the target features.
1862ffd6dc43SDouglas Gregor   TargetFeatures = Invocation->getTargetOpts().Features;
1863ffd6dc43SDouglas Gregor 
18647bb8af61SDouglas Gregor   llvm::MemoryBuffer *OverrideMainBuffer = 0;
1865f5a18546SDouglas Gregor   if (PrecompilePreamble) {
1866c6592929SDouglas Gregor     PreambleRebuildCounter = 2;
18677bb8af61SDouglas Gregor     OverrideMainBuffer
18687bb8af61SDouglas Gregor       = getMainBufferWithPrecompiledPreamble(*Invocation);
18697bb8af61SDouglas Gregor   }
18707bb8af61SDouglas Gregor 
187116896c45SDouglas Gregor   SimpleTimer ParsingTimer(WantTiming);
187216896c45SDouglas Gregor   ParsingTimer.setOutput("Parsing " + getMainFileName());
18737bb8af61SDouglas Gregor 
1874022a4904STed Kremenek   // Recover resources if we crash before exiting this method.
1875022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
1876022a4904STed Kremenek     MemBufferCleanup(OverrideMainBuffer);
1877022a4904STed Kremenek 
187816896c45SDouglas Gregor   return Parse(OverrideMainBuffer);
18797bb8af61SDouglas Gregor }
18807bb8af61SDouglas Gregor 
1881aa21cc40SDouglas Gregor ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
1882c95d8192SDylan Noblesmith                               IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
1883aa21cc40SDouglas Gregor                                              bool OnlyLocalDecls,
1884be2d8c60SDouglas Gregor                                              bool CaptureDiagnostics,
1885028d3e4dSDouglas Gregor                                              bool PrecompilePreamble,
188669f74f80SDouglas Gregor                                              TranslationUnitKind TUKind,
18873292d06aSDmitri Gribenko                                              bool CacheCodeCompletionResults,
18886d7833f1SArgyrios Kyrtzidis                                     bool IncludeBriefCommentsInCodeCompletion,
18896d7833f1SArgyrios Kyrtzidis                                              bool UserFilesAreVolatile) {
1890aa21cc40SDouglas Gregor   // Create the AST unit.
1891e2778999SDylan Noblesmith   OwningPtr<ASTUnit> AST;
1892aa21cc40SDouglas Gregor   AST.reset(new ASTUnit(false));
1893345c1bcbSDouglas Gregor   ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
1894aa21cc40SDouglas Gregor   AST->Diagnostics = Diags;
1895aa21cc40SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
189644c6ee77SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
189769f74f80SDouglas Gregor   AST->TUKind = TUKind;
1898b14904c4SDouglas Gregor   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
18993292d06aSDmitri Gribenko   AST->IncludeBriefCommentsInCodeCompletion
19003292d06aSDmitri Gribenko     = IncludeBriefCommentsInCodeCompletion;
19015e14d39aSTed Kremenek   AST->Invocation = CI;
19026d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
1903aa21cc40SDouglas Gregor 
19044422bfeaSTed Kremenek   // Recover resources if we crash before exiting this method.
1905022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1906022a4904STed Kremenek     ASTUnitCleanup(AST.get());
19079c902b55SDavid Blaikie   llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
19089c902b55SDavid Blaikie     llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
1909022a4904STed Kremenek     DiagCleanup(Diags.getPtr());
19104422bfeaSTed Kremenek 
19117bb8af61SDouglas Gregor   return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take();
1912764c0820SDaniel Dunbar }
191355a17b66SDaniel Dunbar 
191455a17b66SDaniel Dunbar ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
191555a17b66SDaniel Dunbar                                       const char **ArgEnd,
1916c95d8192SDylan Noblesmith                                     IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
19170e62c1ccSChris Lattner                                       StringRef ResourceFilesPath,
191855a17b66SDaniel Dunbar                                       bool OnlyLocalDecls,
191944c6ee77SDouglas Gregor                                       bool CaptureDiagnostics,
1920aa98ed9aSDouglas Gregor                                       RemappedFile *RemappedFiles,
192133cdd810SDouglas Gregor                                       unsigned NumRemappedFiles,
192297d3a38cSArgyrios Kyrtzidis                                       bool RemappedFilesKeepOriginalName,
1923028d3e4dSDouglas Gregor                                       bool PrecompilePreamble,
192469f74f80SDouglas Gregor                                       TranslationUnitKind TUKind,
19254a280ff4SArgyrios Kyrtzidis                                       bool CacheCodeCompletionResults,
19263292d06aSDmitri Gribenko                                       bool IncludeBriefCommentsInCodeCompletion,
1927ac1cc934SArgyrios Kyrtzidis                                       bool AllowPCHWithCompilerErrors,
19286e92251fSErik Verbruggen                                       bool SkipFunctionBodies,
19296d7833f1SArgyrios Kyrtzidis                                       bool UserFilesAreVolatile,
1930ac1cc934SArgyrios Kyrtzidis                                       OwningPtr<ASTUnit> *ErrAST) {
19317f95d26eSDouglas Gregor   if (!Diags.getPtr()) {
1932d03e823fSDouglas Gregor     // No diagnostics engine was provided, so create our own diagnostics object
1933d03e823fSDouglas Gregor     // with the default options.
1934d03e823fSDouglas Gregor     DiagnosticOptions DiagOpts;
1935345c1bcbSDouglas Gregor     Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin,
1936345c1bcbSDouglas Gregor                                                 ArgBegin);
1937d03e823fSDouglas Gregor   }
1938d03e823fSDouglas Gregor 
19390e62c1ccSChris Lattner   SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
19407bb8af61SDouglas Gregor 
1941c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<CompilerInvocation> CI;
194244c6ee77SDouglas Gregor 
19437bb8af61SDouglas Gregor   {
1944925296b4SDouglas Gregor 
194544c6ee77SDouglas Gregor     CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
19467bb8af61SDouglas Gregor                                       StoredDiagnostics);
19477bb8af61SDouglas Gregor 
19485cf423ecSArgyrios Kyrtzidis     CI = clang::createInvocationFromCommandLine(
1949717d7eddSFrits van Bommel                                            llvm::makeArrayRef(ArgBegin, ArgEnd),
1950f606b82eSArgyrios Kyrtzidis                                            Diags);
1951f606b82eSArgyrios Kyrtzidis     if (!CI)
1952bc1f48f6SArgyrios Kyrtzidis       return 0;
1953bc1f48f6SArgyrios Kyrtzidis   }
1954bc1f48f6SArgyrios Kyrtzidis 
1955aa98ed9aSDouglas Gregor   // Override any files that need remapping
195611e6f0a6SArgyrios Kyrtzidis   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
195711e6f0a6SArgyrios Kyrtzidis     FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
195811e6f0a6SArgyrios Kyrtzidis     if (const llvm::MemoryBuffer *
195911e6f0a6SArgyrios Kyrtzidis             memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
196011e6f0a6SArgyrios Kyrtzidis       CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, memBuf);
196111e6f0a6SArgyrios Kyrtzidis     } else {
196211e6f0a6SArgyrios Kyrtzidis       const char *fname = fileOrBuf.get<const char *>();
196311e6f0a6SArgyrios Kyrtzidis       CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, fname);
196411e6f0a6SArgyrios Kyrtzidis     }
196511e6f0a6SArgyrios Kyrtzidis   }
19664a280ff4SArgyrios Kyrtzidis   PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
19674a280ff4SArgyrios Kyrtzidis   PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
19684a280ff4SArgyrios Kyrtzidis   PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
1969aa98ed9aSDouglas Gregor 
1970a5a166d0SDaniel Dunbar   // Override the resources path.
19716b03ecefSDaniel Dunbar   CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
197255a17b66SDaniel Dunbar 
19736e92251fSErik Verbruggen   CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies;
19746e92251fSErik Verbruggen 
19757bb8af61SDouglas Gregor   // Create the AST unit.
1976e2778999SDylan Noblesmith   OwningPtr<ASTUnit> AST;
19777bb8af61SDouglas Gregor   AST.reset(new ASTUnit(false));
1978345c1bcbSDouglas Gregor   ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics);
19797bb8af61SDouglas Gregor   AST->Diagnostics = Diags;
198025047602STed Kremenek   Diags = 0; // Zero out now to ease cleanup during crash recovery.
1981c30dcecbSAnders Carlsson   AST->FileSystemOpts = CI->getFileSystemOpts();
19825e14d39aSTed Kremenek   AST->FileMgr = new FileManager(AST->FileSystemOpts);
19837bb8af61SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
198444c6ee77SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
198569f74f80SDouglas Gregor   AST->TUKind = TUKind;
19867bb8af61SDouglas Gregor   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
19873292d06aSDmitri Gribenko   AST->IncludeBriefCommentsInCodeCompletion
19883292d06aSDmitri Gribenko     = IncludeBriefCommentsInCodeCompletion;
19896d7833f1SArgyrios Kyrtzidis   AST->UserFilesAreVolatile = UserFilesAreVolatile;
19907bb8af61SDouglas Gregor   AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
19917bb8af61SDouglas Gregor   AST->StoredDiagnostics.swap(StoredDiagnostics);
19925e14d39aSTed Kremenek   AST->Invocation = CI;
199325047602STed Kremenek   CI = 0; // Zero out now to ease cleanup during crash recovery.
19944422bfeaSTed Kremenek 
19954422bfeaSTed Kremenek   // Recover resources if we crash before exiting this method.
1996022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1997022a4904STed Kremenek     ASTUnitCleanup(AST.get());
19984422bfeaSTed Kremenek 
1999ac1cc934SArgyrios Kyrtzidis   if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) {
2000ac1cc934SArgyrios Kyrtzidis     // Some error occurred, if caller wants to examine diagnostics, pass it the
2001ac1cc934SArgyrios Kyrtzidis     // ASTUnit.
2002ac1cc934SArgyrios Kyrtzidis     if (ErrAST) {
2003ac1cc934SArgyrios Kyrtzidis       AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
2004ac1cc934SArgyrios Kyrtzidis       ErrAST->swap(AST);
2005ac1cc934SArgyrios Kyrtzidis     }
2006ac1cc934SArgyrios Kyrtzidis     return 0;
2007ac1cc934SArgyrios Kyrtzidis   }
2008ac1cc934SArgyrios Kyrtzidis 
2009ac1cc934SArgyrios Kyrtzidis   return AST.take();
201055a17b66SDaniel Dunbar }
2011aa21cc40SDouglas Gregor 
2012aa21cc40SDouglas Gregor bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
20135e14d39aSTed Kremenek   if (!Invocation)
2014aa21cc40SDouglas Gregor     return true;
2015aa21cc40SDouglas Gregor 
2016e54568d6SArgyrios Kyrtzidis   clearFileLevelDecls();
2017e54568d6SArgyrios Kyrtzidis 
201816896c45SDouglas Gregor   SimpleTimer ParsingTimer(WantTiming);
201916896c45SDouglas Gregor   ParsingTimer.setOutput("Reparsing " + getMainFileName());
202015ba0b34SDouglas Gregor 
20210e11955cSDouglas Gregor   // Remap files.
20227b02b583SDouglas Gregor   PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
2023606c4ac3SDouglas Gregor   PPOpts.DisableStatCache = true;
20247b02b583SDouglas Gregor   for (PreprocessorOptions::remapped_file_buffer_iterator
20257b02b583SDouglas Gregor          R = PPOpts.remapped_file_buffer_begin(),
20267b02b583SDouglas Gregor          REnd = PPOpts.remapped_file_buffer_end();
20277b02b583SDouglas Gregor        R != REnd;
20287b02b583SDouglas Gregor        ++R) {
20297b02b583SDouglas Gregor     delete R->second;
20307b02b583SDouglas Gregor   }
20310e11955cSDouglas Gregor   Invocation->getPreprocessorOpts().clearRemappedFiles();
203211e6f0a6SArgyrios Kyrtzidis   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
203311e6f0a6SArgyrios Kyrtzidis     FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
203411e6f0a6SArgyrios Kyrtzidis     if (const llvm::MemoryBuffer *
203511e6f0a6SArgyrios Kyrtzidis             memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
20360e11955cSDouglas Gregor       Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
203711e6f0a6SArgyrios Kyrtzidis                                                         memBuf);
203811e6f0a6SArgyrios Kyrtzidis     } else {
203911e6f0a6SArgyrios Kyrtzidis       const char *fname = fileOrBuf.get<const char *>();
204011e6f0a6SArgyrios Kyrtzidis       Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
204111e6f0a6SArgyrios Kyrtzidis                                                         fname);
204211e6f0a6SArgyrios Kyrtzidis     }
204311e6f0a6SArgyrios Kyrtzidis   }
20440e11955cSDouglas Gregor 
2045bb420abdSDouglas Gregor   // If we have a preamble file lying around, or if we might try to
2046bb420abdSDouglas Gregor   // build a precompiled preamble, do so now.
20476481ef1fSDouglas Gregor   llvm::MemoryBuffer *OverrideMainBuffer = 0;
204806b4f919STed Kremenek   if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0)
2049b97b666cSDouglas Gregor     OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
20504dde7498SDouglas Gregor 
2051aa21cc40SDouglas Gregor   // Clear out the diagnostics state.
2052aa21cc40SDouglas Gregor   getDiagnostics().Reset();
205336e3b5c7SDouglas Gregor   ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
2054462ff35dSArgyrios Kyrtzidis   if (OverrideMainBuffer)
2055462ff35dSArgyrios Kyrtzidis     getDiagnostics().setNumWarnings(NumWarningsInPreamble);
2056aa21cc40SDouglas Gregor 
20574dde7498SDouglas Gregor   // Parse the sources
20586481ef1fSDouglas Gregor   bool Result = Parse(OverrideMainBuffer);
2059df7a79a9SDouglas Gregor 
20603689337cSArgyrios Kyrtzidis   // If we're caching global code-completion results, and the top-level
20613689337cSArgyrios Kyrtzidis   // declarations have changed, clear out the code-completion cache.
20623689337cSArgyrios Kyrtzidis   if (!Result && ShouldCacheCodeCompletionResults &&
20633689337cSArgyrios Kyrtzidis       CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
20643689337cSArgyrios Kyrtzidis     CacheCodeCompletionResults();
20653689337cSArgyrios Kyrtzidis 
20669d7c0fefSArgyrios Kyrtzidis   // We now need to clear out the completion info related to this translation
20679d7c0fefSArgyrios Kyrtzidis   // unit; it'll be recreated if necessary.
20689d7c0fefSArgyrios Kyrtzidis   CCTUInfo.reset();
20693f35bb2dSDouglas Gregor 
20704dde7498SDouglas Gregor   return Result;
2071aa21cc40SDouglas Gregor }
20728e984da8SDouglas Gregor 
2073b14904c4SDouglas Gregor //----------------------------------------------------------------------------//
2074b14904c4SDouglas Gregor // Code completion
2075b14904c4SDouglas Gregor //----------------------------------------------------------------------------//
2076b14904c4SDouglas Gregor 
2077b14904c4SDouglas Gregor namespace {
2078b14904c4SDouglas Gregor   /// \brief Code completion consumer that combines the cached code-completion
2079b14904c4SDouglas Gregor   /// results from an ASTUnit with the code-completion results provided to it,
2080b14904c4SDouglas Gregor   /// then passes the result on to
2081b14904c4SDouglas Gregor   class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
2082697cc9e6SRichard Smith     uint64_t NormalContexts;
2083b14904c4SDouglas Gregor     ASTUnit &AST;
2084b14904c4SDouglas Gregor     CodeCompleteConsumer &Next;
2085b14904c4SDouglas Gregor 
2086b14904c4SDouglas Gregor   public:
2087b14904c4SDouglas Gregor     AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
20883292d06aSDmitri Gribenko                                   const CodeCompleteOptions &CodeCompleteOpts)
20893292d06aSDmitri Gribenko       : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
20903292d06aSDmitri Gribenko         AST(AST), Next(Next)
2091b14904c4SDouglas Gregor     {
2092b14904c4SDouglas Gregor       // Compute the set of contexts in which we will look when we don't have
2093b14904c4SDouglas Gregor       // any information about the specific context.
2094b14904c4SDouglas Gregor       NormalContexts
2095697cc9e6SRichard Smith         = (1LL << CodeCompletionContext::CCC_TopLevel)
2096697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCInterface)
2097697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
2098697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
2099697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Statement)
2100697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Expression)
2101697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
2102697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_DotMemberAccess)
2103697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)
2104697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)
2105697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ObjCProtocolName)
2106697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
2107697cc9e6SRichard Smith         | (1LL << CodeCompletionContext::CCC_Recovery);
2108b14904c4SDouglas Gregor 
2109bbafb8a7SDavid Blaikie       if (AST.getASTContext().getLangOpts().CPlusPlus)
2110697cc9e6SRichard Smith         NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)
2111697cc9e6SRichard Smith                        |  (1LL << CodeCompletionContext::CCC_UnionTag)
2112697cc9e6SRichard Smith                        |  (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
2113b14904c4SDouglas Gregor     }
2114b14904c4SDouglas Gregor 
2115b14904c4SDouglas Gregor     virtual void ProcessCodeCompleteResults(Sema &S,
2116b14904c4SDouglas Gregor                                             CodeCompletionContext Context,
2117276321a9SJohn McCall                                             CodeCompletionResult *Results,
2118d46cf182SDouglas Gregor                                             unsigned NumResults);
2119d46cf182SDouglas Gregor 
2120d46cf182SDouglas Gregor     virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
2121d46cf182SDouglas Gregor                                            OverloadCandidate *Candidates,
2122d46cf182SDouglas Gregor                                            unsigned NumCandidates) {
2123d46cf182SDouglas Gregor       Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
2124d46cf182SDouglas Gregor     }
2125b278aafbSDouglas Gregor 
2126bcbf46c7SDouglas Gregor     virtual CodeCompletionAllocator &getAllocator() {
2127b278aafbSDouglas Gregor       return Next.getAllocator();
2128b278aafbSDouglas Gregor     }
21299d7c0fefSArgyrios Kyrtzidis 
21309d7c0fefSArgyrios Kyrtzidis     virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() {
21319d7c0fefSArgyrios Kyrtzidis       return Next.getCodeCompletionTUInfo();
21329d7c0fefSArgyrios Kyrtzidis     }
2133d46cf182SDouglas Gregor   };
2134d46cf182SDouglas Gregor }
2135d46cf182SDouglas Gregor 
21366199f2d1SDouglas Gregor /// \brief Helper function that computes which global names are hidden by the
21376199f2d1SDouglas Gregor /// local code-completion results.
21386a15337dSTed Kremenek static void CalculateHiddenNames(const CodeCompletionContext &Context,
2139276321a9SJohn McCall                                  CodeCompletionResult *Results,
21406199f2d1SDouglas Gregor                                  unsigned NumResults,
21416199f2d1SDouglas Gregor                                  ASTContext &Ctx,
21426a15337dSTed Kremenek                           llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){
21436199f2d1SDouglas Gregor   bool OnlyTagNames = false;
21446199f2d1SDouglas Gregor   switch (Context.getKind()) {
21450ac41389SDouglas Gregor   case CodeCompletionContext::CCC_Recovery:
21466199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_TopLevel:
21476199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCInterface:
21486199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCImplementation:
21496199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCIvarList:
21506199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ClassStructUnion:
21516199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Statement:
21526199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Expression:
21536199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCMessageReceiver:
21542132584dSDouglas Gregor   case CodeCompletionContext::CCC_DotMemberAccess:
21552132584dSDouglas Gregor   case CodeCompletionContext::CCC_ArrowMemberAccess:
21562132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCPropertyAccess:
21576199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Namespace:
21586199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Type:
2159c49f5b2fSDouglas Gregor   case CodeCompletionContext::CCC_Name:
2160c49f5b2fSDouglas Gregor   case CodeCompletionContext::CCC_PotentiallyQualifiedName:
21615e35d591SDouglas Gregor   case CodeCompletionContext::CCC_ParenthesizedExpression:
21622c595adfSDouglas Gregor   case CodeCompletionContext::CCC_ObjCInterfaceName:
21636199f2d1SDouglas Gregor     break;
21646199f2d1SDouglas Gregor 
21656199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_EnumTag:
21666199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_UnionTag:
21676199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ClassOrStructTag:
21686199f2d1SDouglas Gregor     OnlyTagNames = true;
21696199f2d1SDouglas Gregor     break;
21706199f2d1SDouglas Gregor 
21716199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCProtocolName:
217212785108SDouglas Gregor   case CodeCompletionContext::CCC_MacroName:
217312785108SDouglas Gregor   case CodeCompletionContext::CCC_MacroNameUse:
2174ec00a268SDouglas Gregor   case CodeCompletionContext::CCC_PreprocessorExpression:
21750de55cecSDouglas Gregor   case CodeCompletionContext::CCC_PreprocessorDirective:
2176ea14705cSDouglas Gregor   case CodeCompletionContext::CCC_NaturalLanguage:
217767c692ccSDouglas Gregor   case CodeCompletionContext::CCC_SelectorName:
217828c7843eSDouglas Gregor   case CodeCompletionContext::CCC_TypeQualifiers:
21790ac41389SDouglas Gregor   case CodeCompletionContext::CCC_Other:
21803a69eafaSDouglas Gregor   case CodeCompletionContext::CCC_OtherWithMacros:
21812132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCInstanceMessage:
21822132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCClassMessage:
21832132584dSDouglas Gregor   case CodeCompletionContext::CCC_ObjCCategoryName:
21840de55cecSDouglas Gregor     // We're looking for nothing, or we're looking for names that cannot
21850de55cecSDouglas Gregor     // be hidden.
21866199f2d1SDouglas Gregor     return;
21876199f2d1SDouglas Gregor   }
21886199f2d1SDouglas Gregor 
2189276321a9SJohn McCall   typedef CodeCompletionResult Result;
21906199f2d1SDouglas Gregor   for (unsigned I = 0; I != NumResults; ++I) {
21916199f2d1SDouglas Gregor     if (Results[I].Kind != Result::RK_Declaration)
21926199f2d1SDouglas Gregor       continue;
21936199f2d1SDouglas Gregor 
21946199f2d1SDouglas Gregor     unsigned IDNS
21956199f2d1SDouglas Gregor       = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
21966199f2d1SDouglas Gregor 
21976199f2d1SDouglas Gregor     bool Hiding = false;
21986199f2d1SDouglas Gregor     if (OnlyTagNames)
21996199f2d1SDouglas Gregor       Hiding = (IDNS & Decl::IDNS_Tag);
22006199f2d1SDouglas Gregor     else {
22016199f2d1SDouglas Gregor       unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
22026199f2d1SDouglas Gregor                              Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
22036199f2d1SDouglas Gregor                              Decl::IDNS_NonMemberOperator);
2204bbafb8a7SDavid Blaikie       if (Ctx.getLangOpts().CPlusPlus)
22056199f2d1SDouglas Gregor         HiddenIDNS |= Decl::IDNS_Tag;
22066199f2d1SDouglas Gregor       Hiding = (IDNS & HiddenIDNS);
22076199f2d1SDouglas Gregor     }
22086199f2d1SDouglas Gregor 
22096199f2d1SDouglas Gregor     if (!Hiding)
22106199f2d1SDouglas Gregor       continue;
22116199f2d1SDouglas Gregor 
22126199f2d1SDouglas Gregor     DeclarationName Name = Results[I].Declaration->getDeclName();
22136199f2d1SDouglas Gregor     if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
22146199f2d1SDouglas Gregor       HiddenNames.insert(Identifier->getName());
22156199f2d1SDouglas Gregor     else
22166199f2d1SDouglas Gregor       HiddenNames.insert(Name.getAsString());
22176199f2d1SDouglas Gregor   }
22186199f2d1SDouglas Gregor }
22196199f2d1SDouglas Gregor 
22206199f2d1SDouglas Gregor 
2221d46cf182SDouglas Gregor void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
2222d46cf182SDouglas Gregor                                             CodeCompletionContext Context,
2223276321a9SJohn McCall                                             CodeCompletionResult *Results,
2224b14904c4SDouglas Gregor                                             unsigned NumResults) {
2225b14904c4SDouglas Gregor   // Merge the results we were given with the results we cached.
2226b14904c4SDouglas Gregor   bool AddedResult = false;
2227697cc9e6SRichard Smith   uint64_t InContexts =
2228697cc9e6SRichard Smith       Context.getKind() == CodeCompletionContext::CCC_Recovery
2229697cc9e6SRichard Smith         ? NormalContexts : (1LL << Context.getKind());
22306199f2d1SDouglas Gregor   // Contains the set of names that are hidden by "local" completion results.
22316a15337dSTed Kremenek   llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
2232276321a9SJohn McCall   typedef CodeCompletionResult Result;
22330e62c1ccSChris Lattner   SmallVector<Result, 8> AllResults;
2234b14904c4SDouglas Gregor   for (ASTUnit::cached_completion_iterator
2235b14904c4SDouglas Gregor             C = AST.cached_completion_begin(),
2236b14904c4SDouglas Gregor          CEnd = AST.cached_completion_end();
2237b14904c4SDouglas Gregor        C != CEnd; ++C) {
2238b14904c4SDouglas Gregor     // If the context we are in matches any of the contexts we are
2239b14904c4SDouglas Gregor     // interested in, we'll add this result.
2240b14904c4SDouglas Gregor     if ((C->ShowInContexts & InContexts) == 0)
2241b14904c4SDouglas Gregor       continue;
2242b14904c4SDouglas Gregor 
2243b14904c4SDouglas Gregor     // If we haven't added any results previously, do so now.
2244b14904c4SDouglas Gregor     if (!AddedResult) {
22456199f2d1SDouglas Gregor       CalculateHiddenNames(Context, Results, NumResults, S.Context,
22466199f2d1SDouglas Gregor                            HiddenNames);
2247b14904c4SDouglas Gregor       AllResults.insert(AllResults.end(), Results, Results + NumResults);
2248b14904c4SDouglas Gregor       AddedResult = true;
2249b14904c4SDouglas Gregor     }
2250b14904c4SDouglas Gregor 
22516199f2d1SDouglas Gregor     // Determine whether this global completion result is hidden by a local
22526199f2d1SDouglas Gregor     // completion result. If so, skip it.
22536199f2d1SDouglas Gregor     if (C->Kind != CXCursor_MacroDefinition &&
22546199f2d1SDouglas Gregor         HiddenNames.count(C->Completion->getTypedText()))
22556199f2d1SDouglas Gregor       continue;
22566199f2d1SDouglas Gregor 
22576e24033bSDouglas Gregor     // Adjust priority based on similar type classes.
22586e24033bSDouglas Gregor     unsigned Priority = C->Priority;
225912785108SDouglas Gregor     CodeCompletionString *Completion = C->Completion;
22606e24033bSDouglas Gregor     if (!Context.getPreferredType().isNull()) {
22616e24033bSDouglas Gregor       if (C->Kind == CXCursor_MacroDefinition) {
22626e24033bSDouglas Gregor         Priority = getMacroUsagePriority(C->Completion->getTypedText(),
2263bbafb8a7SDavid Blaikie                                          S.getLangOpts(),
22646e24033bSDouglas Gregor                                Context.getPreferredType()->isAnyPointerType());
2265b61c07acSDouglas Gregor       } else if (C->Type) {
22666e24033bSDouglas Gregor         CanQualType Expected
2267b61c07acSDouglas Gregor           = S.Context.getCanonicalType(
2268b61c07acSDouglas Gregor                                Context.getPreferredType().getUnqualifiedType());
22696e24033bSDouglas Gregor         SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
22706e24033bSDouglas Gregor         if (ExpectedSTC == C->TypeClass) {
2271b61c07acSDouglas Gregor           // We know this type is similar; check for an exact match.
2272b61c07acSDouglas Gregor           llvm::StringMap<unsigned> &CachedCompletionTypes
2273b61c07acSDouglas Gregor             = AST.getCachedCompletionTypes();
2274b61c07acSDouglas Gregor           llvm::StringMap<unsigned>::iterator Pos
2275b61c07acSDouglas Gregor             = CachedCompletionTypes.find(QualType(Expected).getAsString());
2276b61c07acSDouglas Gregor           if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
2277b61c07acSDouglas Gregor             Priority /= CCF_ExactTypeMatch;
2278b61c07acSDouglas Gregor           else
22796e24033bSDouglas Gregor             Priority /= CCF_SimilarTypeMatch;
22806e24033bSDouglas Gregor         }
22816e24033bSDouglas Gregor       }
22826e24033bSDouglas Gregor     }
22836e24033bSDouglas Gregor 
228412785108SDouglas Gregor     // Adjust the completion string, if required.
228512785108SDouglas Gregor     if (C->Kind == CXCursor_MacroDefinition &&
228612785108SDouglas Gregor         Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
228712785108SDouglas Gregor       // Create a new code-completion string that just contains the
228812785108SDouglas Gregor       // macro name, without its arguments.
22899d7c0fefSArgyrios Kyrtzidis       CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),
22909d7c0fefSArgyrios Kyrtzidis                                     CCP_CodePattern, C->Availability);
2291b278aafbSDouglas Gregor       Builder.AddTypedTextChunk(C->Completion->getTypedText());
22928850aa3fSDouglas Gregor       Priority = CCP_CodePattern;
2293b278aafbSDouglas Gregor       Completion = Builder.TakeString();
229412785108SDouglas Gregor     }
229512785108SDouglas Gregor 
22965c8b1cd2SArgyrios Kyrtzidis     AllResults.push_back(Result(Completion, Priority, C->Kind,
2297f757a12dSDouglas Gregor                                 C->Availability));
2298b14904c4SDouglas Gregor   }
2299b14904c4SDouglas Gregor 
2300b14904c4SDouglas Gregor   // If we did not add any cached completion results, just forward the
2301b14904c4SDouglas Gregor   // results we were given to the next consumer.
2302b14904c4SDouglas Gregor   if (!AddedResult) {
2303b14904c4SDouglas Gregor     Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
2304b14904c4SDouglas Gregor     return;
2305b14904c4SDouglas Gregor   }
2306b14904c4SDouglas Gregor 
2307b14904c4SDouglas Gregor   Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
2308b14904c4SDouglas Gregor                                   AllResults.size());
2309b14904c4SDouglas Gregor }
2310b14904c4SDouglas Gregor 
2311d46cf182SDouglas Gregor 
2312d46cf182SDouglas Gregor 
23130e62c1ccSChris Lattner void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
23148e984da8SDouglas Gregor                            RemappedFile *RemappedFiles,
23158e984da8SDouglas Gregor                            unsigned NumRemappedFiles,
2316b68bc59aSDouglas Gregor                            bool IncludeMacros,
2317b68bc59aSDouglas Gregor                            bool IncludeCodePatterns,
23183292d06aSDmitri Gribenko                            bool IncludeBriefComments,
23198e984da8SDouglas Gregor                            CodeCompleteConsumer &Consumer,
23209c902b55SDavid Blaikie                            DiagnosticsEngine &Diag, LangOptions &LangOpts,
23218e984da8SDouglas Gregor                            SourceManager &SourceMgr, FileManager &FileMgr,
23220e62c1ccSChris Lattner                    SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
23230e62c1ccSChris Lattner              SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
23245e14d39aSTed Kremenek   if (!Invocation)
23258e984da8SDouglas Gregor     return;
23268e984da8SDouglas Gregor 
232716896c45SDouglas Gregor   SimpleTimer CompletionTimer(WantTiming);
2328f2e5a91fSBenjamin Kramer   CompletionTimer.setOutput("Code completion @ " + File + ":" +
23290e62c1ccSChris Lattner                             Twine(Line) + ":" + Twine(Column));
2330028d3e4dSDouglas Gregor 
2331c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<CompilerInvocation>
23325e14d39aSTed Kremenek     CCInvocation(new CompilerInvocation(*Invocation));
23335e14d39aSTed Kremenek 
23345e14d39aSTed Kremenek   FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();
23353292d06aSDmitri Gribenko   CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;
23365e14d39aSTed Kremenek   PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
23378e984da8SDouglas Gregor 
23383292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeMacros = IncludeMacros &&
23393292d06aSDmitri Gribenko                                    CachedCompletionResults.empty();
23403292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
23413292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
23423292d06aSDmitri Gribenko   CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
23433292d06aSDmitri Gribenko 
23443292d06aSDmitri Gribenko   assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);
23453292d06aSDmitri Gribenko 
23468e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.FileName = File;
23478e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.Line = Line;
23488e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.Column = Column;
23498e984da8SDouglas Gregor 
23508e984da8SDouglas Gregor   // Set the language options appropriately.
23518cf47df7STed Kremenek   LangOpts = *CCInvocation->getLangOpts();
23528e984da8SDouglas Gregor 
2353e2778999SDylan Noblesmith   OwningPtr<CompilerInstance> Clang(new CompilerInstance());
235484de4a17STed Kremenek 
235584de4a17STed Kremenek   // Recover resources if we crash before exiting this method.
2356022a4904STed Kremenek   llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
2357022a4904STed Kremenek     CICleanup(Clang.get());
235884de4a17STed Kremenek 
23595e14d39aSTed Kremenek   Clang->setInvocation(&*CCInvocation);
236032fbe312SDouglas Gregor   OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
23618e984da8SDouglas Gregor 
23628e984da8SDouglas Gregor   // Set up diagnostics, capturing any diagnostics produced.
236384de4a17STed Kremenek   Clang->setDiagnostics(&Diag);
23645e14d39aSTed Kremenek   ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts());
23658e984da8SDouglas Gregor   CaptureDroppedDiagnostics Capture(true,
236684de4a17STed Kremenek                                     Clang->getDiagnostics(),
23678e984da8SDouglas Gregor                                     StoredDiagnostics);
23688e984da8SDouglas Gregor 
23698e984da8SDouglas Gregor   // Create the target instance.
237084de4a17STed Kremenek   Clang->getTargetOpts().Features = TargetFeatures;
237184de4a17STed Kremenek   Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
237284de4a17STed Kremenek                                                Clang->getTargetOpts()));
237384de4a17STed Kremenek   if (!Clang->hasTarget()) {
23745e14d39aSTed Kremenek     Clang->setInvocation(0);
23752dd19f1dSDouglas Gregor     return;
23768e984da8SDouglas Gregor   }
23778e984da8SDouglas Gregor 
23788e984da8SDouglas Gregor   // Inform the target of the language options.
23798e984da8SDouglas Gregor   //
23808e984da8SDouglas Gregor   // FIXME: We shouldn't need to do this, the target should be immutable once
23818e984da8SDouglas Gregor   // created. This complexity should be lifted elsewhere.
238284de4a17STed Kremenek   Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
23838e984da8SDouglas Gregor 
238484de4a17STed Kremenek   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
23858e984da8SDouglas Gregor          "Invocation must have exactly one source file!");
238632fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
23878e984da8SDouglas Gregor          "FIXME: AST inputs not yet supported here!");
238832fbe312SDouglas Gregor   assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
23898e984da8SDouglas Gregor          "IR inputs not support here!");
23908e984da8SDouglas Gregor 
23918e984da8SDouglas Gregor 
23928e984da8SDouglas Gregor   // Use the source and file managers that we were given.
239384de4a17STed Kremenek   Clang->setFileManager(&FileMgr);
239484de4a17STed Kremenek   Clang->setSourceManager(&SourceMgr);
23958e984da8SDouglas Gregor 
23968e984da8SDouglas Gregor   // Remap files.
23978e984da8SDouglas Gregor   PreprocessorOpts.clearRemappedFiles();
2398d8a5dba9SDouglas Gregor   PreprocessorOpts.RetainRemappedFileBuffers = true;
2399b97b666cSDouglas Gregor   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
240011e6f0a6SArgyrios Kyrtzidis     FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
240111e6f0a6SArgyrios Kyrtzidis     if (const llvm::MemoryBuffer *
240211e6f0a6SArgyrios Kyrtzidis             memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
240311e6f0a6SArgyrios Kyrtzidis       PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, memBuf);
240411e6f0a6SArgyrios Kyrtzidis       OwnedBuffers.push_back(memBuf);
240511e6f0a6SArgyrios Kyrtzidis     } else {
240611e6f0a6SArgyrios Kyrtzidis       const char *fname = fileOrBuf.get<const char *>();
240711e6f0a6SArgyrios Kyrtzidis       PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, fname);
240811e6f0a6SArgyrios Kyrtzidis     }
2409b97b666cSDouglas Gregor   }
24108e984da8SDouglas Gregor 
2411b14904c4SDouglas Gregor   // Use the code completion consumer we were given, but adding any cached
2412b14904c4SDouglas Gregor   // code-completion results.
2413e9186e6dSDouglas Gregor   AugmentedCodeCompleteConsumer *AugmentedConsumer
24143292d06aSDmitri Gribenko     = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);
241584de4a17STed Kremenek   Clang->setCodeCompletionConsumer(AugmentedConsumer);
24168e984da8SDouglas Gregor 
24176e92251fSErik Verbruggen   Clang->getFrontendOpts().SkipFunctionBodies = true;
24186e92251fSErik Verbruggen 
2419028d3e4dSDouglas Gregor   // If we have a precompiled preamble, try to use it. We only allow
2420028d3e4dSDouglas Gregor   // the use of the precompiled preamble if we're if the completion
2421028d3e4dSDouglas Gregor   // point is within the main file, after the end of the precompiled
2422028d3e4dSDouglas Gregor   // preamble.
2423028d3e4dSDouglas Gregor   llvm::MemoryBuffer *OverrideMainBuffer = 0;
242406b4f919STed Kremenek   if (!getPreambleFile(this).empty()) {
2425028d3e4dSDouglas Gregor     using llvm::sys::FileStatus;
2426028d3e4dSDouglas Gregor     llvm::sys::PathWithStatus CompleteFilePath(File);
2427028d3e4dSDouglas Gregor     llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
2428028d3e4dSDouglas Gregor     if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
2429028d3e4dSDouglas Gregor       if (const FileStatus *MainStatus = MainPath.getFileStatus())
2430a3deaeebSArgyrios Kyrtzidis         if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID() &&
2431a3deaeebSArgyrios Kyrtzidis             Line > 1)
2432b97b666cSDouglas Gregor           OverrideMainBuffer
24335e14d39aSTed Kremenek             = getMainBufferWithPrecompiledPreamble(*CCInvocation, false,
24348e817b6aSDouglas Gregor                                                    Line - 1);
2435028d3e4dSDouglas Gregor   }
2436028d3e4dSDouglas Gregor 
2437028d3e4dSDouglas Gregor   // If the main file has been overridden due to the use of a preamble,
2438028d3e4dSDouglas Gregor   // make that override happen and introduce the preamble.
2439606c4ac3SDouglas Gregor   PreprocessorOpts.DisableStatCache = true;
24407bb8af61SDouglas Gregor   StoredDiagnostics.insert(StoredDiagnostics.end(),
2441067cbfa2SArgyrios Kyrtzidis                            stored_diag_begin(),
2442067cbfa2SArgyrios Kyrtzidis                            stored_diag_afterDriver_begin());
2443028d3e4dSDouglas Gregor   if (OverrideMainBuffer) {
2444028d3e4dSDouglas Gregor     PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
2445028d3e4dSDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
2446028d3e4dSDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second
2447028d3e4dSDouglas Gregor                                                     = PreambleEndsAtStartOfLine;
244806b4f919STed Kremenek     PreprocessorOpts.ImplicitPCHInclude = getPreambleFile(this);
2449028d3e4dSDouglas Gregor     PreprocessorOpts.DisablePCHValidation = true;
2450028d3e4dSDouglas Gregor 
2451b97b666cSDouglas Gregor     OwnedBuffers.push_back(OverrideMainBuffer);
24527b02b583SDouglas Gregor   } else {
24537b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
24547b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second = false;
2455028d3e4dSDouglas Gregor   }
2456028d3e4dSDouglas Gregor 
2457998caeadSDouglas Gregor   // Disable the preprocessing record
2458998caeadSDouglas Gregor   PreprocessorOpts.DetailedRecord = false;
2459998caeadSDouglas Gregor 
2460e2778999SDylan Noblesmith   OwningPtr<SyntaxOnlyAction> Act;
24618e984da8SDouglas Gregor   Act.reset(new SyntaxOnlyAction);
246232fbe312SDouglas Gregor   if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
2463925296b4SDouglas Gregor     if (OverrideMainBuffer) {
246406b4f919STed Kremenek       std::string ModName = getPreambleFile(this);
2465925296b4SDouglas Gregor       TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
2466925296b4SDouglas Gregor                                  getSourceManager(), PreambleDiagnostics,
2467925296b4SDouglas Gregor                                  StoredDiagnostics);
2468925296b4SDouglas Gregor     }
24698e984da8SDouglas Gregor     Act->Execute();
24708e984da8SDouglas Gregor     Act->EndSourceFile();
24718e984da8SDouglas Gregor   }
247238bacf34SArgyrios Kyrtzidis 
247338bacf34SArgyrios Kyrtzidis   checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());
24748e984da8SDouglas Gregor }
2475e9386680SDouglas Gregor 
247639a76387SArgyrios Kyrtzidis bool ASTUnit::Save(StringRef File) {
247755e75574SArgyrios Kyrtzidis   // Write to a temporary file and later rename it to the actual file, to avoid
247855e75574SArgyrios Kyrtzidis   // possible race conditions.
24792c1dd271SDylan Noblesmith   SmallString<128> TempPath;
248008a2bfd2SArgyrios Kyrtzidis   TempPath = File;
248108a2bfd2SArgyrios Kyrtzidis   TempPath += "-%%%%%%%%";
248208a2bfd2SArgyrios Kyrtzidis   int fd;
248308a2bfd2SArgyrios Kyrtzidis   if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
248408a2bfd2SArgyrios Kyrtzidis                                  /*makeAbsolute=*/false))
248539a76387SArgyrios Kyrtzidis     return true;
248655e75574SArgyrios Kyrtzidis 
2487e9386680SDouglas Gregor   // FIXME: Can we somehow regenerate the stat cache here, or do we need to
2488e9386680SDouglas Gregor   // unconditionally create a stat cache when we parse the file?
248908a2bfd2SArgyrios Kyrtzidis   llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
2490e9386680SDouglas Gregor 
249135dcda79SArgyrios Kyrtzidis   serialize(Out);
249235dcda79SArgyrios Kyrtzidis   Out.close();
2493eeea16a0SArgyrios Kyrtzidis   if (Out.has_error()) {
2494eeea16a0SArgyrios Kyrtzidis     Out.clear_error();
249539a76387SArgyrios Kyrtzidis     return true;
2496eeea16a0SArgyrios Kyrtzidis   }
249755e75574SArgyrios Kyrtzidis 
249865e025caSRafael Espindola   if (llvm::sys::fs::rename(TempPath.str(), File)) {
249955e75574SArgyrios Kyrtzidis     bool exists;
250055e75574SArgyrios Kyrtzidis     llvm::sys::fs::remove(TempPath.str(), exists);
250139a76387SArgyrios Kyrtzidis     return true;
250255e75574SArgyrios Kyrtzidis   }
250355e75574SArgyrios Kyrtzidis 
250439a76387SArgyrios Kyrtzidis   return false;
250535dcda79SArgyrios Kyrtzidis }
250635dcda79SArgyrios Kyrtzidis 
25070e62c1ccSChris Lattner bool ASTUnit::serialize(raw_ostream &OS) {
25084a280ff4SArgyrios Kyrtzidis   bool hasErrors = getDiagnostics().hasErrorOccurred();
250935dcda79SArgyrios Kyrtzidis 
25109a96386eSDaniel Dunbar   SmallString<128> Buffer;
2511e9386680SDouglas Gregor   llvm::BitstreamWriter Stream(Buffer);
251255c0ad57SSebastian Redl   ASTWriter Writer(Stream);
25134a69c2e6SDouglas Gregor   // FIXME: Handle modules
25144a280ff4SArgyrios Kyrtzidis   Writer.WriteAST(getSema(), 0, std::string(), 0, "", hasErrors);
2515e9386680SDouglas Gregor 
2516e9386680SDouglas Gregor   // Write the generated bitstream to "Out".
25172dd19f1dSDouglas Gregor   if (!Buffer.empty())
251835dcda79SArgyrios Kyrtzidis     OS.write((char *)&Buffer.front(), Buffer.size());
251935dcda79SArgyrios Kyrtzidis 
252035dcda79SArgyrios Kyrtzidis   return false;
2521e9386680SDouglas Gregor }
2522925296b4SDouglas Gregor 
2523925296b4SDouglas Gregor typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
2524925296b4SDouglas Gregor 
2525925296b4SDouglas Gregor static void TranslateSLoc(SourceLocation &L, SLocRemap &Remap) {
2526925296b4SDouglas Gregor   unsigned Raw = L.getRawEncoding();
2527925296b4SDouglas Gregor   const unsigned MacroBit = 1U << 31;
2528925296b4SDouglas Gregor   L = SourceLocation::getFromRawEncoding((Raw & MacroBit) |
2529925296b4SDouglas Gregor       ((Raw & ~MacroBit) + Remap.find(Raw & ~MacroBit)->second));
2530925296b4SDouglas Gregor }
2531925296b4SDouglas Gregor 
2532925296b4SDouglas Gregor void ASTUnit::TranslateStoredDiagnostics(
2533925296b4SDouglas Gregor                           ASTReader *MMan,
25340e62c1ccSChris Lattner                           StringRef ModName,
2535925296b4SDouglas Gregor                           SourceManager &SrcMgr,
25360e62c1ccSChris Lattner                           const SmallVectorImpl<StoredDiagnostic> &Diags,
25370e62c1ccSChris Lattner                           SmallVectorImpl<StoredDiagnostic> &Out) {
2538925296b4SDouglas Gregor   // The stored diagnostic has the old source manager in it; update
2539925296b4SDouglas Gregor   // the locations to refer into the new source manager. We also need to remap
2540925296b4SDouglas Gregor   // all the locations to the new view. This includes the diag location, any
2541925296b4SDouglas Gregor   // associated source ranges, and the source ranges of associated fix-its.
2542925296b4SDouglas Gregor   // FIXME: There should be a cleaner way to do this.
2543925296b4SDouglas Gregor 
25440e62c1ccSChris Lattner   SmallVector<StoredDiagnostic, 4> Result;
2545925296b4SDouglas Gregor   Result.reserve(Diags.size());
2546925296b4SDouglas Gregor   assert(MMan && "Don't have a module manager");
2547de3ef502SDouglas Gregor   serialization::ModuleFile *Mod = MMan->ModuleMgr.lookup(ModName);
2548925296b4SDouglas Gregor   assert(Mod && "Don't have preamble module");
2549925296b4SDouglas Gregor   SLocRemap &Remap = Mod->SLocRemap;
2550925296b4SDouglas Gregor   for (unsigned I = 0, N = Diags.size(); I != N; ++I) {
2551925296b4SDouglas Gregor     // Rebuild the StoredDiagnostic.
2552925296b4SDouglas Gregor     const StoredDiagnostic &SD = Diags[I];
2553925296b4SDouglas Gregor     SourceLocation L = SD.getLocation();
2554925296b4SDouglas Gregor     TranslateSLoc(L, Remap);
2555925296b4SDouglas Gregor     FullSourceLoc Loc(L, SrcMgr);
2556925296b4SDouglas Gregor 
25570e62c1ccSChris Lattner     SmallVector<CharSourceRange, 4> Ranges;
2558925296b4SDouglas Gregor     Ranges.reserve(SD.range_size());
2559925296b4SDouglas Gregor     for (StoredDiagnostic::range_iterator I = SD.range_begin(),
2560925296b4SDouglas Gregor                                           E = SD.range_end();
2561925296b4SDouglas Gregor          I != E; ++I) {
2562925296b4SDouglas Gregor       SourceLocation BL = I->getBegin();
2563925296b4SDouglas Gregor       TranslateSLoc(BL, Remap);
2564925296b4SDouglas Gregor       SourceLocation EL = I->getEnd();
2565925296b4SDouglas Gregor       TranslateSLoc(EL, Remap);
2566925296b4SDouglas Gregor       Ranges.push_back(CharSourceRange(SourceRange(BL, EL), I->isTokenRange()));
2567925296b4SDouglas Gregor     }
2568925296b4SDouglas Gregor 
25690e62c1ccSChris Lattner     SmallVector<FixItHint, 2> FixIts;
2570925296b4SDouglas Gregor     FixIts.reserve(SD.fixit_size());
2571925296b4SDouglas Gregor     for (StoredDiagnostic::fixit_iterator I = SD.fixit_begin(),
2572925296b4SDouglas Gregor                                           E = SD.fixit_end();
2573925296b4SDouglas Gregor          I != E; ++I) {
2574925296b4SDouglas Gregor       FixIts.push_back(FixItHint());
2575925296b4SDouglas Gregor       FixItHint &FH = FixIts.back();
2576925296b4SDouglas Gregor       FH.CodeToInsert = I->CodeToInsert;
2577925296b4SDouglas Gregor       SourceLocation BL = I->RemoveRange.getBegin();
2578925296b4SDouglas Gregor       TranslateSLoc(BL, Remap);
2579925296b4SDouglas Gregor       SourceLocation EL = I->RemoveRange.getEnd();
2580925296b4SDouglas Gregor       TranslateSLoc(EL, Remap);
2581925296b4SDouglas Gregor       FH.RemoveRange = CharSourceRange(SourceRange(BL, EL),
2582925296b4SDouglas Gregor                                        I->RemoveRange.isTokenRange());
2583925296b4SDouglas Gregor     }
2584925296b4SDouglas Gregor 
2585925296b4SDouglas Gregor     Result.push_back(StoredDiagnostic(SD.getLevel(), SD.getID(),
2586925296b4SDouglas Gregor                                       SD.getMessage(), Loc, Ranges, FixIts));
2587925296b4SDouglas Gregor   }
2588925296b4SDouglas Gregor   Result.swap(Out);
2589925296b4SDouglas Gregor }
25907c06d866SArgyrios Kyrtzidis 
2591e54568d6SArgyrios Kyrtzidis static inline bool compLocDecl(std::pair<unsigned, Decl *> L,
2592e54568d6SArgyrios Kyrtzidis                                std::pair<unsigned, Decl *> R) {
2593e54568d6SArgyrios Kyrtzidis   return L.first < R.first;
2594e54568d6SArgyrios Kyrtzidis }
2595e54568d6SArgyrios Kyrtzidis 
2596e54568d6SArgyrios Kyrtzidis void ASTUnit::addFileLevelDecl(Decl *D) {
2597e54568d6SArgyrios Kyrtzidis   assert(D);
259861d63d0fSDouglas Gregor 
259961d63d0fSDouglas Gregor   // We only care about local declarations.
260061d63d0fSDouglas Gregor   if (D->isFromASTFile())
260161d63d0fSDouglas Gregor     return;
2602e54568d6SArgyrios Kyrtzidis 
2603e54568d6SArgyrios Kyrtzidis   SourceManager &SM = *SourceMgr;
2604e54568d6SArgyrios Kyrtzidis   SourceLocation Loc = D->getLocation();
2605e54568d6SArgyrios Kyrtzidis   if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc))
2606e54568d6SArgyrios Kyrtzidis     return;
2607e54568d6SArgyrios Kyrtzidis 
2608e54568d6SArgyrios Kyrtzidis   // We only keep track of the file-level declarations of each file.
2609e54568d6SArgyrios Kyrtzidis   if (!D->getLexicalDeclContext()->isFileContext())
2610e54568d6SArgyrios Kyrtzidis     return;
2611e54568d6SArgyrios Kyrtzidis 
2612e54568d6SArgyrios Kyrtzidis   SourceLocation FileLoc = SM.getFileLoc(Loc);
2613e54568d6SArgyrios Kyrtzidis   assert(SM.isLocalSourceLocation(FileLoc));
2614e54568d6SArgyrios Kyrtzidis   FileID FID;
2615e54568d6SArgyrios Kyrtzidis   unsigned Offset;
2616e54568d6SArgyrios Kyrtzidis   llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
2617e54568d6SArgyrios Kyrtzidis   if (FID.isInvalid())
2618e54568d6SArgyrios Kyrtzidis     return;
2619e54568d6SArgyrios Kyrtzidis 
2620e54568d6SArgyrios Kyrtzidis   LocDeclsTy *&Decls = FileDecls[FID];
2621e54568d6SArgyrios Kyrtzidis   if (!Decls)
2622e54568d6SArgyrios Kyrtzidis     Decls = new LocDeclsTy();
2623e54568d6SArgyrios Kyrtzidis 
2624e54568d6SArgyrios Kyrtzidis   std::pair<unsigned, Decl *> LocDecl(Offset, D);
2625e54568d6SArgyrios Kyrtzidis 
2626e54568d6SArgyrios Kyrtzidis   if (Decls->empty() || Decls->back().first <= Offset) {
2627e54568d6SArgyrios Kyrtzidis     Decls->push_back(LocDecl);
2628e54568d6SArgyrios Kyrtzidis     return;
2629e54568d6SArgyrios Kyrtzidis   }
2630e54568d6SArgyrios Kyrtzidis 
2631e54568d6SArgyrios Kyrtzidis   LocDeclsTy::iterator
2632e54568d6SArgyrios Kyrtzidis     I = std::upper_bound(Decls->begin(), Decls->end(), LocDecl, compLocDecl);
2633e54568d6SArgyrios Kyrtzidis 
2634e54568d6SArgyrios Kyrtzidis   Decls->insert(I, LocDecl);
2635e54568d6SArgyrios Kyrtzidis }
2636e54568d6SArgyrios Kyrtzidis 
2637e9681525SArgyrios Kyrtzidis void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
2638e9681525SArgyrios Kyrtzidis                                   SmallVectorImpl<Decl *> &Decls) {
2639e9681525SArgyrios Kyrtzidis   if (File.isInvalid())
2640e9681525SArgyrios Kyrtzidis     return;
2641e9681525SArgyrios Kyrtzidis 
2642e9681525SArgyrios Kyrtzidis   if (SourceMgr->isLoadedFileID(File)) {
2643e9681525SArgyrios Kyrtzidis     assert(Ctx->getExternalSource() && "No external source!");
2644e9681525SArgyrios Kyrtzidis     return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length,
2645e9681525SArgyrios Kyrtzidis                                                          Decls);
2646e9681525SArgyrios Kyrtzidis   }
2647e9681525SArgyrios Kyrtzidis 
2648e9681525SArgyrios Kyrtzidis   FileDeclsTy::iterator I = FileDecls.find(File);
2649e9681525SArgyrios Kyrtzidis   if (I == FileDecls.end())
2650e9681525SArgyrios Kyrtzidis     return;
2651e9681525SArgyrios Kyrtzidis 
2652e9681525SArgyrios Kyrtzidis   LocDeclsTy &LocDecls = *I->second;
2653e9681525SArgyrios Kyrtzidis   if (LocDecls.empty())
2654e9681525SArgyrios Kyrtzidis     return;
2655e9681525SArgyrios Kyrtzidis 
2656e9681525SArgyrios Kyrtzidis   LocDeclsTy::iterator
2657e9681525SArgyrios Kyrtzidis     BeginIt = std::lower_bound(LocDecls.begin(), LocDecls.end(),
2658e9681525SArgyrios Kyrtzidis                                std::make_pair(Offset, (Decl*)0), compLocDecl);
2659e9681525SArgyrios Kyrtzidis   if (BeginIt != LocDecls.begin())
2660e9681525SArgyrios Kyrtzidis     --BeginIt;
2661e9681525SArgyrios Kyrtzidis 
26628ad3bab5SArgyrios Kyrtzidis   // If we are pointing at a top-level decl inside an objc container, we need
26638ad3bab5SArgyrios Kyrtzidis   // to backtrack until we find it otherwise we will fail to report that the
26648ad3bab5SArgyrios Kyrtzidis   // region overlaps with an objc container.
26658ad3bab5SArgyrios Kyrtzidis   while (BeginIt != LocDecls.begin() &&
26668ad3bab5SArgyrios Kyrtzidis          BeginIt->second->isTopLevelDeclInObjCContainer())
26678ad3bab5SArgyrios Kyrtzidis     --BeginIt;
26688ad3bab5SArgyrios Kyrtzidis 
2669e9681525SArgyrios Kyrtzidis   LocDeclsTy::iterator
2670e9681525SArgyrios Kyrtzidis     EndIt = std::upper_bound(LocDecls.begin(), LocDecls.end(),
2671e9681525SArgyrios Kyrtzidis                              std::make_pair(Offset+Length, (Decl*)0),
2672e9681525SArgyrios Kyrtzidis                              compLocDecl);
2673e9681525SArgyrios Kyrtzidis   if (EndIt != LocDecls.end())
2674e9681525SArgyrios Kyrtzidis     ++EndIt;
2675e9681525SArgyrios Kyrtzidis 
2676e9681525SArgyrios Kyrtzidis   for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)
2677e9681525SArgyrios Kyrtzidis     Decls.push_back(DIt->second);
2678e9681525SArgyrios Kyrtzidis }
2679e9681525SArgyrios Kyrtzidis 
26807c06d866SArgyrios Kyrtzidis SourceLocation ASTUnit::getLocation(const FileEntry *File,
26817c06d866SArgyrios Kyrtzidis                                     unsigned Line, unsigned Col) const {
26827c06d866SArgyrios Kyrtzidis   const SourceManager &SM = getSourceManager();
26834cdfcae7SArgyrios Kyrtzidis   SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);
26847c06d866SArgyrios Kyrtzidis   return SM.getMacroArgExpandedLocation(Loc);
26857c06d866SArgyrios Kyrtzidis }
26867c06d866SArgyrios Kyrtzidis 
26877c06d866SArgyrios Kyrtzidis SourceLocation ASTUnit::getLocation(const FileEntry *File,
26887c06d866SArgyrios Kyrtzidis                                     unsigned Offset) const {
26897c06d866SArgyrios Kyrtzidis   const SourceManager &SM = getSourceManager();
26904cdfcae7SArgyrios Kyrtzidis   SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);
26917c06d866SArgyrios Kyrtzidis   return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
26927c06d866SArgyrios Kyrtzidis }
26937c06d866SArgyrios Kyrtzidis 
26944cdfcae7SArgyrios Kyrtzidis /// \brief If \arg Loc is a loaded location from the preamble, returns
26954cdfcae7SArgyrios Kyrtzidis /// the corresponding local location of the main file, otherwise it returns
26964cdfcae7SArgyrios Kyrtzidis /// \arg Loc.
26974cdfcae7SArgyrios Kyrtzidis SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) {
26984cdfcae7SArgyrios Kyrtzidis   FileID PreambleID;
26994cdfcae7SArgyrios Kyrtzidis   if (SourceMgr)
27004cdfcae7SArgyrios Kyrtzidis     PreambleID = SourceMgr->getPreambleFileID();
27014cdfcae7SArgyrios Kyrtzidis 
27024cdfcae7SArgyrios Kyrtzidis   if (Loc.isInvalid() || Preamble.empty() || PreambleID.isInvalid())
27034cdfcae7SArgyrios Kyrtzidis     return Loc;
27044cdfcae7SArgyrios Kyrtzidis 
27054cdfcae7SArgyrios Kyrtzidis   unsigned Offs;
27064cdfcae7SArgyrios Kyrtzidis   if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble.size()) {
27074cdfcae7SArgyrios Kyrtzidis     SourceLocation FileLoc
27084cdfcae7SArgyrios Kyrtzidis         = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());
27094cdfcae7SArgyrios Kyrtzidis     return FileLoc.getLocWithOffset(Offs);
27104cdfcae7SArgyrios Kyrtzidis   }
27114cdfcae7SArgyrios Kyrtzidis 
27124cdfcae7SArgyrios Kyrtzidis   return Loc;
27134cdfcae7SArgyrios Kyrtzidis }
27144cdfcae7SArgyrios Kyrtzidis 
27154cdfcae7SArgyrios Kyrtzidis /// \brief If \arg Loc is a local location of the main file but inside the
27164cdfcae7SArgyrios Kyrtzidis /// preamble chunk, returns the corresponding loaded location from the
27174cdfcae7SArgyrios Kyrtzidis /// preamble, otherwise it returns \arg Loc.
27184cdfcae7SArgyrios Kyrtzidis SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) {
27194cdfcae7SArgyrios Kyrtzidis   FileID PreambleID;
27204cdfcae7SArgyrios Kyrtzidis   if (SourceMgr)
27214cdfcae7SArgyrios Kyrtzidis     PreambleID = SourceMgr->getPreambleFileID();
27224cdfcae7SArgyrios Kyrtzidis 
27234cdfcae7SArgyrios Kyrtzidis   if (Loc.isInvalid() || Preamble.empty() || PreambleID.isInvalid())
27244cdfcae7SArgyrios Kyrtzidis     return Loc;
27254cdfcae7SArgyrios Kyrtzidis 
27264cdfcae7SArgyrios Kyrtzidis   unsigned Offs;
27274cdfcae7SArgyrios Kyrtzidis   if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&
27284cdfcae7SArgyrios Kyrtzidis       Offs < Preamble.size()) {
27294cdfcae7SArgyrios Kyrtzidis     SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);
27304cdfcae7SArgyrios Kyrtzidis     return FileLoc.getLocWithOffset(Offs);
27314cdfcae7SArgyrios Kyrtzidis   }
27324cdfcae7SArgyrios Kyrtzidis 
27334cdfcae7SArgyrios Kyrtzidis   return Loc;
27344cdfcae7SArgyrios Kyrtzidis }
27354cdfcae7SArgyrios Kyrtzidis 
2736429ec024SArgyrios Kyrtzidis bool ASTUnit::isInPreambleFileID(SourceLocation Loc) {
2737429ec024SArgyrios Kyrtzidis   FileID FID;
2738429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2739429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getPreambleFileID();
2740429ec024SArgyrios Kyrtzidis 
2741429ec024SArgyrios Kyrtzidis   if (Loc.isInvalid() || FID.isInvalid())
2742429ec024SArgyrios Kyrtzidis     return false;
2743429ec024SArgyrios Kyrtzidis 
2744429ec024SArgyrios Kyrtzidis   return SourceMgr->isInFileID(Loc, FID);
2745429ec024SArgyrios Kyrtzidis }
2746429ec024SArgyrios Kyrtzidis 
2747429ec024SArgyrios Kyrtzidis bool ASTUnit::isInMainFileID(SourceLocation Loc) {
2748429ec024SArgyrios Kyrtzidis   FileID FID;
2749429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2750429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getMainFileID();
2751429ec024SArgyrios Kyrtzidis 
2752429ec024SArgyrios Kyrtzidis   if (Loc.isInvalid() || FID.isInvalid())
2753429ec024SArgyrios Kyrtzidis     return false;
2754429ec024SArgyrios Kyrtzidis 
2755429ec024SArgyrios Kyrtzidis   return SourceMgr->isInFileID(Loc, FID);
2756429ec024SArgyrios Kyrtzidis }
2757429ec024SArgyrios Kyrtzidis 
2758429ec024SArgyrios Kyrtzidis SourceLocation ASTUnit::getEndOfPreambleFileID() {
2759429ec024SArgyrios Kyrtzidis   FileID FID;
2760429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2761429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getPreambleFileID();
2762429ec024SArgyrios Kyrtzidis 
2763429ec024SArgyrios Kyrtzidis   if (FID.isInvalid())
2764429ec024SArgyrios Kyrtzidis     return SourceLocation();
2765429ec024SArgyrios Kyrtzidis 
2766429ec024SArgyrios Kyrtzidis   return SourceMgr->getLocForEndOfFile(FID);
2767429ec024SArgyrios Kyrtzidis }
2768429ec024SArgyrios Kyrtzidis 
2769429ec024SArgyrios Kyrtzidis SourceLocation ASTUnit::getStartOfMainFileID() {
2770429ec024SArgyrios Kyrtzidis   FileID FID;
2771429ec024SArgyrios Kyrtzidis   if (SourceMgr)
2772429ec024SArgyrios Kyrtzidis     FID = SourceMgr->getMainFileID();
2773429ec024SArgyrios Kyrtzidis 
2774429ec024SArgyrios Kyrtzidis   if (FID.isInvalid())
2775429ec024SArgyrios Kyrtzidis     return SourceLocation();
2776429ec024SArgyrios Kyrtzidis 
2777429ec024SArgyrios Kyrtzidis   return SourceMgr->getLocForStartOfFile(FID);
2778429ec024SArgyrios Kyrtzidis }
2779429ec024SArgyrios Kyrtzidis 
2780d4fcf580SArgyrios Kyrtzidis std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
2781d4fcf580SArgyrios Kyrtzidis ASTUnit::getLocalPreprocessingEntities() const {
2782d4fcf580SArgyrios Kyrtzidis   if (isMainFileAST()) {
2783d4fcf580SArgyrios Kyrtzidis     serialization::ModuleFile &
2784d4fcf580SArgyrios Kyrtzidis       Mod = Reader->getModuleManager().getPrimaryModule();
2785d4fcf580SArgyrios Kyrtzidis     return Reader->getModulePreprocessedEntities(Mod);
2786d4fcf580SArgyrios Kyrtzidis   }
2787d4fcf580SArgyrios Kyrtzidis 
2788d4fcf580SArgyrios Kyrtzidis   if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
2789d4fcf580SArgyrios Kyrtzidis     return std::make_pair(PPRec->local_begin(), PPRec->local_end());
2790d4fcf580SArgyrios Kyrtzidis 
2791d4fcf580SArgyrios Kyrtzidis   return std::make_pair(PreprocessingRecord::iterator(),
2792d4fcf580SArgyrios Kyrtzidis                         PreprocessingRecord::iterator());
2793d4fcf580SArgyrios Kyrtzidis }
2794d4fcf580SArgyrios Kyrtzidis 
2795*e514b200SArgyrios Kyrtzidis bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
279610e7846aSArgyrios Kyrtzidis   if (isMainFileAST()) {
279710e7846aSArgyrios Kyrtzidis     serialization::ModuleFile &
279810e7846aSArgyrios Kyrtzidis       Mod = Reader->getModuleManager().getPrimaryModule();
279910e7846aSArgyrios Kyrtzidis     ASTReader::ModuleDeclIterator MDI, MDE;
280010e7846aSArgyrios Kyrtzidis     llvm::tie(MDI, MDE) = Reader->getModuleFileLevelDecls(Mod);
280110e7846aSArgyrios Kyrtzidis     for (; MDI != MDE; ++MDI) {
280210e7846aSArgyrios Kyrtzidis       if (!Fn(context, *MDI))
280310e7846aSArgyrios Kyrtzidis         return false;
280410e7846aSArgyrios Kyrtzidis     }
280510e7846aSArgyrios Kyrtzidis 
280610e7846aSArgyrios Kyrtzidis     return true;
280710e7846aSArgyrios Kyrtzidis   }
280810e7846aSArgyrios Kyrtzidis 
280910e7846aSArgyrios Kyrtzidis   for (ASTUnit::top_level_iterator TL = top_level_begin(),
281010e7846aSArgyrios Kyrtzidis                                 TLEnd = top_level_end();
281110e7846aSArgyrios Kyrtzidis          TL != TLEnd; ++TL) {
281210e7846aSArgyrios Kyrtzidis     if (!Fn(context, *TL))
281310e7846aSArgyrios Kyrtzidis       return false;
281410e7846aSArgyrios Kyrtzidis   }
281510e7846aSArgyrios Kyrtzidis 
281610e7846aSArgyrios Kyrtzidis   return true;
281710e7846aSArgyrios Kyrtzidis }
281810e7846aSArgyrios Kyrtzidis 
28197c06d866SArgyrios Kyrtzidis void ASTUnit::PreambleData::countLines() const {
28207c06d866SArgyrios Kyrtzidis   NumLines = 0;
28217c06d866SArgyrios Kyrtzidis   if (empty())
28227c06d866SArgyrios Kyrtzidis     return;
28237c06d866SArgyrios Kyrtzidis 
28247c06d866SArgyrios Kyrtzidis   for (std::vector<char>::const_iterator
28257c06d866SArgyrios Kyrtzidis          I = Buffer.begin(), E = Buffer.end(); I != E; ++I) {
28267c06d866SArgyrios Kyrtzidis     if (*I == '\n')
28277c06d866SArgyrios Kyrtzidis       ++NumLines;
28287c06d866SArgyrios Kyrtzidis   }
28297c06d866SArgyrios Kyrtzidis   if (Buffer.back() != '\n')
28307c06d866SArgyrios Kyrtzidis     ++NumLines;
28317c06d866SArgyrios Kyrtzidis }
2832ebf01369SArgyrios Kyrtzidis 
2833ebf01369SArgyrios Kyrtzidis #ifndef NDEBUG
2834ebf01369SArgyrios Kyrtzidis ASTUnit::ConcurrencyState::ConcurrencyState() {
2835ebf01369SArgyrios Kyrtzidis   Mutex = new llvm::sys::MutexImpl(/*recursive=*/true);
2836ebf01369SArgyrios Kyrtzidis }
2837ebf01369SArgyrios Kyrtzidis 
2838ebf01369SArgyrios Kyrtzidis ASTUnit::ConcurrencyState::~ConcurrencyState() {
2839ebf01369SArgyrios Kyrtzidis   delete static_cast<llvm::sys::MutexImpl *>(Mutex);
2840ebf01369SArgyrios Kyrtzidis }
2841ebf01369SArgyrios Kyrtzidis 
2842ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::start() {
2843ebf01369SArgyrios Kyrtzidis   bool acquired = static_cast<llvm::sys::MutexImpl *>(Mutex)->tryacquire();
2844ebf01369SArgyrios Kyrtzidis   assert(acquired && "Concurrent access to ASTUnit!");
2845ebf01369SArgyrios Kyrtzidis }
2846ebf01369SArgyrios Kyrtzidis 
2847ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::finish() {
2848ebf01369SArgyrios Kyrtzidis   static_cast<llvm::sys::MutexImpl *>(Mutex)->release();
2849ebf01369SArgyrios Kyrtzidis }
2850ebf01369SArgyrios Kyrtzidis 
2851ebf01369SArgyrios Kyrtzidis #else // NDEBUG
2852ebf01369SArgyrios Kyrtzidis 
2853ebf01369SArgyrios Kyrtzidis ASTUnit::ConcurrencyState::ConcurrencyState() {}
2854ebf01369SArgyrios Kyrtzidis ASTUnit::ConcurrencyState::~ConcurrencyState() {}
2855ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::start() {}
2856ebf01369SArgyrios Kyrtzidis void ASTUnit::ConcurrencyState::finish() {}
2857ebf01369SArgyrios Kyrtzidis 
2858ebf01369SArgyrios Kyrtzidis #endif
2859