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"
2055a17b66SDaniel Dunbar #include "clang/Driver/Compilation.h"
2155a17b66SDaniel Dunbar #include "clang/Driver/Driver.h"
2255a17b66SDaniel Dunbar #include "clang/Driver/Job.h"
2355a17b66SDaniel Dunbar #include "clang/Driver/Tool.h"
24764c0820SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h"
25764c0820SDaniel Dunbar #include "clang/Frontend/FrontendActions.h"
2655a17b66SDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h"
27764c0820SDaniel Dunbar #include "clang/Frontend/FrontendOptions.h"
28f5b13467SSebastian Redl #include "clang/Serialization/ASTReader.h"
291914c6feSSebastian Redl #include "clang/Serialization/ASTWriter.h"
30ce379752SArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
31ce379752SArgyrios Kyrtzidis #include "clang/Lex/Preprocessor.h"
32b9bbd54fSDaniel Dunbar #include "clang/Basic/TargetOptions.h"
33ce379752SArgyrios Kyrtzidis #include "clang/Basic/TargetInfo.h"
34ce379752SArgyrios Kyrtzidis #include "clang/Basic/Diagnostic.h"
3540a5a7deSDouglas Gregor #include "llvm/ADT/StringSet.h"
36aa98ed9aSDouglas Gregor #include "llvm/Support/MemoryBuffer.h"
3755a17b66SDaniel Dunbar #include "llvm/System/Host.h"
386c839f82SBenjamin Kramer #include "llvm/System/Path.h"
39028d3e4dSDouglas Gregor #include "llvm/Support/raw_ostream.h"
4015ba0b34SDouglas Gregor #include "llvm/Support/Timer.h"
41be2d8c60SDouglas Gregor #include <cstdlib>
42318e4036SZhongxing Xu #include <cstdio>
430e11955cSDouglas Gregor #include <sys/stat.h>
44ce379752SArgyrios Kyrtzidis using namespace clang;
45ce379752SArgyrios Kyrtzidis 
46bb420abdSDouglas Gregor /// \brief After failing to build a precompiled preamble (due to
47bb420abdSDouglas Gregor /// errors in the source that occurs in the preamble), the number of
48bb420abdSDouglas Gregor /// reparses during which we'll skip even trying to precompile the
49bb420abdSDouglas Gregor /// preamble.
50bb420abdSDouglas Gregor const unsigned DefaultPreambleRebuildInterval = 5;
51bb420abdSDouglas Gregor 
52d03e823fSDouglas Gregor ASTUnit::ASTUnit(bool _MainFileIsAST)
53aa21cc40SDouglas Gregor   : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
54028d3e4dSDouglas Gregor     CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked),
55a0734c5fSDouglas Gregor     PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
562c8bd47aSDouglas Gregor     ShouldCacheCodeCompletionResults(false),
572c8bd47aSDouglas Gregor     NumTopLevelDeclsAtLastCompletionCache(0),
584740c450SDouglas Gregor     CacheCodeCompletionCoolDown(0),
594740c450SDouglas Gregor     UnsafeToFree(false) {
6015ba0b34SDouglas Gregor }
61d03e823fSDouglas Gregor 
6244cd60eeSSteve Naroff ASTUnit::~ASTUnit() {
630c7c2f8bSDouglas Gregor   ConcurrencyCheckValue = CheckLocked;
64aa21cc40SDouglas Gregor   CleanTemporaryFiles();
654dde7498SDouglas Gregor   if (!PreambleFile.empty())
6615ba0b34SDouglas Gregor     llvm::sys::Path(PreambleFile).eraseFromDisk();
673f4bea06SDouglas Gregor 
683f4bea06SDouglas Gregor   // Free the buffers associated with remapped files. We are required to
693f4bea06SDouglas Gregor   // perform this operation here because we explicitly request that the
703f4bea06SDouglas Gregor   // compiler instance *not* free these buffers for each invocation of the
713f4bea06SDouglas Gregor   // parser.
723f4bea06SDouglas Gregor   if (Invocation.get()) {
733f4bea06SDouglas Gregor     PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
743f4bea06SDouglas Gregor     for (PreprocessorOptions::remapped_file_buffer_iterator
753f4bea06SDouglas Gregor            FB = PPOpts.remapped_file_buffer_begin(),
763f4bea06SDouglas Gregor            FBEnd = PPOpts.remapped_file_buffer_end();
773f4bea06SDouglas Gregor          FB != FBEnd;
783f4bea06SDouglas Gregor          ++FB)
793f4bea06SDouglas Gregor       delete FB->second;
803f4bea06SDouglas Gregor   }
8196c04261SDouglas Gregor 
8296c04261SDouglas Gregor   delete SavedMainFileBuffer;
83a0734c5fSDouglas Gregor   delete PreambleBuffer;
8415ba0b34SDouglas Gregor 
85b14904c4SDouglas Gregor   ClearCachedCompletionResults();
86b14904c4SDouglas Gregor 
8715ba0b34SDouglas Gregor   for (unsigned I = 0, N = Timers.size(); I != N; ++I)
8815ba0b34SDouglas Gregor     delete Timers[I];
89aa21cc40SDouglas Gregor }
90aa21cc40SDouglas Gregor 
91aa21cc40SDouglas Gregor void ASTUnit::CleanTemporaryFiles() {
926cb5ba4cSDouglas Gregor   for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
936cb5ba4cSDouglas Gregor     TemporaryFiles[I].eraseFromDisk();
94aa21cc40SDouglas Gregor   TemporaryFiles.clear();
9544cd60eeSSteve Naroff }
96ce379752SArgyrios Kyrtzidis 
9739982197SDouglas Gregor /// \brief Determine the set of code-completion contexts in which this
9839982197SDouglas Gregor /// declaration should be shown.
9939982197SDouglas Gregor static unsigned getDeclShowContexts(NamedDecl *ND,
10059cab556SDouglas Gregor                                     const LangOptions &LangOpts,
10159cab556SDouglas Gregor                                     bool &IsNestedNameSpecifier) {
10259cab556SDouglas Gregor   IsNestedNameSpecifier = false;
10359cab556SDouglas Gregor 
10439982197SDouglas Gregor   if (isa<UsingShadowDecl>(ND))
10539982197SDouglas Gregor     ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
10639982197SDouglas Gregor   if (!ND)
10739982197SDouglas Gregor     return 0;
10839982197SDouglas Gregor 
10939982197SDouglas Gregor   unsigned Contexts = 0;
11039982197SDouglas Gregor   if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
11139982197SDouglas Gregor       isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
11239982197SDouglas Gregor     // Types can appear in these contexts.
11339982197SDouglas Gregor     if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
11439982197SDouglas Gregor       Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
11539982197SDouglas Gregor                 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
11639982197SDouglas Gregor                 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
11739982197SDouglas Gregor                 | (1 << (CodeCompletionContext::CCC_Statement - 1))
11839982197SDouglas Gregor                 | (1 << (CodeCompletionContext::CCC_Type - 1));
11939982197SDouglas Gregor 
12039982197SDouglas Gregor     // In C++, types can appear in expressions contexts (for functional casts).
12139982197SDouglas Gregor     if (LangOpts.CPlusPlus)
12239982197SDouglas Gregor       Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
12339982197SDouglas Gregor 
12439982197SDouglas Gregor     // In Objective-C, message sends can send interfaces. In Objective-C++,
12539982197SDouglas Gregor     // all types are available due to functional casts.
12639982197SDouglas Gregor     if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
12739982197SDouglas Gregor       Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
12839982197SDouglas Gregor 
12939982197SDouglas Gregor     // Deal with tag names.
13039982197SDouglas Gregor     if (isa<EnumDecl>(ND)) {
13139982197SDouglas Gregor       Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
13239982197SDouglas Gregor 
13359cab556SDouglas Gregor       // Part of the nested-name-specifier in C++0x.
13439982197SDouglas Gregor       if (LangOpts.CPlusPlus0x)
13559cab556SDouglas Gregor         IsNestedNameSpecifier = true;
13639982197SDouglas Gregor     } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
13739982197SDouglas Gregor       if (Record->isUnion())
13839982197SDouglas Gregor         Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
13939982197SDouglas Gregor       else
14039982197SDouglas Gregor         Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
14139982197SDouglas Gregor 
14239982197SDouglas Gregor       if (LangOpts.CPlusPlus)
14359cab556SDouglas Gregor         IsNestedNameSpecifier = true;
14459cab556SDouglas Gregor     } else if (isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND))
14559cab556SDouglas Gregor       IsNestedNameSpecifier = true;
14639982197SDouglas Gregor   } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
14739982197SDouglas Gregor     // Values can appear in these contexts.
14839982197SDouglas Gregor     Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
14939982197SDouglas Gregor              | (1 << (CodeCompletionContext::CCC_Expression - 1))
15039982197SDouglas Gregor              | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
15139982197SDouglas Gregor   } else if (isa<ObjCProtocolDecl>(ND)) {
15239982197SDouglas Gregor     Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
15339982197SDouglas Gregor   } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
15459cab556SDouglas Gregor     Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
15539982197SDouglas Gregor 
15639982197SDouglas Gregor     // Part of the nested-name-specifier.
15759cab556SDouglas Gregor     IsNestedNameSpecifier = true;
15839982197SDouglas Gregor   }
15939982197SDouglas Gregor 
16039982197SDouglas Gregor   return Contexts;
16139982197SDouglas Gregor }
16239982197SDouglas Gregor 
163b14904c4SDouglas Gregor void ASTUnit::CacheCodeCompletionResults() {
164b14904c4SDouglas Gregor   if (!TheSema)
165b14904c4SDouglas Gregor     return;
166b14904c4SDouglas Gregor 
167b14904c4SDouglas Gregor   llvm::Timer *CachingTimer = 0;
168b14904c4SDouglas Gregor   if (TimerGroup.get()) {
169b14904c4SDouglas Gregor     CachingTimer = new llvm::Timer("Cache global code completions",
170b14904c4SDouglas Gregor                                    *TimerGroup);
171b14904c4SDouglas Gregor     CachingTimer->startTimer();
172b14904c4SDouglas Gregor     Timers.push_back(CachingTimer);
173b14904c4SDouglas Gregor   }
174b14904c4SDouglas Gregor 
175b14904c4SDouglas Gregor   // Clear out the previous results.
176b14904c4SDouglas Gregor   ClearCachedCompletionResults();
177b14904c4SDouglas Gregor 
178b14904c4SDouglas Gregor   // Gather the set of global code completions.
179b14904c4SDouglas Gregor   typedef CodeCompleteConsumer::Result Result;
180b14904c4SDouglas Gregor   llvm::SmallVector<Result, 8> Results;
181b14904c4SDouglas Gregor   TheSema->GatherGlobalCodeCompletions(Results);
182b14904c4SDouglas Gregor 
183b14904c4SDouglas Gregor   // Translate global code completions into cached completions.
184b61c07acSDouglas Gregor   llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
185b61c07acSDouglas Gregor 
186b14904c4SDouglas Gregor   for (unsigned I = 0, N = Results.size(); I != N; ++I) {
187b14904c4SDouglas Gregor     switch (Results[I].Kind) {
18839982197SDouglas Gregor     case Result::RK_Declaration: {
18959cab556SDouglas Gregor       bool IsNestedNameSpecifier = false;
19039982197SDouglas Gregor       CachedCodeCompletionResult CachedResult;
19139982197SDouglas Gregor       CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
19239982197SDouglas Gregor       CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
19359cab556SDouglas Gregor                                                         Ctx->getLangOptions(),
19459cab556SDouglas Gregor                                                         IsNestedNameSpecifier);
19539982197SDouglas Gregor       CachedResult.Priority = Results[I].Priority;
19639982197SDouglas Gregor       CachedResult.Kind = Results[I].CursorKind;
197f757a12dSDouglas Gregor       CachedResult.Availability = Results[I].Availability;
19824747408SDouglas Gregor 
199b61c07acSDouglas Gregor       // Keep track of the type of this completion in an ASTContext-agnostic
200b61c07acSDouglas Gregor       // way.
20124747408SDouglas Gregor       QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
202b61c07acSDouglas Gregor       if (UsageType.isNull()) {
20324747408SDouglas Gregor         CachedResult.TypeClass = STC_Void;
204b61c07acSDouglas Gregor         CachedResult.Type = 0;
205b61c07acSDouglas Gregor       } else {
206b61c07acSDouglas Gregor         CanQualType CanUsageType
207b61c07acSDouglas Gregor           = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
208b61c07acSDouglas Gregor         CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
209b61c07acSDouglas Gregor 
210b61c07acSDouglas Gregor         // Determine whether we have already seen this type. If so, we save
211b61c07acSDouglas Gregor         // ourselves the work of formatting the type string by using the
212b61c07acSDouglas Gregor         // temporary, CanQualType-based hash table to find the associated value.
213b61c07acSDouglas Gregor         unsigned &TypeValue = CompletionTypes[CanUsageType];
214b61c07acSDouglas Gregor         if (TypeValue == 0) {
215b61c07acSDouglas Gregor           TypeValue = CompletionTypes.size();
216b61c07acSDouglas Gregor           CachedCompletionTypes[QualType(CanUsageType).getAsString()]
217b61c07acSDouglas Gregor             = TypeValue;
21824747408SDouglas Gregor         }
219b61c07acSDouglas Gregor 
220b61c07acSDouglas Gregor         CachedResult.Type = TypeValue;
221b61c07acSDouglas Gregor       }
222b61c07acSDouglas Gregor 
22339982197SDouglas Gregor       CachedCompletionResults.push_back(CachedResult);
22459cab556SDouglas Gregor 
22559cab556SDouglas Gregor       /// Handle nested-name-specifiers in C++.
22659cab556SDouglas Gregor       if (TheSema->Context.getLangOptions().CPlusPlus &&
22759cab556SDouglas Gregor           IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
22859cab556SDouglas Gregor         // The contexts in which a nested-name-specifier can appear in C++.
22959cab556SDouglas Gregor         unsigned NNSContexts
23059cab556SDouglas Gregor           = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
23159cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
23259cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
23359cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_Statement - 1))
23459cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_Expression - 1))
23559cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
23659cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
23759cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
23859cab556SDouglas Gregor           | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
239c49f5b2fSDouglas Gregor           | (1 << (CodeCompletionContext::CCC_Type - 1))
240c49f5b2fSDouglas Gregor           | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1));
24159cab556SDouglas Gregor 
24259cab556SDouglas Gregor         if (isa<NamespaceDecl>(Results[I].Declaration) ||
24359cab556SDouglas Gregor             isa<NamespaceAliasDecl>(Results[I].Declaration))
24459cab556SDouglas Gregor           NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
24559cab556SDouglas Gregor 
24659cab556SDouglas Gregor         if (unsigned RemainingContexts
24759cab556SDouglas Gregor                                 = NNSContexts & ~CachedResult.ShowInContexts) {
24859cab556SDouglas Gregor           // If there any contexts where this completion can be a
24959cab556SDouglas Gregor           // nested-name-specifier but isn't already an option, create a
25059cab556SDouglas Gregor           // nested-name-specifier completion.
25159cab556SDouglas Gregor           Results[I].StartsNestedNameSpecifier = true;
25259cab556SDouglas Gregor           CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
25359cab556SDouglas Gregor           CachedResult.ShowInContexts = RemainingContexts;
25459cab556SDouglas Gregor           CachedResult.Priority = CCP_NestedNameSpecifier;
25559cab556SDouglas Gregor           CachedResult.TypeClass = STC_Void;
25659cab556SDouglas Gregor           CachedResult.Type = 0;
25759cab556SDouglas Gregor           CachedCompletionResults.push_back(CachedResult);
25859cab556SDouglas Gregor         }
25959cab556SDouglas Gregor       }
260b14904c4SDouglas Gregor       break;
26139982197SDouglas Gregor     }
262b14904c4SDouglas Gregor 
263b14904c4SDouglas Gregor     case Result::RK_Keyword:
264b14904c4SDouglas Gregor     case Result::RK_Pattern:
265b14904c4SDouglas Gregor       // Ignore keywords and patterns; we don't care, since they are so
266b14904c4SDouglas Gregor       // easily regenerated.
267b14904c4SDouglas Gregor       break;
268b14904c4SDouglas Gregor 
269b14904c4SDouglas Gregor     case Result::RK_Macro: {
270b14904c4SDouglas Gregor       CachedCodeCompletionResult CachedResult;
271b14904c4SDouglas Gregor       CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
272b14904c4SDouglas Gregor       CachedResult.ShowInContexts
273b14904c4SDouglas Gregor         = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
274b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
275b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
276b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
277b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
278b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_Statement - 1))
279b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_Expression - 1))
28012785108SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
281*ec00a268SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
282*ec00a268SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1));
283c49f5b2fSDouglas Gregor 
284b14904c4SDouglas Gregor       CachedResult.Priority = Results[I].Priority;
285b14904c4SDouglas Gregor       CachedResult.Kind = Results[I].CursorKind;
286f757a12dSDouglas Gregor       CachedResult.Availability = Results[I].Availability;
2876e24033bSDouglas Gregor       CachedResult.TypeClass = STC_Void;
288b61c07acSDouglas Gregor       CachedResult.Type = 0;
289b14904c4SDouglas Gregor       CachedCompletionResults.push_back(CachedResult);
290b14904c4SDouglas Gregor       break;
291b14904c4SDouglas Gregor     }
292b14904c4SDouglas Gregor     }
293b14904c4SDouglas Gregor     Results[I].Destroy();
294b14904c4SDouglas Gregor   }
295b14904c4SDouglas Gregor 
296b14904c4SDouglas Gregor   if (CachingTimer)
297b14904c4SDouglas Gregor     CachingTimer->stopTimer();
2982c8bd47aSDouglas Gregor 
2992c8bd47aSDouglas Gregor   // Make a note of the state when we performed this caching.
3002c8bd47aSDouglas Gregor   NumTopLevelDeclsAtLastCompletionCache = top_level_size();
3012c8bd47aSDouglas Gregor   CacheCodeCompletionCoolDown = 15;
302b14904c4SDouglas Gregor }
303b14904c4SDouglas Gregor 
304b14904c4SDouglas Gregor void ASTUnit::ClearCachedCompletionResults() {
305b14904c4SDouglas Gregor   for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I)
306b14904c4SDouglas Gregor     delete CachedCompletionResults[I].Completion;
307b14904c4SDouglas Gregor   CachedCompletionResults.clear();
308b61c07acSDouglas Gregor   CachedCompletionTypes.clear();
309b14904c4SDouglas Gregor }
310b14904c4SDouglas Gregor 
311ce379752SArgyrios Kyrtzidis namespace {
312ce379752SArgyrios Kyrtzidis 
3132c499f65SSebastian Redl /// \brief Gathers information from ASTReader that will be used to initialize
314ce379752SArgyrios Kyrtzidis /// a Preprocessor.
315d44cd6adSSebastian Redl class ASTInfoCollector : public ASTReaderListener {
316ce379752SArgyrios Kyrtzidis   LangOptions &LangOpt;
317ce379752SArgyrios Kyrtzidis   HeaderSearch &HSI;
318ce379752SArgyrios Kyrtzidis   std::string &TargetTriple;
319ce379752SArgyrios Kyrtzidis   std::string &Predefines;
320ce379752SArgyrios Kyrtzidis   unsigned &Counter;
321ce379752SArgyrios Kyrtzidis 
322ce379752SArgyrios Kyrtzidis   unsigned NumHeaderInfos;
323ce379752SArgyrios Kyrtzidis 
324ce379752SArgyrios Kyrtzidis public:
325d44cd6adSSebastian Redl   ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
326ce379752SArgyrios Kyrtzidis                    std::string &TargetTriple, std::string &Predefines,
327ce379752SArgyrios Kyrtzidis                    unsigned &Counter)
328ce379752SArgyrios Kyrtzidis     : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
329ce379752SArgyrios Kyrtzidis       Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
330ce379752SArgyrios Kyrtzidis 
331ce379752SArgyrios Kyrtzidis   virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
332ce379752SArgyrios Kyrtzidis     LangOpt = LangOpts;
333ce379752SArgyrios Kyrtzidis     return false;
334ce379752SArgyrios Kyrtzidis   }
335ce379752SArgyrios Kyrtzidis 
33620a682deSDaniel Dunbar   virtual bool ReadTargetTriple(llvm::StringRef Triple) {
337ce379752SArgyrios Kyrtzidis     TargetTriple = Triple;
338ce379752SArgyrios Kyrtzidis     return false;
339ce379752SArgyrios Kyrtzidis   }
340ce379752SArgyrios Kyrtzidis 
3418b41f300SSebastian Redl   virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
342000c4ffdSDaniel Dunbar                                     llvm::StringRef OriginalFileName,
343ce379752SArgyrios Kyrtzidis                                     std::string &SuggestedPredefines) {
3448b41f300SSebastian Redl     Predefines = Buffers[0].Data;
3458b41f300SSebastian Redl     for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
3468b41f300SSebastian Redl       Predefines += Buffers[I].Data;
3478b41f300SSebastian Redl     }
348ce379752SArgyrios Kyrtzidis     return false;
349ce379752SArgyrios Kyrtzidis   }
350ce379752SArgyrios Kyrtzidis 
351a2f49450SDouglas Gregor   virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
352ce379752SArgyrios Kyrtzidis     HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
353ce379752SArgyrios Kyrtzidis   }
354ce379752SArgyrios Kyrtzidis 
355ce379752SArgyrios Kyrtzidis   virtual void ReadCounter(unsigned Value) {
356ce379752SArgyrios Kyrtzidis     Counter = Value;
357ce379752SArgyrios Kyrtzidis   }
358ce379752SArgyrios Kyrtzidis };
359ce379752SArgyrios Kyrtzidis 
36033cdd810SDouglas Gregor class StoredDiagnosticClient : public DiagnosticClient {
36133cdd810SDouglas Gregor   llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
36233cdd810SDouglas Gregor 
36333cdd810SDouglas Gregor public:
36433cdd810SDouglas Gregor   explicit StoredDiagnosticClient(
36533cdd810SDouglas Gregor                           llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
36633cdd810SDouglas Gregor     : StoredDiags(StoredDiags) { }
36733cdd810SDouglas Gregor 
36833cdd810SDouglas Gregor   virtual void HandleDiagnostic(Diagnostic::Level Level,
36933cdd810SDouglas Gregor                                 const DiagnosticInfo &Info);
37033cdd810SDouglas Gregor };
37133cdd810SDouglas Gregor 
37233cdd810SDouglas Gregor /// \brief RAII object that optionally captures diagnostics, if
37333cdd810SDouglas Gregor /// there is no diagnostic client to capture them already.
37433cdd810SDouglas Gregor class CaptureDroppedDiagnostics {
37533cdd810SDouglas Gregor   Diagnostic &Diags;
37633cdd810SDouglas Gregor   StoredDiagnosticClient Client;
37733cdd810SDouglas Gregor   DiagnosticClient *PreviousClient;
37833cdd810SDouglas Gregor 
37933cdd810SDouglas Gregor public:
38033cdd810SDouglas Gregor   CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
38133cdd810SDouglas Gregor                            llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
3822dd19f1dSDouglas Gregor     : Diags(Diags), Client(StoredDiags), PreviousClient(0)
38333cdd810SDouglas Gregor   {
3842dd19f1dSDouglas Gregor     if (RequestCapture || Diags.getClient() == 0) {
3852dd19f1dSDouglas Gregor       PreviousClient = Diags.takeClient();
38633cdd810SDouglas Gregor       Diags.setClient(&Client);
38733cdd810SDouglas Gregor     }
3882dd19f1dSDouglas Gregor   }
38933cdd810SDouglas Gregor 
39033cdd810SDouglas Gregor   ~CaptureDroppedDiagnostics() {
3912dd19f1dSDouglas Gregor     if (Diags.getClient() == &Client) {
3922dd19f1dSDouglas Gregor       Diags.takeClient();
39333cdd810SDouglas Gregor       Diags.setClient(PreviousClient);
39433cdd810SDouglas Gregor     }
3952dd19f1dSDouglas Gregor   }
39633cdd810SDouglas Gregor };
39733cdd810SDouglas Gregor 
398ce379752SArgyrios Kyrtzidis } // anonymous namespace
399ce379752SArgyrios Kyrtzidis 
40033cdd810SDouglas Gregor void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
40133cdd810SDouglas Gregor                                               const DiagnosticInfo &Info) {
40233cdd810SDouglas Gregor   StoredDiags.push_back(StoredDiagnostic(Level, Info));
40333cdd810SDouglas Gregor }
40433cdd810SDouglas Gregor 
405c0683b90SSteve Naroff const std::string &ASTUnit::getOriginalSourceFileName() {
406a8a50937SDaniel Dunbar   return OriginalSourceFile;
407c0683b90SSteve Naroff }
408ce379752SArgyrios Kyrtzidis 
409d44cd6adSSebastian Redl const std::string &ASTUnit::getASTFileName() {
410d44cd6adSSebastian Redl   assert(isMainFileAST() && "Not an ASTUnit from an AST file!");
4112c499f65SSebastian Redl   return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName();
41244cd60eeSSteve Naroff }
41344cd60eeSSteve Naroff 
414d44cd6adSSebastian Redl ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
4157f95d26eSDouglas Gregor                                   llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
4168bcb1c68STed Kremenek                                   bool OnlyLocalDecls,
417aa98ed9aSDouglas Gregor                                   RemappedFile *RemappedFiles,
41833cdd810SDouglas Gregor                                   unsigned NumRemappedFiles,
41933cdd810SDouglas Gregor                                   bool CaptureDiagnostics) {
420d03e823fSDouglas Gregor   llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
421d03e823fSDouglas Gregor 
4227f95d26eSDouglas Gregor   if (!Diags.getPtr()) {
423d03e823fSDouglas Gregor     // No diagnostics engine was provided, so create our own diagnostics object
424d03e823fSDouglas Gregor     // with the default options.
425d03e823fSDouglas Gregor     DiagnosticOptions DiagOpts;
4267f95d26eSDouglas Gregor     Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
427d03e823fSDouglas Gregor   }
428d03e823fSDouglas Gregor 
429aa21cc40SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
43016bef857SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
4317f95d26eSDouglas Gregor   AST->Diagnostics = Diags;
432d03e823fSDouglas Gregor   AST->FileMgr.reset(new FileManager);
433d03e823fSDouglas Gregor   AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
434505fb84eSSteve Naroff   AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
435ce379752SArgyrios Kyrtzidis 
43633cdd810SDouglas Gregor   // If requested, capture diagnostics in the ASTUnit.
437d03e823fSDouglas Gregor   CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
438a2433154SDouglas Gregor                                     AST->StoredDiagnostics);
43933cdd810SDouglas Gregor 
440aa98ed9aSDouglas Gregor   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
441aa98ed9aSDouglas Gregor     // Create the file entry for the file that we're mapping from.
442aa98ed9aSDouglas Gregor     const FileEntry *FromFile
443aa98ed9aSDouglas Gregor       = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
444aa98ed9aSDouglas Gregor                                     RemappedFiles[I].second->getBufferSize(),
445aa98ed9aSDouglas Gregor                                              0);
446aa98ed9aSDouglas Gregor     if (!FromFile) {
447d03e823fSDouglas Gregor       AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
448aa98ed9aSDouglas Gregor         << RemappedFiles[I].first;
44989a56c56SDouglas Gregor       delete RemappedFiles[I].second;
450aa98ed9aSDouglas Gregor       continue;
451aa98ed9aSDouglas Gregor     }
452aa98ed9aSDouglas Gregor 
453aa98ed9aSDouglas Gregor     // Override the contents of the "from" file with the contents of
454aa98ed9aSDouglas Gregor     // the "to" file.
455aa98ed9aSDouglas Gregor     AST->getSourceManager().overrideFileContents(FromFile,
456aa98ed9aSDouglas Gregor                                                  RemappedFiles[I].second);
457aa98ed9aSDouglas Gregor   }
458aa98ed9aSDouglas Gregor 
459ce379752SArgyrios Kyrtzidis   // Gather Info for preprocessor construction later on.
460ce379752SArgyrios Kyrtzidis 
461ce379752SArgyrios Kyrtzidis   LangOptions LangInfo;
462ce379752SArgyrios Kyrtzidis   HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
463ce379752SArgyrios Kyrtzidis   std::string TargetTriple;
464ce379752SArgyrios Kyrtzidis   std::string Predefines;
465ce379752SArgyrios Kyrtzidis   unsigned Counter;
466ce379752SArgyrios Kyrtzidis 
4672c499f65SSebastian Redl   llvm::OwningPtr<ASTReader> Reader;
468ce379752SArgyrios Kyrtzidis 
4692c499f65SSebastian Redl   Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(),
470d03e823fSDouglas Gregor                              AST->getDiagnostics()));
471d44cd6adSSebastian Redl   Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple,
4722d9c740cSDaniel Dunbar                                            Predefines, Counter));
4732d9c740cSDaniel Dunbar 
4743e31c724SSebastian Redl   switch (Reader->ReadAST(Filename)) {
4752c499f65SSebastian Redl   case ASTReader::Success:
476ce379752SArgyrios Kyrtzidis     break;
477ce379752SArgyrios Kyrtzidis 
4782c499f65SSebastian Redl   case ASTReader::Failure:
4792c499f65SSebastian Redl   case ASTReader::IgnorePCH:
480d03e823fSDouglas Gregor     AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
481ce379752SArgyrios Kyrtzidis     return NULL;
482ce379752SArgyrios Kyrtzidis   }
483ce379752SArgyrios Kyrtzidis 
484a8a50937SDaniel Dunbar   AST->OriginalSourceFile = Reader->getOriginalSourceFile();
485a8a50937SDaniel Dunbar 
486d44cd6adSSebastian Redl   // AST file loaded successfully. Now create the preprocessor.
487ce379752SArgyrios Kyrtzidis 
488ce379752SArgyrios Kyrtzidis   // Get information about the target being compiled for.
489b9bbd54fSDaniel Dunbar   //
490d44cd6adSSebastian Redl   // FIXME: This is broken, we should store the TargetOptions in the AST file.
491b9bbd54fSDaniel Dunbar   TargetOptions TargetOpts;
492b9bbd54fSDaniel Dunbar   TargetOpts.ABI = "";
4931c456c89SJohn McCall   TargetOpts.CXXABI = "";
494b9bbd54fSDaniel Dunbar   TargetOpts.CPU = "";
495b9bbd54fSDaniel Dunbar   TargetOpts.Features.clear();
496b9bbd54fSDaniel Dunbar   TargetOpts.Triple = TargetTriple;
497d03e823fSDouglas Gregor   AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
498d03e823fSDouglas Gregor                                                  TargetOpts));
499d03e823fSDouglas Gregor   AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
500d03e823fSDouglas Gregor                                  *AST->Target.get(),
5017cd285f0SDaniel Dunbar                                  AST->getSourceManager(), HeaderInfo));
502ce379752SArgyrios Kyrtzidis   Preprocessor &PP = *AST->PP.get();
503ce379752SArgyrios Kyrtzidis 
504b7bbfdd9SDaniel Dunbar   PP.setPredefines(Reader->getSuggestedPredefines());
505ce379752SArgyrios Kyrtzidis   PP.setCounterValue(Counter);
5062d9c740cSDaniel Dunbar   Reader->setPreprocessor(PP);
507ce379752SArgyrios Kyrtzidis 
508ce379752SArgyrios Kyrtzidis   // Create and initialize the ASTContext.
509ce379752SArgyrios Kyrtzidis 
510ce379752SArgyrios Kyrtzidis   AST->Ctx.reset(new ASTContext(LangInfo,
5117cd285f0SDaniel Dunbar                                 AST->getSourceManager(),
512ce379752SArgyrios Kyrtzidis                                 *AST->Target.get(),
513ce379752SArgyrios Kyrtzidis                                 PP.getIdentifierTable(),
514ce379752SArgyrios Kyrtzidis                                 PP.getSelectorTable(),
515ce379752SArgyrios Kyrtzidis                                 PP.getBuiltinInfo(),
516ce379752SArgyrios Kyrtzidis                                 /* size_reserve = */0));
517ce379752SArgyrios Kyrtzidis   ASTContext &Context = *AST->Ctx.get();
518ce379752SArgyrios Kyrtzidis 
5192d9c740cSDaniel Dunbar   Reader->InitializeContext(Context);
520ce379752SArgyrios Kyrtzidis 
5212c499f65SSebastian Redl   // Attach the AST reader to the AST context as an external AST
522ce379752SArgyrios Kyrtzidis   // source, so that declarations will be deserialized from the
523d44cd6adSSebastian Redl   // AST file as needed.
5242c499f65SSebastian Redl   ASTReader *ReaderPtr = Reader.get();
5256fd55e06SDouglas Gregor   llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
526ce379752SArgyrios Kyrtzidis   Context.setExternalSource(Source);
527ce379752SArgyrios Kyrtzidis 
5286fd55e06SDouglas Gregor   // Create an AST consumer, even though it isn't used.
5296fd55e06SDouglas Gregor   AST->Consumer.reset(new ASTConsumer);
5306fd55e06SDouglas Gregor 
5312c499f65SSebastian Redl   // Create a semantic analysis object and tell the AST reader about it.
5326fd55e06SDouglas Gregor   AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
5336fd55e06SDouglas Gregor   AST->TheSema->Initialize();
5346fd55e06SDouglas Gregor   ReaderPtr->InitializeSema(*AST->TheSema);
5356fd55e06SDouglas Gregor 
536ce379752SArgyrios Kyrtzidis   return AST.take();
537ce379752SArgyrios Kyrtzidis }
538764c0820SDaniel Dunbar 
539764c0820SDaniel Dunbar namespace {
540764c0820SDaniel Dunbar 
541644dca07SDaniel Dunbar class TopLevelDeclTrackerConsumer : public ASTConsumer {
542644dca07SDaniel Dunbar   ASTUnit &Unit;
543644dca07SDaniel Dunbar 
544644dca07SDaniel Dunbar public:
545644dca07SDaniel Dunbar   TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
546644dca07SDaniel Dunbar 
547644dca07SDaniel Dunbar   void HandleTopLevelDecl(DeclGroupRef D) {
548acc59c3eSTed Kremenek     for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
549acc59c3eSTed Kremenek       Decl *D = *it;
550acc59c3eSTed Kremenek       // FIXME: Currently ObjC method declarations are incorrectly being
551acc59c3eSTed Kremenek       // reported as top-level declarations, even though their DeclContext
552acc59c3eSTed Kremenek       // is the containing ObjC @interface/@implementation.  This is a
553acc59c3eSTed Kremenek       // fundamental problem in the parser right now.
554acc59c3eSTed Kremenek       if (isa<ObjCMethodDecl>(D))
555acc59c3eSTed Kremenek         continue;
556e9db88f9SDouglas Gregor       Unit.addTopLevelDecl(D);
557acc59c3eSTed Kremenek     }
558644dca07SDaniel Dunbar   }
559eaa4ade8SSebastian Redl 
560eaa4ade8SSebastian Redl   // We're not interested in "interesting" decls.
561eaa4ade8SSebastian Redl   void HandleInterestingDecl(DeclGroupRef) {}
562644dca07SDaniel Dunbar };
563644dca07SDaniel Dunbar 
564644dca07SDaniel Dunbar class TopLevelDeclTrackerAction : public ASTFrontendAction {
565644dca07SDaniel Dunbar public:
566644dca07SDaniel Dunbar   ASTUnit &Unit;
567644dca07SDaniel Dunbar 
568764c0820SDaniel Dunbar   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
569764c0820SDaniel Dunbar                                          llvm::StringRef InFile) {
570644dca07SDaniel Dunbar     return new TopLevelDeclTrackerConsumer(Unit);
571764c0820SDaniel Dunbar   }
572764c0820SDaniel Dunbar 
573764c0820SDaniel Dunbar public:
574644dca07SDaniel Dunbar   TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
575644dca07SDaniel Dunbar 
576764c0820SDaniel Dunbar   virtual bool hasCodeCompletionSupport() const { return false; }
577028d3e4dSDouglas Gregor   virtual bool usesCompleteTranslationUnit()  {
578028d3e4dSDouglas Gregor     return Unit.isCompleteTranslationUnit();
579028d3e4dSDouglas Gregor   }
580764c0820SDaniel Dunbar };
581764c0820SDaniel Dunbar 
58248c8cd3fSDouglas Gregor class PrecompilePreambleConsumer : public PCHGenerator {
58348c8cd3fSDouglas Gregor   ASTUnit &Unit;
584e9db88f9SDouglas Gregor   std::vector<Decl *> TopLevelDecls;
58548c8cd3fSDouglas Gregor 
58648c8cd3fSDouglas Gregor public:
58748c8cd3fSDouglas Gregor   PrecompilePreambleConsumer(ASTUnit &Unit,
58848c8cd3fSDouglas Gregor                              const Preprocessor &PP, bool Chaining,
58948c8cd3fSDouglas Gregor                              const char *isysroot, llvm::raw_ostream *Out)
59048c8cd3fSDouglas Gregor     : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
59148c8cd3fSDouglas Gregor 
592e9db88f9SDouglas Gregor   virtual void HandleTopLevelDecl(DeclGroupRef D) {
59348c8cd3fSDouglas Gregor     for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
59448c8cd3fSDouglas Gregor       Decl *D = *it;
59548c8cd3fSDouglas Gregor       // FIXME: Currently ObjC method declarations are incorrectly being
59648c8cd3fSDouglas Gregor       // reported as top-level declarations, even though their DeclContext
59748c8cd3fSDouglas Gregor       // is the containing ObjC @interface/@implementation.  This is a
59848c8cd3fSDouglas Gregor       // fundamental problem in the parser right now.
59948c8cd3fSDouglas Gregor       if (isa<ObjCMethodDecl>(D))
60048c8cd3fSDouglas Gregor         continue;
601e9db88f9SDouglas Gregor       TopLevelDecls.push_back(D);
602e9db88f9SDouglas Gregor     }
603e9db88f9SDouglas Gregor   }
604e9db88f9SDouglas Gregor 
605e9db88f9SDouglas Gregor   virtual void HandleTranslationUnit(ASTContext &Ctx) {
606e9db88f9SDouglas Gregor     PCHGenerator::HandleTranslationUnit(Ctx);
607e9db88f9SDouglas Gregor     if (!Unit.getDiagnostics().hasErrorOccurred()) {
608e9db88f9SDouglas Gregor       // Translate the top-level declarations we captured during
609e9db88f9SDouglas Gregor       // parsing into declaration IDs in the precompiled
610e9db88f9SDouglas Gregor       // preamble. This will allow us to deserialize those top-level
611e9db88f9SDouglas Gregor       // declarations when requested.
612e9db88f9SDouglas Gregor       for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
613e9db88f9SDouglas Gregor         Unit.addTopLevelDeclFromPreamble(
614e9db88f9SDouglas Gregor                                       getWriter().getDeclID(TopLevelDecls[I]));
61548c8cd3fSDouglas Gregor     }
61648c8cd3fSDouglas Gregor   }
61748c8cd3fSDouglas Gregor };
61848c8cd3fSDouglas Gregor 
61948c8cd3fSDouglas Gregor class PrecompilePreambleAction : public ASTFrontendAction {
62048c8cd3fSDouglas Gregor   ASTUnit &Unit;
62148c8cd3fSDouglas Gregor 
62248c8cd3fSDouglas Gregor public:
62348c8cd3fSDouglas Gregor   explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
62448c8cd3fSDouglas Gregor 
62548c8cd3fSDouglas Gregor   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
62648c8cd3fSDouglas Gregor                                          llvm::StringRef InFile) {
62748c8cd3fSDouglas Gregor     std::string Sysroot;
62848c8cd3fSDouglas Gregor     llvm::raw_ostream *OS = 0;
62948c8cd3fSDouglas Gregor     bool Chaining;
63048c8cd3fSDouglas Gregor     if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
63148c8cd3fSDouglas Gregor                                                        OS, Chaining))
63248c8cd3fSDouglas Gregor       return 0;
63348c8cd3fSDouglas Gregor 
63448c8cd3fSDouglas Gregor     const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
63548c8cd3fSDouglas Gregor                              Sysroot.c_str() : 0;
63648c8cd3fSDouglas Gregor     return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining,
63748c8cd3fSDouglas Gregor                                           isysroot, OS);
63848c8cd3fSDouglas Gregor   }
63948c8cd3fSDouglas Gregor 
64048c8cd3fSDouglas Gregor   virtual bool hasCodeCompletionSupport() const { return false; }
64148c8cd3fSDouglas Gregor   virtual bool hasASTFileSupport() const { return false; }
642028d3e4dSDouglas Gregor   virtual bool usesCompleteTranslationUnit() { return false; }
64348c8cd3fSDouglas Gregor };
64448c8cd3fSDouglas Gregor 
645764c0820SDaniel Dunbar }
646764c0820SDaniel Dunbar 
647aa21cc40SDouglas Gregor /// Parse the source file into a translation unit using the given compiler
648aa21cc40SDouglas Gregor /// invocation, replacing the current translation unit.
649aa21cc40SDouglas Gregor ///
650aa21cc40SDouglas Gregor /// \returns True if a failure occurred that causes the ASTUnit not to
651aa21cc40SDouglas Gregor /// contain any translation-unit information, false otherwise.
6526481ef1fSDouglas Gregor bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
65396c04261SDouglas Gregor   delete SavedMainFileBuffer;
65496c04261SDouglas Gregor   SavedMainFileBuffer = 0;
65596c04261SDouglas Gregor 
656a0734c5fSDouglas Gregor   if (!Invocation.get()) {
657a0734c5fSDouglas Gregor     delete OverrideMainBuffer;
658aa21cc40SDouglas Gregor     return true;
659a0734c5fSDouglas Gregor   }
660aa21cc40SDouglas Gregor 
661764c0820SDaniel Dunbar   // Create the compiler instance to use for building the AST.
6627afbb8c0SDaniel Dunbar   CompilerInstance Clang;
663aa21cc40SDouglas Gregor   Clang.setInvocation(Invocation.take());
664aa21cc40SDouglas Gregor   OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
665764c0820SDaniel Dunbar 
6668e984da8SDouglas Gregor   // Set up diagnostics, capturing any diagnostics that would
6678e984da8SDouglas Gregor   // otherwise be dropped.
668aa21cc40SDouglas Gregor   Clang.setDiagnostics(&getDiagnostics());
6698e984da8SDouglas Gregor   CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
6708e984da8SDouglas Gregor                                     getDiagnostics(),
6718e984da8SDouglas Gregor                                     StoredDiagnostics);
672764c0820SDaniel Dunbar 
673764c0820SDaniel Dunbar   // Create the target instance.
674764c0820SDaniel Dunbar   Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
675764c0820SDaniel Dunbar                                                Clang.getTargetOpts()));
676a0734c5fSDouglas Gregor   if (!Clang.hasTarget()) {
677a0734c5fSDouglas Gregor     delete OverrideMainBuffer;
678aa21cc40SDouglas Gregor     return true;
679a0734c5fSDouglas Gregor   }
680764c0820SDaniel Dunbar 
681764c0820SDaniel Dunbar   // Inform the target of the language options.
682764c0820SDaniel Dunbar   //
683764c0820SDaniel Dunbar   // FIXME: We shouldn't need to do this, the target should be immutable once
684764c0820SDaniel Dunbar   // created. This complexity should be lifted elsewhere.
685764c0820SDaniel Dunbar   Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
686764c0820SDaniel Dunbar 
687764c0820SDaniel Dunbar   assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
688764c0820SDaniel Dunbar          "Invocation must have exactly one source file!");
6899b491e79SDaniel Dunbar   assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
690764c0820SDaniel Dunbar          "FIXME: AST inputs not yet supported here!");
6919507f9ccSDaniel Dunbar   assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
6929507f9ccSDaniel Dunbar          "IR inputs not support here!");
693764c0820SDaniel Dunbar 
694aa21cc40SDouglas Gregor   // Configure the various subsystems.
695aa21cc40SDouglas Gregor   // FIXME: Should we retain the previous file manager?
696aa21cc40SDouglas Gregor   FileMgr.reset(new FileManager);
697aa21cc40SDouglas Gregor   SourceMgr.reset(new SourceManager(getDiagnostics()));
6986fd55e06SDouglas Gregor   TheSema.reset();
699aa21cc40SDouglas Gregor   Ctx.reset();
700aa21cc40SDouglas Gregor   PP.reset();
701aa21cc40SDouglas Gregor 
702aa21cc40SDouglas Gregor   // Clear out old caches and data.
703aa21cc40SDouglas Gregor   TopLevelDecls.clear();
704aa21cc40SDouglas Gregor   CleanTemporaryFiles();
705aa21cc40SDouglas Gregor   PreprocessedEntitiesByFile.clear();
706a8a50937SDaniel Dunbar 
7077b02b583SDouglas Gregor   if (!OverrideMainBuffer) {
708d9a30af2SDouglas Gregor     StoredDiagnostics.clear();
7097b02b583SDouglas Gregor     TopLevelDeclsInPreamble.clear();
7107b02b583SDouglas Gregor   }
711d9a30af2SDouglas Gregor 
712764c0820SDaniel Dunbar   // Create a file manager object to provide access to and cache the filesystem.
713aa21cc40SDouglas Gregor   Clang.setFileManager(&getFileManager());
714764c0820SDaniel Dunbar 
715764c0820SDaniel Dunbar   // Create the source manager.
716aa21cc40SDouglas Gregor   Clang.setSourceManager(&getSourceManager());
717764c0820SDaniel Dunbar 
7183f4bea06SDouglas Gregor   // If the main file has been overridden due to the use of a preamble,
7193f4bea06SDouglas Gregor   // make that override happen and introduce the preamble.
7203f4bea06SDouglas Gregor   PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
7218e984da8SDouglas Gregor   std::string PriorImplicitPCHInclude;
7223f4bea06SDouglas Gregor   if (OverrideMainBuffer) {
7233f4bea06SDouglas Gregor     PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
7243f4bea06SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
7253f4bea06SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second
7263f4bea06SDouglas Gregor                                                     = PreambleEndsAtStartOfLine;
7278e984da8SDouglas Gregor     PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
72815ba0b34SDouglas Gregor     PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
729ce3a8293SDouglas Gregor     PreprocessorOpts.DisablePCHValidation = true;
73096c04261SDouglas Gregor 
73196c04261SDouglas Gregor     // Keep track of the override buffer;
73296c04261SDouglas Gregor     SavedMainFileBuffer = OverrideMainBuffer;
733d9a30af2SDouglas Gregor 
734d9a30af2SDouglas Gregor     // The stored diagnostic has the old source manager in it; update
735d9a30af2SDouglas Gregor     // the locations to refer into the new source manager. Since we've
736d9a30af2SDouglas Gregor     // been careful to make sure that the source manager's state
737d9a30af2SDouglas Gregor     // before and after are identical, so that we can reuse the source
738d9a30af2SDouglas Gregor     // location itself.
739d9a30af2SDouglas Gregor     for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) {
740d9a30af2SDouglas Gregor       FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
741d9a30af2SDouglas Gregor                         getSourceManager());
742d9a30af2SDouglas Gregor       StoredDiagnostics[I].setLocation(Loc);
743d9a30af2SDouglas Gregor     }
7447b02b583SDouglas Gregor   } else {
7457b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
7467b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second = false;
7473f4bea06SDouglas Gregor   }
7483f4bea06SDouglas Gregor 
749aa21cc40SDouglas Gregor   llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
750aa21cc40SDouglas Gregor   Act.reset(new TopLevelDeclTrackerAction(*this));
751644dca07SDaniel Dunbar   if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
7528654638bSDaniel Dunbar                             Clang.getFrontendOpts().Inputs[0].first))
753764c0820SDaniel Dunbar     goto error;
754764c0820SDaniel Dunbar 
755644dca07SDaniel Dunbar   Act->Execute();
756764c0820SDaniel Dunbar 
757d2f8be36SDaniel Dunbar   // Steal the created target, context, and preprocessor, and take back the
758d2f8be36SDaniel Dunbar   // source and file managers.
7596fd55e06SDouglas Gregor   TheSema.reset(Clang.takeSema());
7606fd55e06SDouglas Gregor   Consumer.reset(Clang.takeASTConsumer());
761aa21cc40SDouglas Gregor   Ctx.reset(Clang.takeASTContext());
762aa21cc40SDouglas Gregor   PP.reset(Clang.takePreprocessor());
763764c0820SDaniel Dunbar   Clang.takeSourceManager();
764764c0820SDaniel Dunbar   Clang.takeFileManager();
765aa21cc40SDouglas Gregor   Target.reset(Clang.takeTarget());
766764c0820SDaniel Dunbar 
767644dca07SDaniel Dunbar   Act->EndSourceFile();
768764c0820SDaniel Dunbar 
7693f4bea06SDouglas Gregor   // Remove the overridden buffer we used for the preamble.
7708e984da8SDouglas Gregor   if (OverrideMainBuffer) {
7713f4bea06SDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
7723f4bea06SDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
7738e984da8SDouglas Gregor     PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
7748e984da8SDouglas Gregor   }
7753f4bea06SDouglas Gregor 
776aa21cc40SDouglas Gregor   Invocation.reset(Clang.takeInvocation());
777b14904c4SDouglas Gregor 
778b14904c4SDouglas Gregor   // If we were asked to cache code-completion results and don't have any
779b14904c4SDouglas Gregor   // results yet, do so now.
780b14904c4SDouglas Gregor   if (ShouldCacheCodeCompletionResults && CachedCompletionResults.empty())
781b14904c4SDouglas Gregor     CacheCodeCompletionResults();
782b14904c4SDouglas Gregor 
783aa21cc40SDouglas Gregor   return false;
784764c0820SDaniel Dunbar 
785764c0820SDaniel Dunbar error:
7863f4bea06SDouglas Gregor   // Remove the overridden buffer we used for the preamble.
787ce3a8293SDouglas Gregor   if (OverrideMainBuffer) {
7883f4bea06SDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
7893f4bea06SDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
790ce3a8293SDouglas Gregor     PreprocessorOpts.DisablePCHValidation = true;
7918e984da8SDouglas Gregor     PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
792a0734c5fSDouglas Gregor     delete OverrideMainBuffer;
793ce3a8293SDouglas Gregor   }
7943f4bea06SDouglas Gregor 
795764c0820SDaniel Dunbar   Clang.takeSourceManager();
796764c0820SDaniel Dunbar   Clang.takeFileManager();
797aa21cc40SDouglas Gregor   Invocation.reset(Clang.takeInvocation());
798aa21cc40SDouglas Gregor   return true;
799aa21cc40SDouglas Gregor }
800aa21cc40SDouglas Gregor 
801be2d8c60SDouglas Gregor /// \brief Simple function to retrieve a path for a preamble precompiled header.
802be2d8c60SDouglas Gregor static std::string GetPreamblePCHPath() {
803be2d8c60SDouglas Gregor   // FIXME: This is lame; sys::Path should provide this function (in particular,
804be2d8c60SDouglas Gregor   // it should know how to find the temporary files dir).
805be2d8c60SDouglas Gregor   // FIXME: This is really lame. I copied this code from the Driver!
806be2d8c60SDouglas Gregor   std::string Error;
807be2d8c60SDouglas Gregor   const char *TmpDir = ::getenv("TMPDIR");
808be2d8c60SDouglas Gregor   if (!TmpDir)
809be2d8c60SDouglas Gregor     TmpDir = ::getenv("TEMP");
810be2d8c60SDouglas Gregor   if (!TmpDir)
811be2d8c60SDouglas Gregor     TmpDir = ::getenv("TMP");
812be2d8c60SDouglas Gregor   if (!TmpDir)
813be2d8c60SDouglas Gregor     TmpDir = "/tmp";
814be2d8c60SDouglas Gregor   llvm::sys::Path P(TmpDir);
815be2d8c60SDouglas Gregor   P.appendComponent("preamble");
81620975b25SDouglas Gregor   P.appendSuffix("pch");
817be2d8c60SDouglas Gregor   if (P.createTemporaryFileOnDisk())
818be2d8c60SDouglas Gregor     return std::string();
819be2d8c60SDouglas Gregor 
820be2d8c60SDouglas Gregor   return P.str();
821be2d8c60SDouglas Gregor }
822be2d8c60SDouglas Gregor 
8233f4bea06SDouglas Gregor /// \brief Compute the preamble for the main file, providing the source buffer
8243f4bea06SDouglas Gregor /// that corresponds to the main file along with a pair (bytes, start-of-line)
8253f4bea06SDouglas Gregor /// that describes the preamble.
8263f4bea06SDouglas Gregor std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
827028d3e4dSDouglas Gregor ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
828028d3e4dSDouglas Gregor                          unsigned MaxLines, bool &CreatedBuffer) {
8294dde7498SDouglas Gregor   FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
830be2d8c60SDouglas Gregor   PreprocessorOptions &PreprocessorOpts
8314dde7498SDouglas Gregor     = Invocation.getPreprocessorOpts();
8324dde7498SDouglas Gregor   CreatedBuffer = false;
833be2d8c60SDouglas Gregor 
834be2d8c60SDouglas Gregor   // Try to determine if the main file has been remapped, either from the
835be2d8c60SDouglas Gregor   // command line (to another file) or directly through the compiler invocation
836be2d8c60SDouglas Gregor   // (to a memory buffer).
837be2d8c60SDouglas Gregor   llvm::MemoryBuffer *Buffer = 0;
838be2d8c60SDouglas Gregor   llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
839be2d8c60SDouglas Gregor   if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
840be2d8c60SDouglas Gregor     // Check whether there is a file-file remapping of the main file
841be2d8c60SDouglas Gregor     for (PreprocessorOptions::remapped_file_iterator
842be2d8c60SDouglas Gregor           M = PreprocessorOpts.remapped_file_begin(),
843be2d8c60SDouglas Gregor           E = PreprocessorOpts.remapped_file_end();
844be2d8c60SDouglas Gregor          M != E;
845be2d8c60SDouglas Gregor          ++M) {
846be2d8c60SDouglas Gregor       llvm::sys::PathWithStatus MPath(M->first);
847be2d8c60SDouglas Gregor       if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
848be2d8c60SDouglas Gregor         if (MainFileStatus->uniqueID == MStatus->uniqueID) {
849be2d8c60SDouglas Gregor           // We found a remapping. Try to load the resulting, remapped source.
8504dde7498SDouglas Gregor           if (CreatedBuffer) {
851be2d8c60SDouglas Gregor             delete Buffer;
8524dde7498SDouglas Gregor             CreatedBuffer = false;
8534dde7498SDouglas Gregor           }
8544dde7498SDouglas Gregor 
855be2d8c60SDouglas Gregor           Buffer = llvm::MemoryBuffer::getFile(M->second);
856be2d8c60SDouglas Gregor           if (!Buffer)
8573f4bea06SDouglas Gregor             return std::make_pair((llvm::MemoryBuffer*)0,
8583f4bea06SDouglas Gregor                                   std::make_pair(0, true));
8594dde7498SDouglas Gregor           CreatedBuffer = true;
860be2d8c60SDouglas Gregor 
8614dde7498SDouglas Gregor           // Remove this remapping. We've captured the buffer already.
862be2d8c60SDouglas Gregor           M = PreprocessorOpts.eraseRemappedFile(M);
863be2d8c60SDouglas Gregor           E = PreprocessorOpts.remapped_file_end();
864438c7724SDaniel Dunbar           if (M == E)
865438c7724SDaniel Dunbar             break;
866be2d8c60SDouglas Gregor         }
867be2d8c60SDouglas Gregor       }
868be2d8c60SDouglas Gregor     }
869be2d8c60SDouglas Gregor 
870be2d8c60SDouglas Gregor     // Check whether there is a file-buffer remapping. It supercedes the
871be2d8c60SDouglas Gregor     // file-file remapping.
872be2d8c60SDouglas Gregor     for (PreprocessorOptions::remapped_file_buffer_iterator
873be2d8c60SDouglas Gregor            M = PreprocessorOpts.remapped_file_buffer_begin(),
874be2d8c60SDouglas Gregor            E = PreprocessorOpts.remapped_file_buffer_end();
875be2d8c60SDouglas Gregor          M != E;
876be2d8c60SDouglas Gregor          ++M) {
877be2d8c60SDouglas Gregor       llvm::sys::PathWithStatus MPath(M->first);
878be2d8c60SDouglas Gregor       if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
879be2d8c60SDouglas Gregor         if (MainFileStatus->uniqueID == MStatus->uniqueID) {
880be2d8c60SDouglas Gregor           // We found a remapping.
8814dde7498SDouglas Gregor           if (CreatedBuffer) {
882be2d8c60SDouglas Gregor             delete Buffer;
8834dde7498SDouglas Gregor             CreatedBuffer = false;
8844dde7498SDouglas Gregor           }
8854dde7498SDouglas Gregor 
886be2d8c60SDouglas Gregor           Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
887be2d8c60SDouglas Gregor 
8884dde7498SDouglas Gregor           // Remove this remapping. We've captured the buffer already.
889be2d8c60SDouglas Gregor           M = PreprocessorOpts.eraseRemappedFile(M);
890be2d8c60SDouglas Gregor           E = PreprocessorOpts.remapped_file_buffer_end();
891438c7724SDaniel Dunbar           if (M == E)
892438c7724SDaniel Dunbar             break;
893be2d8c60SDouglas Gregor         }
894be2d8c60SDouglas Gregor       }
895be2d8c60SDouglas Gregor     }
896be2d8c60SDouglas Gregor   }
897be2d8c60SDouglas Gregor 
898be2d8c60SDouglas Gregor   // If the main source file was not remapped, load it now.
899be2d8c60SDouglas Gregor   if (!Buffer) {
900be2d8c60SDouglas Gregor     Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
901be2d8c60SDouglas Gregor     if (!Buffer)
9023f4bea06SDouglas Gregor       return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
9034dde7498SDouglas Gregor 
9044dde7498SDouglas Gregor     CreatedBuffer = true;
905be2d8c60SDouglas Gregor   }
906be2d8c60SDouglas Gregor 
907028d3e4dSDouglas Gregor   return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines));
9084dde7498SDouglas Gregor }
9094dde7498SDouglas Gregor 
9106481ef1fSDouglas Gregor static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
9116481ef1fSDouglas Gregor                                                       bool DeleteOld,
9126481ef1fSDouglas Gregor                                                       unsigned NewSize,
9136481ef1fSDouglas Gregor                                                       llvm::StringRef NewName) {
9146481ef1fSDouglas Gregor   llvm::MemoryBuffer *Result
9156481ef1fSDouglas Gregor     = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
9166481ef1fSDouglas Gregor   memcpy(const_cast<char*>(Result->getBufferStart()),
9176481ef1fSDouglas Gregor          Old->getBufferStart(), Old->getBufferSize());
9186481ef1fSDouglas Gregor   memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
9193f4bea06SDouglas Gregor          ' ', NewSize - Old->getBufferSize() - 1);
9203f4bea06SDouglas Gregor   const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
9216481ef1fSDouglas Gregor 
9226481ef1fSDouglas Gregor   if (DeleteOld)
9236481ef1fSDouglas Gregor     delete Old;
9246481ef1fSDouglas Gregor 
9256481ef1fSDouglas Gregor   return Result;
9266481ef1fSDouglas Gregor }
9276481ef1fSDouglas Gregor 
9284dde7498SDouglas Gregor /// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
9294dde7498SDouglas Gregor /// the source file.
9304dde7498SDouglas Gregor ///
9314dde7498SDouglas Gregor /// This routine will compute the preamble of the main source file. If a
9324dde7498SDouglas Gregor /// non-trivial preamble is found, it will precompile that preamble into a
9334dde7498SDouglas Gregor /// precompiled header so that the precompiled preamble can be used to reduce
9344dde7498SDouglas Gregor /// reparsing time. If a precompiled preamble has already been constructed,
9354dde7498SDouglas Gregor /// this routine will determine if it is still valid and, if so, avoid
9364dde7498SDouglas Gregor /// rebuilding the precompiled preamble.
9374dde7498SDouglas Gregor ///
938028d3e4dSDouglas Gregor /// \param AllowRebuild When true (the default), this routine is
939028d3e4dSDouglas Gregor /// allowed to rebuild the precompiled preamble if it is found to be
940028d3e4dSDouglas Gregor /// out-of-date.
941028d3e4dSDouglas Gregor ///
942028d3e4dSDouglas Gregor /// \param MaxLines When non-zero, the maximum number of lines that
943028d3e4dSDouglas Gregor /// can occur within the preamble.
944028d3e4dSDouglas Gregor ///
9456481ef1fSDouglas Gregor /// \returns If the precompiled preamble can be used, returns a newly-allocated
9466481ef1fSDouglas Gregor /// buffer that should be used in place of the main file when doing so.
9476481ef1fSDouglas Gregor /// Otherwise, returns a NULL pointer.
948028d3e4dSDouglas Gregor llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
949b97b666cSDouglas Gregor                                           CompilerInvocation PreambleInvocation,
950028d3e4dSDouglas Gregor                                                            bool AllowRebuild,
951028d3e4dSDouglas Gregor                                                            unsigned MaxLines) {
9524dde7498SDouglas Gregor   FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
9534dde7498SDouglas Gregor   PreprocessorOptions &PreprocessorOpts
9544dde7498SDouglas Gregor     = PreambleInvocation.getPreprocessorOpts();
9554dde7498SDouglas Gregor 
9564dde7498SDouglas Gregor   bool CreatedPreambleBuffer = false;
9573f4bea06SDouglas Gregor   std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
958028d3e4dSDouglas Gregor     = ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer);
9594dde7498SDouglas Gregor 
9603f4bea06SDouglas Gregor   if (!NewPreamble.second.first) {
9614dde7498SDouglas Gregor     // We couldn't find a preamble in the main source. Clear out the current
9624dde7498SDouglas Gregor     // preamble, if we have one. It's obviously no good any more.
9634dde7498SDouglas Gregor     Preamble.clear();
9644dde7498SDouglas Gregor     if (!PreambleFile.empty()) {
96515ba0b34SDouglas Gregor       llvm::sys::Path(PreambleFile).eraseFromDisk();
9664dde7498SDouglas Gregor       PreambleFile.clear();
9674dde7498SDouglas Gregor     }
9684dde7498SDouglas Gregor     if (CreatedPreambleBuffer)
9694dde7498SDouglas Gregor       delete NewPreamble.first;
9704dde7498SDouglas Gregor 
971bb420abdSDouglas Gregor     // The next time we actually see a preamble, precompile it.
972bb420abdSDouglas Gregor     PreambleRebuildCounter = 1;
9736481ef1fSDouglas Gregor     return 0;
9744dde7498SDouglas Gregor   }
9754dde7498SDouglas Gregor 
9764dde7498SDouglas Gregor   if (!Preamble.empty()) {
9774dde7498SDouglas Gregor     // We've previously computed a preamble. Check whether we have the same
9784dde7498SDouglas Gregor     // preamble now that we did before, and that there's enough space in
9794dde7498SDouglas Gregor     // the main-file buffer within the precompiled preamble to fit the
9804dde7498SDouglas Gregor     // new main file.
9813f4bea06SDouglas Gregor     if (Preamble.size() == NewPreamble.second.first &&
9823f4bea06SDouglas Gregor         PreambleEndsAtStartOfLine == NewPreamble.second.second &&
983f5275a83SDouglas Gregor         NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
9844dde7498SDouglas Gregor         memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
9853f4bea06SDouglas Gregor                NewPreamble.second.first) == 0) {
9864dde7498SDouglas Gregor       // The preamble has not changed. We may be able to re-use the precompiled
9874dde7498SDouglas Gregor       // preamble.
9884dde7498SDouglas Gregor 
9890e11955cSDouglas Gregor       // Check that none of the files used by the preamble have changed.
9900e11955cSDouglas Gregor       bool AnyFileChanged = false;
9914dde7498SDouglas Gregor 
9920e11955cSDouglas Gregor       // First, make a record of those files that have been overridden via
9930e11955cSDouglas Gregor       // remapping or unsaved_files.
9940e11955cSDouglas Gregor       llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
9950e11955cSDouglas Gregor       for (PreprocessorOptions::remapped_file_iterator
9960e11955cSDouglas Gregor                 R = PreprocessorOpts.remapped_file_begin(),
9970e11955cSDouglas Gregor              REnd = PreprocessorOpts.remapped_file_end();
9980e11955cSDouglas Gregor            !AnyFileChanged && R != REnd;
9990e11955cSDouglas Gregor            ++R) {
10000e11955cSDouglas Gregor         struct stat StatBuf;
10010e11955cSDouglas Gregor         if (stat(R->second.c_str(), &StatBuf)) {
10020e11955cSDouglas Gregor           // If we can't stat the file we're remapping to, assume that something
10030e11955cSDouglas Gregor           // horrible happened.
10040e11955cSDouglas Gregor           AnyFileChanged = true;
10050e11955cSDouglas Gregor           break;
10060e11955cSDouglas Gregor         }
10070e11955cSDouglas Gregor 
10080e11955cSDouglas Gregor         OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
10090e11955cSDouglas Gregor                                                    StatBuf.st_mtime);
10100e11955cSDouglas Gregor       }
10110e11955cSDouglas Gregor       for (PreprocessorOptions::remapped_file_buffer_iterator
10120e11955cSDouglas Gregor                 R = PreprocessorOpts.remapped_file_buffer_begin(),
10130e11955cSDouglas Gregor              REnd = PreprocessorOpts.remapped_file_buffer_end();
10140e11955cSDouglas Gregor            !AnyFileChanged && R != REnd;
10150e11955cSDouglas Gregor            ++R) {
10160e11955cSDouglas Gregor         // FIXME: Should we actually compare the contents of file->buffer
10170e11955cSDouglas Gregor         // remappings?
10180e11955cSDouglas Gregor         OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
10190e11955cSDouglas Gregor                                                    0);
10200e11955cSDouglas Gregor       }
10210e11955cSDouglas Gregor 
10220e11955cSDouglas Gregor       // Check whether anything has changed.
10230e11955cSDouglas Gregor       for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
10240e11955cSDouglas Gregor              F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
10250e11955cSDouglas Gregor            !AnyFileChanged && F != FEnd;
10260e11955cSDouglas Gregor            ++F) {
10270e11955cSDouglas Gregor         llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
10280e11955cSDouglas Gregor           = OverriddenFiles.find(F->first());
10290e11955cSDouglas Gregor         if (Overridden != OverriddenFiles.end()) {
10300e11955cSDouglas Gregor           // This file was remapped; check whether the newly-mapped file
10310e11955cSDouglas Gregor           // matches up with the previous mapping.
10320e11955cSDouglas Gregor           if (Overridden->second != F->second)
10330e11955cSDouglas Gregor             AnyFileChanged = true;
10340e11955cSDouglas Gregor           continue;
10350e11955cSDouglas Gregor         }
10360e11955cSDouglas Gregor 
10370e11955cSDouglas Gregor         // The file was not remapped; check whether it has changed on disk.
10380e11955cSDouglas Gregor         struct stat StatBuf;
10390e11955cSDouglas Gregor         if (stat(F->first(), &StatBuf)) {
10400e11955cSDouglas Gregor           // If we can't stat the file, assume that something horrible happened.
10410e11955cSDouglas Gregor           AnyFileChanged = true;
10420e11955cSDouglas Gregor         } else if (StatBuf.st_size != F->second.first ||
10430e11955cSDouglas Gregor                    StatBuf.st_mtime != F->second.second)
10440e11955cSDouglas Gregor           AnyFileChanged = true;
10450e11955cSDouglas Gregor       }
10460e11955cSDouglas Gregor 
10470e11955cSDouglas Gregor       if (!AnyFileChanged) {
1048d9a30af2SDouglas Gregor         // Okay! We can re-use the precompiled preamble.
1049d9a30af2SDouglas Gregor 
1050d9a30af2SDouglas Gregor         // Set the state of the diagnostic object to mimic its state
1051d9a30af2SDouglas Gregor         // after parsing the preamble.
1052d9a30af2SDouglas Gregor         getDiagnostics().Reset();
1053d9a30af2SDouglas Gregor         getDiagnostics().setNumWarnings(NumWarningsInPreamble);
1054d9a30af2SDouglas Gregor         if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
1055d9a30af2SDouglas Gregor           StoredDiagnostics.erase(
1056d9a30af2SDouglas Gregor             StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
1057d9a30af2SDouglas Gregor                                   StoredDiagnostics.end());
1058d9a30af2SDouglas Gregor 
1059d9a30af2SDouglas Gregor         // Create a version of the main file buffer that is padded to
1060d9a30af2SDouglas Gregor         // buffer size we reserved when creating the preamble.
10616481ef1fSDouglas Gregor         return CreatePaddedMainFileBuffer(NewPreamble.first,
10626481ef1fSDouglas Gregor                                           CreatedPreambleBuffer,
10636481ef1fSDouglas Gregor                                           PreambleReservedSize,
10646481ef1fSDouglas Gregor                                           FrontendOpts.Inputs[0].second);
10654dde7498SDouglas Gregor       }
10660e11955cSDouglas Gregor     }
10674dde7498SDouglas Gregor 
1068028d3e4dSDouglas Gregor     // If we aren't allowed to rebuild the precompiled preamble, just
1069028d3e4dSDouglas Gregor     // return now.
1070028d3e4dSDouglas Gregor     if (!AllowRebuild)
1071028d3e4dSDouglas Gregor       return 0;
1072028d3e4dSDouglas Gregor 
10734dde7498SDouglas Gregor     // We can't reuse the previously-computed preamble. Build a new one.
10744dde7498SDouglas Gregor     Preamble.clear();
107515ba0b34SDouglas Gregor     llvm::sys::Path(PreambleFile).eraseFromDisk();
1076bb420abdSDouglas Gregor     PreambleRebuildCounter = 1;
1077028d3e4dSDouglas Gregor   } else if (!AllowRebuild) {
1078028d3e4dSDouglas Gregor     // We aren't allowed to rebuild the precompiled preamble; just
1079028d3e4dSDouglas Gregor     // return now.
1080028d3e4dSDouglas Gregor     return 0;
1081bb420abdSDouglas Gregor   }
1082bb420abdSDouglas Gregor 
1083bb420abdSDouglas Gregor   // If the preamble rebuild counter > 1, it's because we previously
1084bb420abdSDouglas Gregor   // failed to build a preamble and we're not yet ready to try
1085bb420abdSDouglas Gregor   // again. Decrement the counter and return a failure.
1086bb420abdSDouglas Gregor   if (PreambleRebuildCounter > 1) {
1087bb420abdSDouglas Gregor     --PreambleRebuildCounter;
1088bb420abdSDouglas Gregor     return 0;
10894dde7498SDouglas Gregor   }
10904dde7498SDouglas Gregor 
10914dde7498SDouglas Gregor   // We did not previously compute a preamble, or it can't be reused anyway.
109215ba0b34SDouglas Gregor   llvm::Timer *PreambleTimer = 0;
109315ba0b34SDouglas Gregor   if (TimerGroup.get()) {
109415ba0b34SDouglas Gregor     PreambleTimer = new llvm::Timer("Precompiling preamble", *TimerGroup);
109515ba0b34SDouglas Gregor     PreambleTimer->startTimer();
109615ba0b34SDouglas Gregor     Timers.push_back(PreambleTimer);
109715ba0b34SDouglas Gregor   }
1098be2d8c60SDouglas Gregor 
1099be2d8c60SDouglas Gregor   // Create a new buffer that stores the preamble. The buffer also contains
1100be2d8c60SDouglas Gregor   // extra space for the original contents of the file (which will be present
1101be2d8c60SDouglas Gregor   // when we actually parse the file) along with more room in case the file
1102be2d8c60SDouglas Gregor   // grows.
11034dde7498SDouglas Gregor   PreambleReservedSize = NewPreamble.first->getBufferSize();
11044dde7498SDouglas Gregor   if (PreambleReservedSize < 4096)
11053f4bea06SDouglas Gregor     PreambleReservedSize = 8191;
1106be2d8c60SDouglas Gregor   else
11074dde7498SDouglas Gregor     PreambleReservedSize *= 2;
1108be2d8c60SDouglas Gregor 
1109d9a30af2SDouglas Gregor   // Save the preamble text for later; we'll need to compare against it for
1110d9a30af2SDouglas Gregor   // subsequent reparses.
1111d9a30af2SDouglas Gregor   Preamble.assign(NewPreamble.first->getBufferStart(),
1112d9a30af2SDouglas Gregor                   NewPreamble.first->getBufferStart()
1113d9a30af2SDouglas Gregor                                                   + NewPreamble.second.first);
1114d9a30af2SDouglas Gregor   PreambleEndsAtStartOfLine = NewPreamble.second.second;
1115d9a30af2SDouglas Gregor 
1116a0734c5fSDouglas Gregor   delete PreambleBuffer;
1117a0734c5fSDouglas Gregor   PreambleBuffer
11184dde7498SDouglas Gregor     = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
1119be2d8c60SDouglas Gregor                                                 FrontendOpts.Inputs[0].second);
1120be2d8c60SDouglas Gregor   memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
11214dde7498SDouglas Gregor          NewPreamble.first->getBufferStart(), Preamble.size());
11224dde7498SDouglas Gregor   memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
11233f4bea06SDouglas Gregor          ' ', PreambleReservedSize - Preamble.size() - 1);
11243f4bea06SDouglas Gregor   const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
11254dde7498SDouglas Gregor 
1126be2d8c60SDouglas Gregor   // Remap the main source file to the preamble buffer.
11274dde7498SDouglas Gregor   llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
1128be2d8c60SDouglas Gregor   PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
1129be2d8c60SDouglas Gregor 
1130be2d8c60SDouglas Gregor   // Tell the compiler invocation to generate a temporary precompiled header.
1131be2d8c60SDouglas Gregor   FrontendOpts.ProgramAction = frontend::GeneratePCH;
1132e98428d7SSebastian Redl   // FIXME: Set ChainedPCH unconditionally, once it is ready.
1133e98428d7SSebastian Redl   if (::getenv("LIBCLANG_CHAINING"))
1134e98428d7SSebastian Redl     FrontendOpts.ChainedPCH = true;
1135be2d8c60SDouglas Gregor   // FIXME: Generate the precompiled header into memory?
1136be2d8c60SDouglas Gregor   FrontendOpts.OutputFile = GetPreamblePCHPath();
1137be2d8c60SDouglas Gregor 
1138be2d8c60SDouglas Gregor   // Create the compiler instance to use for building the precompiled preamble.
1139be2d8c60SDouglas Gregor   CompilerInstance Clang;
1140be2d8c60SDouglas Gregor   Clang.setInvocation(&PreambleInvocation);
1141be2d8c60SDouglas Gregor   OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
1142be2d8c60SDouglas Gregor 
11438e984da8SDouglas Gregor   // Set up diagnostics, capturing all of the diagnostics produced.
1144be2d8c60SDouglas Gregor   Clang.setDiagnostics(&getDiagnostics());
11458e984da8SDouglas Gregor   CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
11468e984da8SDouglas Gregor                                     getDiagnostics(),
11478e984da8SDouglas Gregor                                     StoredDiagnostics);
1148be2d8c60SDouglas Gregor 
1149be2d8c60SDouglas Gregor   // Create the target instance.
1150be2d8c60SDouglas Gregor   Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
1151be2d8c60SDouglas Gregor                                                Clang.getTargetOpts()));
1152be2d8c60SDouglas Gregor   if (!Clang.hasTarget()) {
11534dde7498SDouglas Gregor     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
11544dde7498SDouglas Gregor     Preamble.clear();
11554dde7498SDouglas Gregor     if (CreatedPreambleBuffer)
11564dde7498SDouglas Gregor       delete NewPreamble.first;
115715ba0b34SDouglas Gregor     if (PreambleTimer)
115815ba0b34SDouglas Gregor       PreambleTimer->stopTimer();
1159bb420abdSDouglas Gregor     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
1160a0734c5fSDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
1161a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
11626481ef1fSDouglas Gregor     return 0;
1163be2d8c60SDouglas Gregor   }
1164be2d8c60SDouglas Gregor 
1165be2d8c60SDouglas Gregor   // Inform the target of the language options.
1166be2d8c60SDouglas Gregor   //
1167be2d8c60SDouglas Gregor   // FIXME: We shouldn't need to do this, the target should be immutable once
1168be2d8c60SDouglas Gregor   // created. This complexity should be lifted elsewhere.
1169be2d8c60SDouglas Gregor   Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
1170be2d8c60SDouglas Gregor 
1171be2d8c60SDouglas Gregor   assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
1172be2d8c60SDouglas Gregor          "Invocation must have exactly one source file!");
1173be2d8c60SDouglas Gregor   assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
1174be2d8c60SDouglas Gregor          "FIXME: AST inputs not yet supported here!");
1175be2d8c60SDouglas Gregor   assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1176be2d8c60SDouglas Gregor          "IR inputs not support here!");
1177be2d8c60SDouglas Gregor 
1178be2d8c60SDouglas Gregor   // Clear out old caches and data.
1179be2d8c60SDouglas Gregor   StoredDiagnostics.clear();
1180e9db88f9SDouglas Gregor   TopLevelDecls.clear();
1181e9db88f9SDouglas Gregor   TopLevelDeclsInPreamble.clear();
1182be2d8c60SDouglas Gregor 
1183be2d8c60SDouglas Gregor   // Create a file manager object to provide access to and cache the filesystem.
1184be2d8c60SDouglas Gregor   Clang.setFileManager(new FileManager);
1185be2d8c60SDouglas Gregor 
1186be2d8c60SDouglas Gregor   // Create the source manager.
1187be2d8c60SDouglas Gregor   Clang.setSourceManager(new SourceManager(getDiagnostics()));
1188be2d8c60SDouglas Gregor 
118948c8cd3fSDouglas Gregor   llvm::OwningPtr<PrecompilePreambleAction> Act;
119048c8cd3fSDouglas Gregor   Act.reset(new PrecompilePreambleAction(*this));
1191be2d8c60SDouglas Gregor   if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
1192be2d8c60SDouglas Gregor                             Clang.getFrontendOpts().Inputs[0].first)) {
1193be2d8c60SDouglas Gregor     Clang.takeInvocation();
11944dde7498SDouglas Gregor     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
11954dde7498SDouglas Gregor     Preamble.clear();
11964dde7498SDouglas Gregor     if (CreatedPreambleBuffer)
11974dde7498SDouglas Gregor       delete NewPreamble.first;
119815ba0b34SDouglas Gregor     if (PreambleTimer)
119915ba0b34SDouglas Gregor       PreambleTimer->stopTimer();
1200bb420abdSDouglas Gregor     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
1201a0734c5fSDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
1202a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
12036481ef1fSDouglas Gregor     return 0;
1204be2d8c60SDouglas Gregor   }
1205be2d8c60SDouglas Gregor 
1206be2d8c60SDouglas Gregor   Act->Execute();
1207be2d8c60SDouglas Gregor   Act->EndSourceFile();
1208be2d8c60SDouglas Gregor   Clang.takeInvocation();
1209be2d8c60SDouglas Gregor 
1210e9db88f9SDouglas Gregor   if (Diagnostics->hasErrorOccurred()) {
12114dde7498SDouglas Gregor     // There were errors parsing the preamble, so no precompiled header was
12124dde7498SDouglas Gregor     // generated. Forget that we even tried.
12134dde7498SDouglas Gregor     // FIXME: Should we leave a note for ourselves to try again?
12144dde7498SDouglas Gregor     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
12154dde7498SDouglas Gregor     Preamble.clear();
12164dde7498SDouglas Gregor     if (CreatedPreambleBuffer)
12174dde7498SDouglas Gregor       delete NewPreamble.first;
121815ba0b34SDouglas Gregor     if (PreambleTimer)
121915ba0b34SDouglas Gregor       PreambleTimer->stopTimer();
1220e9db88f9SDouglas Gregor     TopLevelDeclsInPreamble.clear();
1221bb420abdSDouglas Gregor     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
1222a0734c5fSDouglas Gregor     PreprocessorOpts.eraseRemappedFile(
1223a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
12246481ef1fSDouglas Gregor     return 0;
12254dde7498SDouglas Gregor   }
12264dde7498SDouglas Gregor 
12274dde7498SDouglas Gregor   // Keep track of the preamble we precompiled.
12284dde7498SDouglas Gregor   PreambleFile = FrontendOpts.OutputFile;
1229d9a30af2SDouglas Gregor   NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
1230d9a30af2SDouglas Gregor   NumWarningsInPreamble = getDiagnostics().getNumWarnings();
12310e11955cSDouglas Gregor 
12320e11955cSDouglas Gregor   // Keep track of all of the files that the source manager knows about,
12330e11955cSDouglas Gregor   // so we can verify whether they have changed or not.
12340e11955cSDouglas Gregor   FilesInPreamble.clear();
12350e11955cSDouglas Gregor   SourceManager &SourceMgr = Clang.getSourceManager();
12360e11955cSDouglas Gregor   const llvm::MemoryBuffer *MainFileBuffer
12370e11955cSDouglas Gregor     = SourceMgr.getBuffer(SourceMgr.getMainFileID());
12380e11955cSDouglas Gregor   for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
12390e11955cSDouglas Gregor                                      FEnd = SourceMgr.fileinfo_end();
12400e11955cSDouglas Gregor        F != FEnd;
12410e11955cSDouglas Gregor        ++F) {
12420e11955cSDouglas Gregor     const FileEntry *File = F->second->Entry;
12430e11955cSDouglas Gregor     if (!File || F->second->getRawBuffer() == MainFileBuffer)
12440e11955cSDouglas Gregor       continue;
12450e11955cSDouglas Gregor 
12460e11955cSDouglas Gregor     FilesInPreamble[File->getName()]
12470e11955cSDouglas Gregor       = std::make_pair(F->second->getSize(), File->getModificationTime());
12480e11955cSDouglas Gregor   }
12490e11955cSDouglas Gregor 
125015ba0b34SDouglas Gregor   if (PreambleTimer)
125115ba0b34SDouglas Gregor     PreambleTimer->stopTimer();
125215ba0b34SDouglas Gregor 
1253bb420abdSDouglas Gregor   PreambleRebuildCounter = 1;
1254a0734c5fSDouglas Gregor   PreprocessorOpts.eraseRemappedFile(
1255a0734c5fSDouglas Gregor                                PreprocessorOpts.remapped_file_buffer_end() - 1);
12566481ef1fSDouglas Gregor   return CreatePaddedMainFileBuffer(NewPreamble.first,
12576481ef1fSDouglas Gregor                                     CreatedPreambleBuffer,
12586481ef1fSDouglas Gregor                                     PreambleReservedSize,
12596481ef1fSDouglas Gregor                                     FrontendOpts.Inputs[0].second);
1260be2d8c60SDouglas Gregor }
1261aa21cc40SDouglas Gregor 
1262e9db88f9SDouglas Gregor void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
1263e9db88f9SDouglas Gregor   std::vector<Decl *> Resolved;
1264e9db88f9SDouglas Gregor   Resolved.reserve(TopLevelDeclsInPreamble.size());
1265e9db88f9SDouglas Gregor   ExternalASTSource &Source = *getASTContext().getExternalSource();
1266e9db88f9SDouglas Gregor   for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
1267e9db88f9SDouglas Gregor     // Resolve the declaration ID to an actual declaration, possibly
1268e9db88f9SDouglas Gregor     // deserializing the declaration in the process.
1269e9db88f9SDouglas Gregor     Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
1270e9db88f9SDouglas Gregor     if (D)
1271e9db88f9SDouglas Gregor       Resolved.push_back(D);
1272e9db88f9SDouglas Gregor   }
1273e9db88f9SDouglas Gregor   TopLevelDeclsInPreamble.clear();
1274e9db88f9SDouglas Gregor   TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
1275e9db88f9SDouglas Gregor }
1276e9db88f9SDouglas Gregor 
1277e9db88f9SDouglas Gregor unsigned ASTUnit::getMaxPCHLevel() const {
1278e9db88f9SDouglas Gregor   if (!getOnlyLocalDecls())
1279e9db88f9SDouglas Gregor     return Decl::MaxPCHLevel;
1280e9db88f9SDouglas Gregor 
1281e9db88f9SDouglas Gregor   unsigned Result = 0;
1282e9db88f9SDouglas Gregor   if (isMainFileAST() || SavedMainFileBuffer)
1283e9db88f9SDouglas Gregor     ++Result;
1284e9db88f9SDouglas Gregor   return Result;
1285e9db88f9SDouglas Gregor }
1286e9db88f9SDouglas Gregor 
1287aa21cc40SDouglas Gregor ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
1288aa21cc40SDouglas Gregor                                    llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
1289aa21cc40SDouglas Gregor                                              bool OnlyLocalDecls,
1290be2d8c60SDouglas Gregor                                              bool CaptureDiagnostics,
1291028d3e4dSDouglas Gregor                                              bool PrecompilePreamble,
1292b14904c4SDouglas Gregor                                              bool CompleteTranslationUnit,
1293b14904c4SDouglas Gregor                                              bool CacheCodeCompletionResults) {
1294aa21cc40SDouglas Gregor   if (!Diags.getPtr()) {
1295aa21cc40SDouglas Gregor     // No diagnostics engine was provided, so create our own diagnostics object
1296aa21cc40SDouglas Gregor     // with the default options.
1297aa21cc40SDouglas Gregor     DiagnosticOptions DiagOpts;
1298aa21cc40SDouglas Gregor     Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
1299aa21cc40SDouglas Gregor   }
1300aa21cc40SDouglas Gregor 
1301aa21cc40SDouglas Gregor   // Create the AST unit.
1302aa21cc40SDouglas Gregor   llvm::OwningPtr<ASTUnit> AST;
1303aa21cc40SDouglas Gregor   AST.reset(new ASTUnit(false));
1304aa21cc40SDouglas Gregor   AST->Diagnostics = Diags;
1305aa21cc40SDouglas Gregor   AST->CaptureDiagnostics = CaptureDiagnostics;
1306aa21cc40SDouglas Gregor   AST->OnlyLocalDecls = OnlyLocalDecls;
1307028d3e4dSDouglas Gregor   AST->CompleteTranslationUnit = CompleteTranslationUnit;
1308b14904c4SDouglas Gregor   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
1309aa21cc40SDouglas Gregor   AST->Invocation.reset(CI);
13103f4bea06SDouglas Gregor   CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1311aa21cc40SDouglas Gregor 
131215ba0b34SDouglas Gregor   if (getenv("LIBCLANG_TIMING"))
131315ba0b34SDouglas Gregor     AST->TimerGroup.reset(
131415ba0b34SDouglas Gregor                   new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
131515ba0b34SDouglas Gregor 
131615ba0b34SDouglas Gregor 
13176481ef1fSDouglas Gregor   llvm::MemoryBuffer *OverrideMainBuffer = 0;
1318a5fd5229SDouglas Gregor   // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
1319bb420abdSDouglas Gregor   if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
1320bb420abdSDouglas Gregor     AST->PreambleRebuildCounter = 1;
1321b97b666cSDouglas Gregor     OverrideMainBuffer
1322b97b666cSDouglas Gregor       = AST->getMainBufferWithPrecompiledPreamble(*AST->Invocation);
1323bb420abdSDouglas Gregor   }
1324be2d8c60SDouglas Gregor 
132515ba0b34SDouglas Gregor   llvm::Timer *ParsingTimer = 0;
132615ba0b34SDouglas Gregor   if (AST->TimerGroup.get()) {
132715ba0b34SDouglas Gregor     ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
132815ba0b34SDouglas Gregor     ParsingTimer->startTimer();
132915ba0b34SDouglas Gregor     AST->Timers.push_back(ParsingTimer);
133015ba0b34SDouglas Gregor   }
1331aa21cc40SDouglas Gregor 
133215ba0b34SDouglas Gregor   bool Failed = AST->Parse(OverrideMainBuffer);
133315ba0b34SDouglas Gregor   if (ParsingTimer)
133415ba0b34SDouglas Gregor     ParsingTimer->stopTimer();
133515ba0b34SDouglas Gregor 
133615ba0b34SDouglas Gregor   return Failed? 0 : AST.take();
1337764c0820SDaniel Dunbar }
133855a17b66SDaniel Dunbar 
133955a17b66SDaniel Dunbar ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
134055a17b66SDaniel Dunbar                                       const char **ArgEnd,
13417f95d26eSDouglas Gregor                                     llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
13428d4a202aSDaniel Dunbar                                       llvm::StringRef ResourceFilesPath,
134355a17b66SDaniel Dunbar                                       bool OnlyLocalDecls,
1344aa98ed9aSDouglas Gregor                                       RemappedFile *RemappedFiles,
134533cdd810SDouglas Gregor                                       unsigned NumRemappedFiles,
1346be2d8c60SDouglas Gregor                                       bool CaptureDiagnostics,
1347028d3e4dSDouglas Gregor                                       bool PrecompilePreamble,
1348b14904c4SDouglas Gregor                                       bool CompleteTranslationUnit,
1349b14904c4SDouglas Gregor                                       bool CacheCodeCompletionResults) {
13502dd19f1dSDouglas Gregor   bool CreatedDiagnosticsObject = false;
13512dd19f1dSDouglas Gregor 
13527f95d26eSDouglas Gregor   if (!Diags.getPtr()) {
1353d03e823fSDouglas Gregor     // No diagnostics engine was provided, so create our own diagnostics object
1354d03e823fSDouglas Gregor     // with the default options.
1355d03e823fSDouglas Gregor     DiagnosticOptions DiagOpts;
13567f95d26eSDouglas Gregor     Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
13572dd19f1dSDouglas Gregor     CreatedDiagnosticsObject = true;
1358d03e823fSDouglas Gregor   }
1359d03e823fSDouglas Gregor 
136055a17b66SDaniel Dunbar   llvm::SmallVector<const char *, 16> Args;
136155a17b66SDaniel Dunbar   Args.push_back("<clang>"); // FIXME: Remove dummy argument.
136255a17b66SDaniel Dunbar   Args.insert(Args.end(), ArgBegin, ArgEnd);
136355a17b66SDaniel Dunbar 
136455a17b66SDaniel Dunbar   // FIXME: Find a cleaner way to force the driver into restricted modes. We
136555a17b66SDaniel Dunbar   // also want to force it to use clang.
136655a17b66SDaniel Dunbar   Args.push_back("-fsyntax-only");
136755a17b66SDaniel Dunbar 
13688d4a202aSDaniel Dunbar   // FIXME: We shouldn't have to pass in the path info.
1369e38764c6SDaniel Dunbar   driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
1370d03e823fSDouglas Gregor                            "a.out", false, false, *Diags);
1371fcf2d428SDaniel Dunbar 
1372fcf2d428SDaniel Dunbar   // Don't check that inputs exist, they have been remapped.
1373fcf2d428SDaniel Dunbar   TheDriver.setCheckInputsExist(false);
1374fcf2d428SDaniel Dunbar 
137555a17b66SDaniel Dunbar   llvm::OwningPtr<driver::Compilation> C(
137655a17b66SDaniel Dunbar     TheDriver.BuildCompilation(Args.size(), Args.data()));
137755a17b66SDaniel Dunbar 
137855a17b66SDaniel Dunbar   // We expect to get back exactly one command job, if we didn't something
137955a17b66SDaniel Dunbar   // failed.
138055a17b66SDaniel Dunbar   const driver::JobList &Jobs = C->getJobs();
138155a17b66SDaniel Dunbar   if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
138255a17b66SDaniel Dunbar     llvm::SmallString<256> Msg;
138355a17b66SDaniel Dunbar     llvm::raw_svector_ostream OS(Msg);
138455a17b66SDaniel Dunbar     C->PrintJob(OS, C->getJobs(), "; ", true);
1385d03e823fSDouglas Gregor     Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
138655a17b66SDaniel Dunbar     return 0;
138755a17b66SDaniel Dunbar   }
138855a17b66SDaniel Dunbar 
138955a17b66SDaniel Dunbar   const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
139055a17b66SDaniel Dunbar   if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
1391d03e823fSDouglas Gregor     Diags->Report(diag::err_fe_expected_clang_command);
139255a17b66SDaniel Dunbar     return 0;
139355a17b66SDaniel Dunbar   }
139455a17b66SDaniel Dunbar 
139555a17b66SDaniel Dunbar   const driver::ArgStringList &CCArgs = Cmd->getArguments();
13966b03ecefSDaniel Dunbar   llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
1397145f3f1eSDan Gohman   CompilerInvocation::CreateFromArgs(*CI,
1398145f3f1eSDan Gohman                                      const_cast<const char **>(CCArgs.data()),
1399145f3f1eSDan Gohman                                      const_cast<const char **>(CCArgs.data()) +
1400145f3f1eSDan Gohman                                      CCArgs.size(),
1401d03e823fSDouglas Gregor                                      *Diags);
1402d613677eSDaniel Dunbar 
1403aa98ed9aSDouglas Gregor   // Override any files that need remapping
1404aa98ed9aSDouglas Gregor   for (unsigned I = 0; I != NumRemappedFiles; ++I)
14056b03ecefSDaniel Dunbar     CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1406aa98ed9aSDouglas Gregor                                               RemappedFiles[I].second);
1407aa98ed9aSDouglas Gregor 
1408a5a166d0SDaniel Dunbar   // Override the resources path.
14096b03ecefSDaniel Dunbar   CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
141055a17b66SDaniel Dunbar 
14114c6ed904SDouglas Gregor   CI->getFrontendOpts().DisableFree = false;
141233cdd810SDouglas Gregor   return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
1413028d3e4dSDouglas Gregor                                     CaptureDiagnostics, PrecompilePreamble,
1414b14904c4SDouglas Gregor                                     CompleteTranslationUnit,
1415b14904c4SDouglas Gregor                                     CacheCodeCompletionResults);
141655a17b66SDaniel Dunbar }
1417aa21cc40SDouglas Gregor 
1418aa21cc40SDouglas Gregor bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
1419aa21cc40SDouglas Gregor   if (!Invocation.get())
1420aa21cc40SDouglas Gregor     return true;
1421aa21cc40SDouglas Gregor 
142215ba0b34SDouglas Gregor   llvm::Timer *ReparsingTimer = 0;
142315ba0b34SDouglas Gregor   if (TimerGroup.get()) {
142415ba0b34SDouglas Gregor     ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup);
142515ba0b34SDouglas Gregor     ReparsingTimer->startTimer();
142615ba0b34SDouglas Gregor     Timers.push_back(ReparsingTimer);
142715ba0b34SDouglas Gregor   }
142815ba0b34SDouglas Gregor 
14290e11955cSDouglas Gregor   // Remap files.
14307b02b583SDouglas Gregor   PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
14317b02b583SDouglas Gregor   for (PreprocessorOptions::remapped_file_buffer_iterator
14327b02b583SDouglas Gregor          R = PPOpts.remapped_file_buffer_begin(),
14337b02b583SDouglas Gregor          REnd = PPOpts.remapped_file_buffer_end();
14347b02b583SDouglas Gregor        R != REnd;
14357b02b583SDouglas Gregor        ++R) {
14367b02b583SDouglas Gregor     delete R->second;
14377b02b583SDouglas Gregor   }
14380e11955cSDouglas Gregor   Invocation->getPreprocessorOpts().clearRemappedFiles();
14390e11955cSDouglas Gregor   for (unsigned I = 0; I != NumRemappedFiles; ++I)
14400e11955cSDouglas Gregor     Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
14410e11955cSDouglas Gregor                                                       RemappedFiles[I].second);
14420e11955cSDouglas Gregor 
1443bb420abdSDouglas Gregor   // If we have a preamble file lying around, or if we might try to
1444bb420abdSDouglas Gregor   // build a precompiled preamble, do so now.
14456481ef1fSDouglas Gregor   llvm::MemoryBuffer *OverrideMainBuffer = 0;
1446bb420abdSDouglas Gregor   if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
1447b97b666cSDouglas Gregor     OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
14484dde7498SDouglas Gregor 
1449aa21cc40SDouglas Gregor   // Clear out the diagnostics state.
1450d9a30af2SDouglas Gregor   if (!OverrideMainBuffer)
1451aa21cc40SDouglas Gregor     getDiagnostics().Reset();
1452aa21cc40SDouglas Gregor 
14534dde7498SDouglas Gregor   // Parse the sources
14546481ef1fSDouglas Gregor   bool Result = Parse(OverrideMainBuffer);
145515ba0b34SDouglas Gregor   if (ReparsingTimer)
145615ba0b34SDouglas Gregor     ReparsingTimer->stopTimer();
14572c8bd47aSDouglas Gregor 
14582c8bd47aSDouglas Gregor   if (ShouldCacheCodeCompletionResults) {
14592c8bd47aSDouglas Gregor     if (CacheCodeCompletionCoolDown > 0)
14602c8bd47aSDouglas Gregor       --CacheCodeCompletionCoolDown;
14612c8bd47aSDouglas Gregor     else if (top_level_size() != NumTopLevelDeclsAtLastCompletionCache)
14622c8bd47aSDouglas Gregor       CacheCodeCompletionResults();
14632c8bd47aSDouglas Gregor   }
14642c8bd47aSDouglas Gregor 
14654dde7498SDouglas Gregor   return Result;
1466aa21cc40SDouglas Gregor }
14678e984da8SDouglas Gregor 
1468b14904c4SDouglas Gregor //----------------------------------------------------------------------------//
1469b14904c4SDouglas Gregor // Code completion
1470b14904c4SDouglas Gregor //----------------------------------------------------------------------------//
1471b14904c4SDouglas Gregor 
1472b14904c4SDouglas Gregor namespace {
1473b14904c4SDouglas Gregor   /// \brief Code completion consumer that combines the cached code-completion
1474b14904c4SDouglas Gregor   /// results from an ASTUnit with the code-completion results provided to it,
1475b14904c4SDouglas Gregor   /// then passes the result on to
1476b14904c4SDouglas Gregor   class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
1477b14904c4SDouglas Gregor     unsigned NormalContexts;
1478b14904c4SDouglas Gregor     ASTUnit &AST;
1479b14904c4SDouglas Gregor     CodeCompleteConsumer &Next;
1480b14904c4SDouglas Gregor 
1481b14904c4SDouglas Gregor   public:
1482b14904c4SDouglas Gregor     AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
148339982197SDouglas Gregor                                   bool IncludeMacros, bool IncludeCodePatterns,
148439982197SDouglas Gregor                                   bool IncludeGlobals)
148539982197SDouglas Gregor       : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
1486b14904c4SDouglas Gregor                              Next.isOutputBinary()), AST(AST), Next(Next)
1487b14904c4SDouglas Gregor     {
1488b14904c4SDouglas Gregor       // Compute the set of contexts in which we will look when we don't have
1489b14904c4SDouglas Gregor       // any information about the specific context.
1490b14904c4SDouglas Gregor       NormalContexts
1491b14904c4SDouglas Gregor         = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
1492b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
1493b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
1494b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
1495b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_Statement - 1))
1496b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_Expression - 1))
1497b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
1498b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
1499b14904c4SDouglas Gregor         | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
1500b14904c4SDouglas Gregor 
1501b14904c4SDouglas Gregor       if (AST.getASTContext().getLangOptions().CPlusPlus)
1502b14904c4SDouglas Gregor         NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1))
1503b14904c4SDouglas Gregor                     | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
1504b14904c4SDouglas Gregor                     | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
1505b14904c4SDouglas Gregor     }
1506b14904c4SDouglas Gregor 
1507b14904c4SDouglas Gregor     virtual void ProcessCodeCompleteResults(Sema &S,
1508b14904c4SDouglas Gregor                                             CodeCompletionContext Context,
1509b14904c4SDouglas Gregor                                             Result *Results,
1510d46cf182SDouglas Gregor                                             unsigned NumResults);
1511d46cf182SDouglas Gregor 
1512d46cf182SDouglas Gregor     virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
1513d46cf182SDouglas Gregor                                            OverloadCandidate *Candidates,
1514d46cf182SDouglas Gregor                                            unsigned NumCandidates) {
1515d46cf182SDouglas Gregor       Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
1516d46cf182SDouglas Gregor     }
1517d46cf182SDouglas Gregor   };
1518d46cf182SDouglas Gregor }
1519d46cf182SDouglas Gregor 
15206199f2d1SDouglas Gregor /// \brief Helper function that computes which global names are hidden by the
15216199f2d1SDouglas Gregor /// local code-completion results.
15226199f2d1SDouglas Gregor void CalculateHiddenNames(const CodeCompletionContext &Context,
15236199f2d1SDouglas Gregor                           CodeCompleteConsumer::Result *Results,
15246199f2d1SDouglas Gregor                           unsigned NumResults,
15256199f2d1SDouglas Gregor                           ASTContext &Ctx,
15266199f2d1SDouglas Gregor                           llvm::StringSet<> &HiddenNames) {
15276199f2d1SDouglas Gregor   bool OnlyTagNames = false;
15286199f2d1SDouglas Gregor   switch (Context.getKind()) {
15296199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Other:
15306199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_TopLevel:
15316199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCInterface:
15326199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCImplementation:
15336199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCIvarList:
15346199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ClassStructUnion:
15356199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Statement:
15366199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Expression:
15376199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCMessageReceiver:
15386199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_MemberAccess:
15396199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Namespace:
15406199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_Type:
1541c49f5b2fSDouglas Gregor   case CodeCompletionContext::CCC_Name:
1542c49f5b2fSDouglas Gregor   case CodeCompletionContext::CCC_PotentiallyQualifiedName:
15436199f2d1SDouglas Gregor     break;
15446199f2d1SDouglas Gregor 
15456199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_EnumTag:
15466199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_UnionTag:
15476199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ClassOrStructTag:
15486199f2d1SDouglas Gregor     OnlyTagNames = true;
15496199f2d1SDouglas Gregor     break;
15506199f2d1SDouglas Gregor 
15516199f2d1SDouglas Gregor   case CodeCompletionContext::CCC_ObjCProtocolName:
155212785108SDouglas Gregor   case CodeCompletionContext::CCC_MacroName:
155312785108SDouglas Gregor   case CodeCompletionContext::CCC_MacroNameUse:
1554*ec00a268SDouglas Gregor   case CodeCompletionContext::CCC_PreprocessorExpression:
155512785108SDouglas Gregor     // If we're just looking for protocol or macro names, nothing can hide them.
15566199f2d1SDouglas Gregor     return;
15576199f2d1SDouglas Gregor   }
15586199f2d1SDouglas Gregor 
15596199f2d1SDouglas Gregor   typedef CodeCompleteConsumer::Result Result;
15606199f2d1SDouglas Gregor   for (unsigned I = 0; I != NumResults; ++I) {
15616199f2d1SDouglas Gregor     if (Results[I].Kind != Result::RK_Declaration)
15626199f2d1SDouglas Gregor       continue;
15636199f2d1SDouglas Gregor 
15646199f2d1SDouglas Gregor     unsigned IDNS
15656199f2d1SDouglas Gregor       = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
15666199f2d1SDouglas Gregor 
15676199f2d1SDouglas Gregor     bool Hiding = false;
15686199f2d1SDouglas Gregor     if (OnlyTagNames)
15696199f2d1SDouglas Gregor       Hiding = (IDNS & Decl::IDNS_Tag);
15706199f2d1SDouglas Gregor     else {
15716199f2d1SDouglas Gregor       unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
15726199f2d1SDouglas Gregor                              Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
15736199f2d1SDouglas Gregor                              Decl::IDNS_NonMemberOperator);
15746199f2d1SDouglas Gregor       if (Ctx.getLangOptions().CPlusPlus)
15756199f2d1SDouglas Gregor         HiddenIDNS |= Decl::IDNS_Tag;
15766199f2d1SDouglas Gregor       Hiding = (IDNS & HiddenIDNS);
15776199f2d1SDouglas Gregor     }
15786199f2d1SDouglas Gregor 
15796199f2d1SDouglas Gregor     if (!Hiding)
15806199f2d1SDouglas Gregor       continue;
15816199f2d1SDouglas Gregor 
15826199f2d1SDouglas Gregor     DeclarationName Name = Results[I].Declaration->getDeclName();
15836199f2d1SDouglas Gregor     if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
15846199f2d1SDouglas Gregor       HiddenNames.insert(Identifier->getName());
15856199f2d1SDouglas Gregor     else
15866199f2d1SDouglas Gregor       HiddenNames.insert(Name.getAsString());
15876199f2d1SDouglas Gregor   }
15886199f2d1SDouglas Gregor }
15896199f2d1SDouglas Gregor 
15906199f2d1SDouglas Gregor 
1591d46cf182SDouglas Gregor void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
1592d46cf182SDouglas Gregor                                             CodeCompletionContext Context,
1593d46cf182SDouglas Gregor                                             Result *Results,
1594b14904c4SDouglas Gregor                                             unsigned NumResults) {
1595b14904c4SDouglas Gregor   // Merge the results we were given with the results we cached.
1596b14904c4SDouglas Gregor   bool AddedResult = false;
15976199f2d1SDouglas Gregor   unsigned InContexts
15986199f2d1SDouglas Gregor     = (Context.getKind() == CodeCompletionContext::CCC_Other? NormalContexts
1599b14904c4SDouglas Gregor                                             : (1 << (Context.getKind() - 1)));
16006199f2d1SDouglas Gregor 
16016199f2d1SDouglas Gregor   // Contains the set of names that are hidden by "local" completion results.
16026199f2d1SDouglas Gregor   llvm::StringSet<> HiddenNames;
160312785108SDouglas Gregor   llvm::SmallVector<CodeCompletionString *, 4> StringsToDestroy;
1604b14904c4SDouglas Gregor   typedef CodeCompleteConsumer::Result Result;
1605b14904c4SDouglas Gregor   llvm::SmallVector<Result, 8> AllResults;
1606b14904c4SDouglas Gregor   for (ASTUnit::cached_completion_iterator
1607b14904c4SDouglas Gregor             C = AST.cached_completion_begin(),
1608b14904c4SDouglas Gregor          CEnd = AST.cached_completion_end();
1609b14904c4SDouglas Gregor        C != CEnd; ++C) {
1610b14904c4SDouglas Gregor     // If the context we are in matches any of the contexts we are
1611b14904c4SDouglas Gregor     // interested in, we'll add this result.
1612b14904c4SDouglas Gregor     if ((C->ShowInContexts & InContexts) == 0)
1613b14904c4SDouglas Gregor       continue;
1614b14904c4SDouglas Gregor 
1615b14904c4SDouglas Gregor     // If we haven't added any results previously, do so now.
1616b14904c4SDouglas Gregor     if (!AddedResult) {
16176199f2d1SDouglas Gregor       CalculateHiddenNames(Context, Results, NumResults, S.Context,
16186199f2d1SDouglas Gregor                            HiddenNames);
1619b14904c4SDouglas Gregor       AllResults.insert(AllResults.end(), Results, Results + NumResults);
1620b14904c4SDouglas Gregor       AddedResult = true;
1621b14904c4SDouglas Gregor     }
1622b14904c4SDouglas Gregor 
16236199f2d1SDouglas Gregor     // Determine whether this global completion result is hidden by a local
16246199f2d1SDouglas Gregor     // completion result. If so, skip it.
16256199f2d1SDouglas Gregor     if (C->Kind != CXCursor_MacroDefinition &&
16266199f2d1SDouglas Gregor         HiddenNames.count(C->Completion->getTypedText()))
16276199f2d1SDouglas Gregor       continue;
16286199f2d1SDouglas Gregor 
16296e24033bSDouglas Gregor     // Adjust priority based on similar type classes.
16306e24033bSDouglas Gregor     unsigned Priority = C->Priority;
163112785108SDouglas Gregor     CodeCompletionString *Completion = C->Completion;
16326e24033bSDouglas Gregor     if (!Context.getPreferredType().isNull()) {
16336e24033bSDouglas Gregor       if (C->Kind == CXCursor_MacroDefinition) {
16346e24033bSDouglas Gregor         Priority = getMacroUsagePriority(C->Completion->getTypedText(),
16356e24033bSDouglas Gregor                                Context.getPreferredType()->isAnyPointerType());
1636b61c07acSDouglas Gregor       } else if (C->Type) {
16376e24033bSDouglas Gregor         CanQualType Expected
1638b61c07acSDouglas Gregor           = S.Context.getCanonicalType(
1639b61c07acSDouglas Gregor                                Context.getPreferredType().getUnqualifiedType());
16406e24033bSDouglas Gregor         SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
16416e24033bSDouglas Gregor         if (ExpectedSTC == C->TypeClass) {
1642b61c07acSDouglas Gregor           // We know this type is similar; check for an exact match.
1643b61c07acSDouglas Gregor           llvm::StringMap<unsigned> &CachedCompletionTypes
1644b61c07acSDouglas Gregor             = AST.getCachedCompletionTypes();
1645b61c07acSDouglas Gregor           llvm::StringMap<unsigned>::iterator Pos
1646b61c07acSDouglas Gregor             = CachedCompletionTypes.find(QualType(Expected).getAsString());
1647b61c07acSDouglas Gregor           if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
1648b61c07acSDouglas Gregor             Priority /= CCF_ExactTypeMatch;
1649b61c07acSDouglas Gregor           else
16506e24033bSDouglas Gregor             Priority /= CCF_SimilarTypeMatch;
16516e24033bSDouglas Gregor         }
16526e24033bSDouglas Gregor       }
16536e24033bSDouglas Gregor     }
16546e24033bSDouglas Gregor 
165512785108SDouglas Gregor     // Adjust the completion string, if required.
165612785108SDouglas Gregor     if (C->Kind == CXCursor_MacroDefinition &&
165712785108SDouglas Gregor         Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
165812785108SDouglas Gregor       // Create a new code-completion string that just contains the
165912785108SDouglas Gregor       // macro name, without its arguments.
166012785108SDouglas Gregor       Completion = new CodeCompletionString;
166112785108SDouglas Gregor       Completion->AddTypedTextChunk(C->Completion->getTypedText());
166212785108SDouglas Gregor       StringsToDestroy.push_back(Completion);
166312785108SDouglas Gregor     }
166412785108SDouglas Gregor 
166512785108SDouglas Gregor     AllResults.push_back(Result(Completion, Priority, C->Kind,
1666f757a12dSDouglas Gregor                                 C->Availability));
1667b14904c4SDouglas Gregor   }
1668b14904c4SDouglas Gregor 
1669b14904c4SDouglas Gregor   // If we did not add any cached completion results, just forward the
1670b14904c4SDouglas Gregor   // results we were given to the next consumer.
1671b14904c4SDouglas Gregor   if (!AddedResult) {
1672b14904c4SDouglas Gregor     Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
1673b14904c4SDouglas Gregor     return;
1674b14904c4SDouglas Gregor   }
1675b14904c4SDouglas Gregor 
1676b14904c4SDouglas Gregor   Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
1677b14904c4SDouglas Gregor                                   AllResults.size());
167812785108SDouglas Gregor 
167912785108SDouglas Gregor   for (unsigned I = 0, N = StringsToDestroy.size(); I != N; ++I)
168012785108SDouglas Gregor     delete StringsToDestroy[I];
1681b14904c4SDouglas Gregor }
1682b14904c4SDouglas Gregor 
1683d46cf182SDouglas Gregor 
1684d46cf182SDouglas Gregor 
16858e984da8SDouglas Gregor void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
16868e984da8SDouglas Gregor                            RemappedFile *RemappedFiles,
16878e984da8SDouglas Gregor                            unsigned NumRemappedFiles,
1688b68bc59aSDouglas Gregor                            bool IncludeMacros,
1689b68bc59aSDouglas Gregor                            bool IncludeCodePatterns,
16908e984da8SDouglas Gregor                            CodeCompleteConsumer &Consumer,
16918e984da8SDouglas Gregor                            Diagnostic &Diag, LangOptions &LangOpts,
16928e984da8SDouglas Gregor                            SourceManager &SourceMgr, FileManager &FileMgr,
1693b97b666cSDouglas Gregor                    llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
1694b97b666cSDouglas Gregor              llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
16958e984da8SDouglas Gregor   if (!Invocation.get())
16968e984da8SDouglas Gregor     return;
16978e984da8SDouglas Gregor 
1698028d3e4dSDouglas Gregor   llvm::Timer *CompletionTimer = 0;
1699028d3e4dSDouglas Gregor   if (TimerGroup.get()) {
1700028d3e4dSDouglas Gregor     llvm::SmallString<128> TimerName;
1701028d3e4dSDouglas Gregor     llvm::raw_svector_ostream TimerNameOut(TimerName);
1702028d3e4dSDouglas Gregor     TimerNameOut << "Code completion @ " << File << ":" << Line << ":"
1703028d3e4dSDouglas Gregor                  << Column;
1704028d3e4dSDouglas Gregor     CompletionTimer = new llvm::Timer(TimerNameOut.str(), *TimerGroup);
1705028d3e4dSDouglas Gregor     CompletionTimer->startTimer();
1706028d3e4dSDouglas Gregor     Timers.push_back(CompletionTimer);
1707028d3e4dSDouglas Gregor   }
1708028d3e4dSDouglas Gregor 
17098e984da8SDouglas Gregor   CompilerInvocation CCInvocation(*Invocation);
17108e984da8SDouglas Gregor   FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
17118e984da8SDouglas Gregor   PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
17128e984da8SDouglas Gregor 
1713b14904c4SDouglas Gregor   FrontendOpts.ShowMacrosInCodeCompletion
1714b14904c4SDouglas Gregor     = IncludeMacros && CachedCompletionResults.empty();
1715b68bc59aSDouglas Gregor   FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
171639982197SDouglas Gregor   FrontendOpts.ShowGlobalSymbolsInCodeCompletion
171739982197SDouglas Gregor     = CachedCompletionResults.empty();
17188e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.FileName = File;
17198e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.Line = Line;
17208e984da8SDouglas Gregor   FrontendOpts.CodeCompletionAt.Column = Column;
17218e984da8SDouglas Gregor 
1722b68bc59aSDouglas Gregor   // Turn on spell-checking when performing code completion. It leads
1723b68bc59aSDouglas Gregor   // to better results.
1724b68bc59aSDouglas Gregor   unsigned SpellChecking = CCInvocation.getLangOpts().SpellChecking;
1725b68bc59aSDouglas Gregor   CCInvocation.getLangOpts().SpellChecking = 1;
1726b68bc59aSDouglas Gregor 
17278e984da8SDouglas Gregor   // Set the language options appropriately.
17288e984da8SDouglas Gregor   LangOpts = CCInvocation.getLangOpts();
17298e984da8SDouglas Gregor 
17308e984da8SDouglas Gregor   CompilerInstance Clang;
17318e984da8SDouglas Gregor   Clang.setInvocation(&CCInvocation);
17328e984da8SDouglas Gregor   OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
17338e984da8SDouglas Gregor 
17348e984da8SDouglas Gregor   // Set up diagnostics, capturing any diagnostics produced.
17358e984da8SDouglas Gregor   Clang.setDiagnostics(&Diag);
17368e984da8SDouglas Gregor   CaptureDroppedDiagnostics Capture(true,
17378e984da8SDouglas Gregor                                     Clang.getDiagnostics(),
17388e984da8SDouglas Gregor                                     StoredDiagnostics);
17398e984da8SDouglas Gregor 
17408e984da8SDouglas Gregor   // Create the target instance.
17418e984da8SDouglas Gregor   Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
17428e984da8SDouglas Gregor                                                Clang.getTargetOpts()));
17438e984da8SDouglas Gregor   if (!Clang.hasTarget()) {
17448e984da8SDouglas Gregor     Clang.takeInvocation();
17452dd19f1dSDouglas Gregor     CCInvocation.getLangOpts().SpellChecking = SpellChecking;
17462dd19f1dSDouglas Gregor     return;
17478e984da8SDouglas Gregor   }
17488e984da8SDouglas Gregor 
17498e984da8SDouglas Gregor   // Inform the target of the language options.
17508e984da8SDouglas Gregor   //
17518e984da8SDouglas Gregor   // FIXME: We shouldn't need to do this, the target should be immutable once
17528e984da8SDouglas Gregor   // created. This complexity should be lifted elsewhere.
17538e984da8SDouglas Gregor   Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
17548e984da8SDouglas Gregor 
17558e984da8SDouglas Gregor   assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
17568e984da8SDouglas Gregor          "Invocation must have exactly one source file!");
17578e984da8SDouglas Gregor   assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
17588e984da8SDouglas Gregor          "FIXME: AST inputs not yet supported here!");
17598e984da8SDouglas Gregor   assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
17608e984da8SDouglas Gregor          "IR inputs not support here!");
17618e984da8SDouglas Gregor 
17628e984da8SDouglas Gregor 
17638e984da8SDouglas Gregor   // Use the source and file managers that we were given.
17648e984da8SDouglas Gregor   Clang.setFileManager(&FileMgr);
17658e984da8SDouglas Gregor   Clang.setSourceManager(&SourceMgr);
17668e984da8SDouglas Gregor 
17678e984da8SDouglas Gregor   // Remap files.
17688e984da8SDouglas Gregor   PreprocessorOpts.clearRemappedFiles();
1769d8a5dba9SDouglas Gregor   PreprocessorOpts.RetainRemappedFileBuffers = true;
1770b97b666cSDouglas Gregor   for (unsigned I = 0; I != NumRemappedFiles; ++I) {
17718e984da8SDouglas Gregor     PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
17728e984da8SDouglas Gregor                                      RemappedFiles[I].second);
1773b97b666cSDouglas Gregor     OwnedBuffers.push_back(RemappedFiles[I].second);
1774b97b666cSDouglas Gregor   }
17758e984da8SDouglas Gregor 
1776b14904c4SDouglas Gregor   // Use the code completion consumer we were given, but adding any cached
1777b14904c4SDouglas Gregor   // code-completion results.
1778b14904c4SDouglas Gregor   AugmentedCodeCompleteConsumer
1779b14904c4SDouglas Gregor   AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion,
178039982197SDouglas Gregor                     FrontendOpts.ShowCodePatternsInCodeCompletion,
178139982197SDouglas Gregor                     FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
1782b14904c4SDouglas Gregor   Clang.setCodeCompletionConsumer(&AugmentedConsumer);
17838e984da8SDouglas Gregor 
1784028d3e4dSDouglas Gregor   // If we have a precompiled preamble, try to use it. We only allow
1785028d3e4dSDouglas Gregor   // the use of the precompiled preamble if we're if the completion
1786028d3e4dSDouglas Gregor   // point is within the main file, after the end of the precompiled
1787028d3e4dSDouglas Gregor   // preamble.
1788028d3e4dSDouglas Gregor   llvm::MemoryBuffer *OverrideMainBuffer = 0;
1789028d3e4dSDouglas Gregor   if (!PreambleFile.empty()) {
1790028d3e4dSDouglas Gregor     using llvm::sys::FileStatus;
1791028d3e4dSDouglas Gregor     llvm::sys::PathWithStatus CompleteFilePath(File);
1792028d3e4dSDouglas Gregor     llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
1793028d3e4dSDouglas Gregor     if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
1794028d3e4dSDouglas Gregor       if (const FileStatus *MainStatus = MainPath.getFileStatus())
1795028d3e4dSDouglas Gregor         if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
1796b97b666cSDouglas Gregor           OverrideMainBuffer
1797b97b666cSDouglas Gregor             = getMainBufferWithPrecompiledPreamble(CCInvocation, false, Line);
1798028d3e4dSDouglas Gregor   }
1799028d3e4dSDouglas Gregor 
1800028d3e4dSDouglas Gregor   // If the main file has been overridden due to the use of a preamble,
1801028d3e4dSDouglas Gregor   // make that override happen and introduce the preamble.
1802028d3e4dSDouglas Gregor   if (OverrideMainBuffer) {
1803028d3e4dSDouglas Gregor     PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
1804028d3e4dSDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
1805028d3e4dSDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second
1806028d3e4dSDouglas Gregor                                                     = PreambleEndsAtStartOfLine;
1807028d3e4dSDouglas Gregor     PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
1808028d3e4dSDouglas Gregor     PreprocessorOpts.DisablePCHValidation = true;
1809028d3e4dSDouglas Gregor 
1810028d3e4dSDouglas Gregor     // The stored diagnostics have the old source manager. Copy them
1811028d3e4dSDouglas Gregor     // to our output set of stored diagnostics, updating the source
1812028d3e4dSDouglas Gregor     // manager to the one we were given.
1813028d3e4dSDouglas Gregor     for (unsigned I = 0, N = this->StoredDiagnostics.size(); I != N; ++I) {
1814028d3e4dSDouglas Gregor       StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
1815028d3e4dSDouglas Gregor       FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
1816028d3e4dSDouglas Gregor       StoredDiagnostics[I].setLocation(Loc);
1817028d3e4dSDouglas Gregor     }
1818b97b666cSDouglas Gregor 
1819b97b666cSDouglas Gregor     OwnedBuffers.push_back(OverrideMainBuffer);
18207b02b583SDouglas Gregor   } else {
18217b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
18227b02b583SDouglas Gregor     PreprocessorOpts.PrecompiledPreambleBytes.second = false;
1823028d3e4dSDouglas Gregor   }
1824028d3e4dSDouglas Gregor 
18258e984da8SDouglas Gregor   llvm::OwningPtr<SyntaxOnlyAction> Act;
18268e984da8SDouglas Gregor   Act.reset(new SyntaxOnlyAction);
18278e984da8SDouglas Gregor   if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
18288e984da8SDouglas Gregor                            Clang.getFrontendOpts().Inputs[0].first)) {
18298e984da8SDouglas Gregor     Act->Execute();
18308e984da8SDouglas Gregor     Act->EndSourceFile();
18318e984da8SDouglas Gregor   }
18328e984da8SDouglas Gregor 
1833028d3e4dSDouglas Gregor   if (CompletionTimer)
1834028d3e4dSDouglas Gregor     CompletionTimer->stopTimer();
1835028d3e4dSDouglas Gregor 
18368e984da8SDouglas Gregor   // Steal back our resources.
18378e984da8SDouglas Gregor   Clang.takeFileManager();
18388e984da8SDouglas Gregor   Clang.takeSourceManager();
18398e984da8SDouglas Gregor   Clang.takeInvocation();
18408e984da8SDouglas Gregor   Clang.takeCodeCompletionConsumer();
1841b68bc59aSDouglas Gregor   CCInvocation.getLangOpts().SpellChecking = SpellChecking;
18428e984da8SDouglas Gregor }
1843e9386680SDouglas Gregor 
1844e9386680SDouglas Gregor bool ASTUnit::Save(llvm::StringRef File) {
1845e9386680SDouglas Gregor   if (getDiagnostics().hasErrorOccurred())
1846e9386680SDouglas Gregor     return true;
1847e9386680SDouglas Gregor 
1848e9386680SDouglas Gregor   // FIXME: Can we somehow regenerate the stat cache here, or do we need to
1849e9386680SDouglas Gregor   // unconditionally create a stat cache when we parse the file?
1850e9386680SDouglas Gregor   std::string ErrorInfo;
1851340045b2SBenjamin Kramer   llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo,
1852340045b2SBenjamin Kramer                            llvm::raw_fd_ostream::F_Binary);
1853e9386680SDouglas Gregor   if (!ErrorInfo.empty() || Out.has_error())
1854e9386680SDouglas Gregor     return true;
1855e9386680SDouglas Gregor 
1856e9386680SDouglas Gregor   std::vector<unsigned char> Buffer;
1857e9386680SDouglas Gregor   llvm::BitstreamWriter Stream(Buffer);
185855c0ad57SSebastian Redl   ASTWriter Writer(Stream);
185955c0ad57SSebastian Redl   Writer.WriteAST(getSema(), 0, 0);
1860e9386680SDouglas Gregor 
1861e9386680SDouglas Gregor   // Write the generated bitstream to "Out".
18622dd19f1dSDouglas Gregor   if (!Buffer.empty())
1863e9386680SDouglas Gregor     Out.write((char *)&Buffer.front(), Buffer.size());
1864e9386680SDouglas Gregor   Out.close();
1865e9386680SDouglas Gregor   return Out.has_error();
1866e9386680SDouglas Gregor }
1867