]> granicus.if.org Git - clang/commitdiff
Introduce a new libclang parsing flag,
authorDouglas Gregor <dgregor@apple.com>
Fri, 6 May 2011 16:33:08 +0000 (16:33 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 6 May 2011 16:33:08 +0000 (16:33 +0000)
CXTranslationUnit_NestedMacroInstantiations, which indicates whether
we want to see "nested" macro instantiations (e.g., those that occur
inside other macro instantiations) within the detailed preprocessing
record. Many clients (e.g., those that only care about visible tokens)
don't care about this information, and in code that uses preprocessor
metaprogramming, this information can have a very high cost.

Addresses <rdar://problem/9389320>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130990 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/clang-c/Index.h
include/clang/Frontend/ASTUnit.h
include/clang/Frontend/PreprocessorOptions.h
include/clang/Lex/PreprocessingRecord.h
include/clang/Lex/Preprocessor.h
lib/Frontend/ASTUnit.cpp
lib/Frontend/CompilerInstance.cpp
lib/Lex/PreprocessingRecord.cpp
lib/Lex/Preprocessor.cpp
lib/Serialization/ASTReader.cpp
test/Index/nested-macro-instantiations.cpp [new file with mode: 0644]
tools/c-index-test/c-index-test.c
tools/libclang/CIndex.cpp

index 011999bfe92111a631e0fbd6360af6fc93eef69a..97c0c7c0daa1e90f1eecb47f85025a6986b85f14 100644 (file)
@@ -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
 };
 
 /**
index 57d9f712aa18d90d8e5ef851f170508d336a5706..339297eb93626d936627a253cd054835e06fff59 100644 (file)
@@ -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.
index e875ec1fefd2abaf4f8515098e9c213fae3fe994..e471c5cf1d82f8806cc4d8117e3af1a9eb6c91ad 100644 (file)
@@ -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),
index d1534496b3d39ebf802cf1aa69cc948025a49abb..e498e9d0a0202f59fb50337afde60547967ed726 100644 (file)
@@ -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) {
index 616507a914a8fd66e52d71bc6b1f6851eaee8ab1..817fab57d339503bd8b5905ce938939930c900a9 100644 (file)
@@ -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.
index 0d0fecdcf4476fb830b979fe0d657f833685bc03..8827116f2e40f604be3e47e0481fecda562c2176 100644 (file)
@@ -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,
index ace3c5adb100c636e8228e1dbf9766db415922e5..38fcfe3c4711fe16f1ffa22c72edec60469f4027 100644 (file)
@@ -227,7 +227,8 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
   }
 
   if (PPOpts.DetailedRecord)
-    PP->createPreprocessingRecord();
+    PP->createPreprocessingRecord(
+                       PPOpts.DetailedRecordIncludesNestedMacroInstantiations);
   
   InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
 
index 9555611dc59d91acfab27ef41a5244fe0971a88f..0c8d948ce0a7bd619ce22e476b1d6bee1ec0485f 100644 (file)
@@ -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(),
index 31fd667a651dfe21b7889461a3ff9fd424143da7..fdc18f878180ab80b15362930237d898f0018b45 100644 (file)
@@ -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);
 }
index bad18ff02e2ec7c86e72edd41f565496be5af870..bdc46f590fa1d0e37577d84ad148d2febd33d3fd 100644 (file)
@@ -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 (file)
index 0000000..d0c9bbb
--- /dev/null
@@ -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]
index e43ac0699f2e675b2208b00139ef5392bb7197cf..a5d4909e63c8e4045ca6100658ff29b59482fd65 100644 (file)
@@ -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);
index 7234da3f6383ef4a6a328de4ab9fd974fde2f017..f17a415f44b2b3b44d5df6b9d43ff24440657093 100644 (file)
@@ -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.