Optionally store a PreprocessingRecord in the preprocessor itself, and
tie its creation to a CC1 flag -detailed-preprocessing-record.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98963 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 1aaa536..935c415 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -278,8 +278,7 @@
 ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
                                              Diagnostic &Diags,
                                              bool OnlyLocalDecls,
-                                             bool CaptureDiagnostics,
-                                             bool WantPreprocessingRecord) {
+                                             bool CaptureDiagnostics) {
   // Create the compiler instance to use for building the AST.
   CompilerInstance Clang;
   llvm::OwningPtr<ASTUnit> AST;
@@ -329,15 +328,6 @@
   // Create the preprocessor.
   Clang.createPreprocessor();
 
-  // If the ASTUnit was requested to store information about preprocessing,
-  // create storage for that information and attach an appropriate callback to 
-  // populate that storage.
-  if (WantPreprocessingRecord) {
-    AST->Preprocessing.reset(new PreprocessingRecord);
-    Clang.getPreprocessor().addPPCallbacks(
-                          new PopulatePreprocessingRecord(*AST->Preprocessing));
-  }
-      
   Act.reset(new TopLevelDeclTrackerAction(*AST));
   if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
                            /*IsAST=*/false))
@@ -377,8 +367,7 @@
                                       bool OnlyLocalDecls,
                                       RemappedFile *RemappedFiles,
                                       unsigned NumRemappedFiles,
-                                      bool CaptureDiagnostics,
-                                      bool WantPreprocessingRecord) {
+                                      bool CaptureDiagnostics) {
   llvm::SmallVector<const char *, 16> Args;
   Args.push_back("<clang>"); // FIXME: Remove dummy argument.
   Args.insert(Args.end(), ArgBegin, ArgEnd);
@@ -430,6 +419,5 @@
 
   CI->getFrontendOpts().DisableFree = true;
   return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
-                                    CaptureDiagnostics, 
-                                    WantPreprocessingRecord);
+                                    CaptureDiagnostics);
 }
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 5d399bd..bb0d308 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -224,6 +224,9 @@
     PP->setPTHManager(PTHMgr);
   }
 
+  if (PPOpts.DetailedRecord)
+    PP->createPreprocessingRecord();
+  
   InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
 
   // Handle generating dependencies, if requested.
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 5798f2f..d47fcf6 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -575,6 +575,8 @@
   }
   if (!Opts.UsePredefines)
     Res.push_back("-undef");
+  if (Opts.DetailedRecord)
+    Res.push_back("-detailed-preprocessing-record");
   if (!Opts.ImplicitPCHInclude.empty()) {
     Res.push_back("-include-pch");
     Res.push_back(Opts.ImplicitPCHInclude);
@@ -1232,7 +1234,7 @@
   else
     Opts.TokenCache = Opts.ImplicitPTHInclude;
   Opts.UsePredefines = !Args.hasArg(OPT_undef);
-
+  Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
   // Add macros from the command line.
   for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
          ie = Args.filtered_end(); it != ie; ++it) {
diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index 3e0a03b..83268e0 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -21,19 +21,3 @@
   PreprocessedEntities.push_back(Entity);
 }
 
-void PopulatePreprocessingRecord::MacroExpands(const Token &Id, 
-                                               const MacroInfo* MI) {
-  Record.addPreprocessedEntity(
-                        new (Record) MacroInstantiation(Id.getIdentifierInfo(),
-                                                       Id.getLocation(),
-                                                        MacroDefinitions[MI]));
-}
-
-void PopulatePreprocessingRecord::MacroDefined(const IdentifierInfo *II, 
-                                               const MacroInfo *MI) {
-  SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
-  MacroDefinition *Def
-    = new (Record) MacroDefinition(II, MI->getDefinitionLoc(), R);
-  MacroDefinitions[MI] = Def;
-  Record.addPreprocessedEntity(Def);
-}
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 917a2e7..d9aaed4 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -31,6 +31,7 @@
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Pragma.h"
+#include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Lex/ScratchBuffer.h"
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
@@ -627,3 +628,47 @@
 }
 
 CommentHandler::~CommentHandler() { }
+
+namespace {
+  /// \brief Preprocessor callback action used to populate a preprocessing
+  /// record.
+  class PopulatePreprocessingRecord : public PPCallbacks {
+    /// \brief The preprocessing record this action will populate.
+    PreprocessingRecord &Record;
+    
+    /// \brief Mapping from MacroInfo structures to their definitions.
+    llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions;
+    
+  public:
+    explicit PopulatePreprocessingRecord(PreprocessingRecord &Record)
+    : Record(Record) { }
+    
+    virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
+    virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
+  };  
+}
+
+void PopulatePreprocessingRecord::MacroExpands(const Token &Id, 
+                                               const MacroInfo* MI) {
+  Record.addPreprocessedEntity(
+                       new (Record) MacroInstantiation(Id.getIdentifierInfo(),
+                                                       Id.getLocation(),
+                                                       MacroDefinitions[MI]));
+}
+
+void PopulatePreprocessingRecord::MacroDefined(const IdentifierInfo *II, 
+                                               const MacroInfo *MI) {
+  SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
+  MacroDefinition *Def
+  = new (Record) MacroDefinition(II, MI->getDefinitionLoc(), R);
+  MacroDefinitions[MI] = Def;
+  Record.addPreprocessedEntity(Def);
+}
+
+void Preprocessor::createPreprocessingRecord() {
+  if (Record)
+    return;
+  
+  Record.reset(new PreprocessingRecord);
+  addPPCallbacks(new PopulatePreprocessingRecord(*Record));
+}