diff options
-rw-r--r-- | include/clang-c/Index.h | 13 | ||||
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 10 | ||||
-rw-r--r-- | include/clang/Frontend/PreprocessorOptions.h | 5 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 7 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 2 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 14 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 3 | ||||
-rw-r--r-- | lib/Lex/PreprocessingRecord.cpp | 8 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 4 | ||||
-rw-r--r-- | test/Index/nested-macro-instantiations.cpp | 20 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 23 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 10 |
13 files changed, 98 insertions, 26 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 011999bfe9..97c0c7c0da 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -829,7 +829,18 @@ enum CXTranslationUnit_Flags { * Note: this is a *temporary* option that is available only while * we are testing C++ precompiled preamble support. */ - CXTranslationUnit_CXXChainedPCH = 0x20 + CXTranslationUnit_CXXChainedPCH = 0x20, + + /** + * \brief Used to indicate that the "detailed" preprocessing record, + * if requested, should also contain nested macro instantiations. + * + * Nested macro instantiations (i.e., macro instantiations that occur + * inside another macro instantiation) can, in some code bases, require + * a large amount of storage to due preprocessor metaprogramming. Moreover, + * its fairly rare that this information is useful for libclang clients. + */ + CXTranslationUnit_NestedMacroInstantiations = 0x40 }; /** diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 57d9f712aa..339297eb93 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -249,6 +249,10 @@ private: /// \brief Whether we should be caching code-completion results. bool ShouldCacheCodeCompletionResults; + /// \brief Whether we want to include nested macro instantiations in the + /// detailed preprocessing record. + bool NestedMacroInstantiations; + static void ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags, const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics); @@ -607,7 +611,8 @@ public: bool CaptureDiagnostics = false, bool PrecompilePreamble = false, bool CompleteTranslationUnit = true, - bool CacheCodeCompletionResults = false); + bool CacheCodeCompletionResults = false, + bool NestedMacroInstantiations = true); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -636,7 +641,8 @@ public: bool CompleteTranslationUnit = true, bool CacheCodeCompletionResults = false, bool CXXPrecompilePreamble = false, - bool CXXChainedPCH = false); + bool CXXChainedPCH = false, + bool NestedMacroInstantiations = true); /// \brief Reparse the source files using the same command-line options that /// were originally used to produce this translation unit. diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index e875ec1fef..e471c5cf1d 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -41,6 +41,10 @@ public: /// record of all macro definitions and /// instantiations. + /// \brief Whether the detailed preprocessing record includes nested macro + /// instantiations. + unsigned DetailedRecordIncludesNestedMacroInstantiations : 1; + /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -136,6 +140,7 @@ public: public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), + DetailedRecordIncludesNestedMacroInstantiations(true), DisablePCHValidation(false), DisableStatCache(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index d1534496b3..e498e9d0a0 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -258,6 +258,10 @@ namespace clang { /// including the various preprocessing directives processed, macros /// instantiated, etc. class PreprocessingRecord : public PPCallbacks { + /// \brief Whether we should include nested macro instantiations in + /// the preprocessing record. + bool IncludeNestedMacroInstantiations; + /// \brief Allocator used to store preprocessing objects. llvm::BumpPtrAllocator BumpAlloc; @@ -281,7 +285,8 @@ namespace clang { void MaybeLoadPreallocatedEntities() const ; public: - PreprocessingRecord(); + /// \brief Construct + explicit PreprocessingRecord(bool IncludeNestedMacroInstantiations); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 616507a914..817fab57d3 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -441,7 +441,7 @@ public: /// \brief Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. - void createPreprocessingRecord(); + void createPreprocessingRecord(bool IncludeNestedMacroInstantiations); /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 0d0fecdcf4..8827116f2e 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -102,6 +102,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST) ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0), ShouldCacheCodeCompletionResults(false), + NestedMacroInstantiations(true), CompletionCacheTopLevelHashValue(0), PreambleTopLevelHashValue(0), CurrentTopLevelHashValue(0), @@ -927,6 +928,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts(); + PreprocessorOpts.DetailedRecordIncludesNestedMacroInstantiations + = NestedMacroInstantiations; std::string PriorImplicitPCHInclude; if (OverrideMainBuffer) { PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer); @@ -1712,7 +1715,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, bool CaptureDiagnostics, bool PrecompilePreamble, bool CompleteTranslationUnit, - bool CacheCodeCompletionResults) { + bool CacheCodeCompletionResults, + bool NestedMacroInstantiations) { // Create the AST unit. llvm::OwningPtr<ASTUnit> AST; AST.reset(new ASTUnit(false)); @@ -1723,6 +1727,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, AST->CompleteTranslationUnit = CompleteTranslationUnit; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; AST->Invocation = CI; + AST->NestedMacroInstantiations = NestedMacroInstantiations; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> @@ -1747,7 +1752,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, bool CompleteTranslationUnit, bool CacheCodeCompletionResults, bool CXXPrecompilePreamble, - bool CXXChainedPCH) { + bool CXXChainedPCH, + bool NestedMacroInstantiations) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object // with the default options. @@ -1814,6 +1820,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); AST->Invocation = CI; + AST->NestedMacroInstantiations = NestedMacroInstantiations; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> @@ -2265,6 +2272,9 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, PreprocessorOpts.PrecompiledPreambleBytes.second = false; } + // Disable the preprocessing record + PreprocessorOpts.DetailedRecord = false; + llvm::OwningPtr<SyntaxOnlyAction> Act; Act.reset(new SyntaxOnlyAction); if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index ace3c5adb1..38fcfe3c47 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -227,7 +227,8 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, } if (PPOpts.DetailedRecord) - PP->createPreprocessingRecord(); + PP->createPreprocessingRecord( + PPOpts.DetailedRecordIncludesNestedMacroInstantiations); InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts); diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index 9555611dc5..0c8d948ce0 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -45,8 +45,9 @@ void PreprocessingRecord::MaybeLoadPreallocatedEntities() const { ExternalSource->ReadPreprocessedEntities(); } -PreprocessingRecord::PreprocessingRecord() - : ExternalSource(0), NumPreallocatedEntities(0), +PreprocessingRecord::PreprocessingRecord(bool IncludeNestedMacroInstantiations) + : IncludeNestedMacroInstantiations(IncludeNestedMacroInstantiations), + ExternalSource(0), NumPreallocatedEntities(0), LoadedPreallocatedEntities(false) { } @@ -120,6 +121,9 @@ MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) { } void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) { + if (!IncludeNestedMacroInstantiations && Id.getLocation().isMacroID()) + return; + if (MacroDefinition *Def = findMacroDefinition(MI)) PreprocessedEntities.push_back( new (*this) MacroInstantiation(Id.getIdentifierInfo(), diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 31fd667a65..fdc18f8781 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -527,10 +527,11 @@ CommentHandler::~CommentHandler() { } CodeCompletionHandler::~CodeCompletionHandler() { } -void Preprocessor::createPreprocessingRecord() { +void Preprocessor::createPreprocessingRecord( + bool IncludeNestedMacroInstantiations) { if (Record) return; - Record = new PreprocessingRecord; + Record = new PreprocessingRecord(IncludeNestedMacroInstantiations); addPPCallbacks(Record); } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index bad18ff02e..bdc46f590f 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2382,7 +2382,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, PP->getHeaderSearchInfo().SetExternalLookup(this); if (TotalNumPreallocatedPreprocessingEntities > 0) { if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); + PP->createPreprocessingRecord(true); PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNumPreallocatedPreprocessingEntities); } @@ -2581,7 +2581,7 @@ void ASTReader::setPreprocessor(Preprocessor &pp) { TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities; if (TotalNum) { if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); + PP->createPreprocessingRecord(true); PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum); } } diff --git a/test/Index/nested-macro-instantiations.cpp b/test/Index/nested-macro-instantiations.cpp new file mode 100644 index 0000000000..d0c9bbb1e7 --- /dev/null +++ b/test/Index/nested-macro-instantiations.cpp @@ -0,0 +1,20 @@ +#define FOO(x) x +#define BAR(x) FOO(x) +#define WIBBLE(x) BAR(x) + +WIBBLE(int x); + +// RUN: env CINDEXTEST_NESTED_MACROS=1 c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITH-NESTED %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_NESTED_MACROS=1 c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITH-NESTED %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_NESTED_MACROS=1 c-index-test -test-load-source-reparse 5 all %s | FileCheck -check-prefix CHECK-WITH-NESTED %s +// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:5:1: macro instantiation=WIBBLE:3:9 Extent=[5:1 - 5:7] +// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:3:19: macro instantiation=BAR:2:9 Extent=[3:19 - 5:14] +// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:2:16: macro instantiation=FOO:1:9 Extent=[2:16 - 5:14] +// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:5:1: VarDecl=x:5:1 (Definition) Extent=[5:1 - 5:14] + +// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITHOUT-NESTED %s +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITHOUT-NESTED %s +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 all %s | FileCheck -check-prefix CHECK-WITHOUT-NESTED %s +// CHECK-WITHOUT-NESTED: nested-macro-instantiations.cpp:5:1: macro instantiation=WIBBLE:3:9 Extent=[5:1 - 5:7] +// CHECK-WITHOUT-NESTED-NOT: nested-macro-instantiations.cpp:3:19: macro instantiation=BAR:2:9 Extent=[3:19 - 5:14] +// CHECK-WITHOUT-NESTED: nested-macro-instantiations.cpp:5:1: VarDecl=x:5:1 (Definition) Extent=[5:1 - 5:14] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index e43ac0699f..a5d4909e63 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -37,6 +37,8 @@ static unsigned getDefaultParsingOptions() { options |= clang_defaultEditingTranslationUnitOptions(); if (getenv("CINDEXTEST_COMPLETION_CACHING")) options |= CXTranslationUnit_CacheCompletionResults; + if (getenv("CINDEXTEST_NESTED_MACROS")) + options |= CXTranslationUnit_NestedMacroInstantiations; return options; } @@ -713,11 +715,11 @@ int perform_test_load_source(int argc, const char **argv, return -1; } - TU = clang_createTranslationUnitFromSourceFile(Idx, 0, - argc - num_unsaved_files, - argv + num_unsaved_files, - num_unsaved_files, - unsaved_files); + TU = clang_parseTranslationUnit(Idx, 0, + argv + num_unsaved_files, + argc - num_unsaved_files, + unsaved_files, num_unsaved_files, + getDefaultParsingOptions()); if (!TU) { fprintf(stderr, "Unable to load translation unit!\n"); free_remapped_files(unsaved_files, num_unsaved_files); @@ -1231,11 +1233,12 @@ int perform_token_annotation(int argc, const char **argv) { return -1; CIdx = clang_createIndex(0, 1); - TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1], - argc - num_unsaved_files - 3, - argv + num_unsaved_files + 2, - num_unsaved_files, - unsaved_files); + TU = clang_parseTranslationUnit(CIdx, argv[argc - 1], + argv + num_unsaved_files + 2, + argc - num_unsaved_files - 3, + unsaved_files, + num_unsaved_files, + getDefaultParsingOptions()); if (!TU) { fprintf(stderr, "unable to parse input\n"); clang_disposeIndex(CIdx); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 7234da3f63..f17a415f44 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -2376,10 +2376,12 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, const char * const *command_line_args, unsigned num_unsaved_files, struct CXUnsavedFile *unsaved_files) { + unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord | + CXTranslationUnit_NestedMacroInstantiations; return clang_parseTranslationUnit(CIdx, source_filename, command_line_args, num_command_line_args, unsaved_files, num_unsaved_files, - CXTranslationUnit_DetailedPreprocessingRecord); + Options); } struct ParseTranslationUnitInfo { @@ -2480,9 +2482,12 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { Args->push_back(source_filename); // Do we need the detailed preprocessing record? + bool NestedMacroInstantiations = false; if (options & CXTranslationUnit_DetailedPreprocessingRecord) { Args->push_back("-Xclang"); Args->push_back("-detailed-preprocessing-record"); + NestedMacroInstantiations + = (options & CXTranslationUnit_NestedMacroInstantiations); } unsigned NumErrors = Diags->getClient()->getNumErrors(); @@ -2501,7 +2506,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { CompleteTranslationUnit, CacheCodeCompetionResults, CXXPrecompilePreamble, - CXXChainedPCH)); + CXXChainedPCH, + NestedMacroInstantiations)); if (NumErrors != Diags->getClient()->getNumErrors()) { // Make sure to check that 'Unit' is non-NULL. |