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