diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index c6c766bb03be..3ccd04dfb29f 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -674,10 +674,20 @@ public: /// /// \param Unit - optionally an already created ASTUnit. Its ownership is not /// transfered. + /// + /// \param Persistent - if true the returned ASTUnit will be complete. + /// false means the caller is only interested in getting info through the + /// provided \see Action. static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI, llvm::IntrusiveRefCntPtr Diags, ASTFrontendAction *Action = 0, - ASTUnit *Unit = 0); + ASTUnit *Unit = 0, + bool Persistent = true, + StringRef ResourceFilesPath = StringRef(), + bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CacheCodeCompletionResults = false); /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a /// CompilerInvocation object. diff --git a/clang/include/clang/Frontend/MultiplexConsumer.h b/clang/include/clang/Frontend/MultiplexConsumer.h index 89972991d18c..d95c069731cf 100644 --- a/clang/include/clang/Frontend/MultiplexConsumer.h +++ b/clang/include/clang/Frontend/MultiplexConsumer.h @@ -37,6 +37,7 @@ public: virtual void HandleInterestingDecl(DeclGroupRef D); virtual void HandleTranslationUnit(ASTContext &Ctx); virtual void HandleTagDeclDefinition(TagDecl *D); + virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); virtual void CompleteTentativeDefinition(VarDecl *D); virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired); virtual ASTMutationListener *GetASTMutationListener(); diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 2419d2794161..8606f686559e 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -27,6 +27,7 @@ #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendOptions.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" @@ -1649,21 +1650,33 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI, ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, llvm::IntrusiveRefCntPtr Diags, ASTFrontendAction *Action, - ASTUnit *Unit) { + ASTUnit *Unit, + bool Persistent, + StringRef ResourceFilesPath, + bool OnlyLocalDecls, + bool CaptureDiagnostics, + bool PrecompilePreamble, + bool CacheCodeCompletionResults) { assert(CI && "A CompilerInvocation is required"); llvm::OwningPtr OwnAST; ASTUnit *AST = Unit; if (!AST) { // Create the AST unit. - OwnAST.reset(create(CI, Diags)); + OwnAST.reset(create(CI, Diags, CaptureDiagnostics)); AST = OwnAST.get(); } - AST->OnlyLocalDecls = false; - AST->CaptureDiagnostics = false; + if (!ResourceFilesPath.empty()) { + // Override the resources path. + CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; + } + AST->OnlyLocalDecls = OnlyLocalDecls; + AST->CaptureDiagnostics = CaptureDiagnostics; + if (PrecompilePreamble) + AST->PreambleRebuildCounter = 2; AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete; - AST->ShouldCacheCodeCompletionResults = false; + AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1742,7 +1755,17 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, Clang->getFrontendOpts().Inputs[0].second, Clang->getFrontendOpts().Inputs[0].first)) return 0; - + + if (Persistent && !TrackerAct) { + Clang->getPreprocessor().addPPCallbacks( + new MacroDefinitionTrackerPPCallbacks(AST->getCurrentTopLevelHashValue())); + std::vector Consumers; + if (Clang->hasASTConsumer()) + Consumers.push_back(Clang->takeASTConsumer()); + Consumers.push_back(new TopLevelDeclTrackerConsumer(*AST, + AST->getCurrentTopLevelHashValue())); + Clang->setASTConsumer(new MultiplexConsumer(Consumers)); + } Act->Execute(); // Steal the created target, context, and preprocessor. diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp index e7b886ccb609..6ca40abc2abe 100644 --- a/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/clang/lib/Frontend/MultiplexConsumer.cpp @@ -184,9 +184,10 @@ void MultiplexConsumer::Initialize(ASTContext &Context) { } bool MultiplexConsumer::HandleTopLevelDecl(DeclGroupRef D) { + bool Continue = true; for (size_t i = 0, e = Consumers.size(); i != e; ++i) - Consumers[i]->HandleTopLevelDecl(D); - return true; + Continue = Continue && Consumers[i]->HandleTopLevelDecl(D); + return Continue; } void MultiplexConsumer::HandleInterestingDecl(DeclGroupRef D) { @@ -204,6 +205,11 @@ void MultiplexConsumer::HandleTagDeclDefinition(TagDecl *D) { Consumers[i]->HandleTagDeclDefinition(D); } +void MultiplexConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { + for (size_t i = 0, e = Consumers.size(); i != e; ++i) + Consumers[i]->HandleTopLevelDeclInObjCContainer(D); +} + void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) { for (size_t i = 0, e = Consumers.size(); i != e; ++i) Consumers[i]->CompleteTentativeDefinition(D); diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 0e7193ee1043..472c0b0e9501 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -1548,6 +1548,7 @@ typedef struct { const char *check_prefix; int first_check_printed; int fail_for_error; + int abort; } IndexData; static void printCheck(IndexData *data) { @@ -1850,8 +1851,14 @@ static void index_indexEntityReference(CXClientData client_data, printf("\n"); } +static int index_abortQuery(CXClientData client_data, void *reserved) { + IndexData *index_data; + index_data = (IndexData *)client_data; + return index_data->abort; +} + static IndexerCallbacks IndexCB = { - 0, /*abortQuery*/ + index_abortQuery, index_diagnostic, index_enteredMainFile, index_ppIncludedFile, @@ -1894,6 +1901,7 @@ static int index_file(int argc, const char **argv) { index_data.check_prefix = check_prefix; index_data.first_check_printed = 0; index_data.fail_for_error = 0; + index_data.abort = 0; index_opts = 0; if (getenv("CINDEXTEST_SUPPRESSREFS")) @@ -1948,6 +1956,7 @@ static int index_tu(int argc, const char **argv) { index_data.check_prefix = check_prefix; index_data.first_check_printed = 0; index_data.fail_for_error = 0; + index_data.abort = 0; index_opts = 0; if (getenv("CINDEXTEST_SUPPRESSREFS")) diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 5af1d50e7206..222e301d46e9 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -244,9 +244,6 @@ static void clang_indexSourceFile_Impl(void *UserData) { CIndexer *CXXIdx = static_cast(CIdx); - (void)CXXIdx; - (void)TU_options; - CaptureDiagnosticConsumer *CaptureDiag = new CaptureDiagnosticConsumer(); // Configure the diagnostics. @@ -333,9 +330,38 @@ static void clang_indexSourceFile_Impl(void *UserData) { llvm::CrashRecoveryContextCleanupRegistrar IndexActionCleanup(IndexAction.get()); + bool Persistent = requestedToGetTU; + StringRef ResourceFilesPath = CXXIdx->getClangResourcesPath(); + bool OnlyLocalDecls = false; + bool CaptureDiagnostics = true; + bool PrecompilePreamble = false; + bool CacheCodeCompletionResults = false; + PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); + PPOpts.DetailedRecord = false; + PPOpts.DetailedRecordIncludesNestedMacroExpansions = false; + + if (requestedToGetTU) { + OnlyLocalDecls = CXXIdx->getOnlyLocalDecls(); + PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble; + // FIXME: Add a flag for modules. + CacheCodeCompletionResults + = TU_options & CXTranslationUnit_CacheCompletionResults; + if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) { + PPOpts.DetailedRecord = true; + PPOpts.DetailedRecordIncludesNestedMacroExpansions + = (TU_options & CXTranslationUnit_NestedMacroExpansions); + } + } + Unit = ASTUnit::LoadFromCompilerInvocationAction(CInvok.getPtr(), Diags, IndexAction.get(), - Unit); + Unit, + Persistent, + ResourceFilesPath, + OnlyLocalDecls, + CaptureDiagnostics, + PrecompilePreamble, + CacheCodeCompletionResults); if (!Unit) return;