Implement chained PCH support for the macro definitions stored within
authorDouglas Gregor <dgregor@apple.com>
Sat, 2 Oct 2010 19:29:26 +0000 (19:29 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 2 Oct 2010 19:29:26 +0000 (19:29 +0000)
the "detailed" preprocessing record.

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

include/clang/Serialization/ASTDeserializationListener.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/PCH/chain-macro-override.c
test/PCH/chain-macro.c

index f8114de5f15a87116822d5ca7a2dbc04a2e1d9b5..3cccd0572c30120b0a3c7cb248d1fa349f3e9009 100644 (file)
@@ -22,7 +22,8 @@ namespace clang {
 class Decl;
 class ASTReader;
 class QualType;
-
+class MacroDefinition;
+  
 class ASTDeserializationListener {
 protected:
   virtual ~ASTDeserializationListener() {}
@@ -42,6 +43,9 @@ public:
   virtual void DeclRead(serialization::DeclID ID, const Decl *D) = 0;
   /// \brief A selector was read from the AST file.
   virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) = 0;
+  /// \brief A macro definition was read from the AST file.
+  virtual void MacroDefinitionRead(serialization::MacroID, 
+                                   MacroDefinition *MD) = 0;
 };
 
 }
index b2f08c183f2799408c7981f2888ceccd793dba42..5473b2d5da16744f086f708ad2fa4332338bf73e 100644 (file)
@@ -829,6 +829,11 @@ public:
     return static_cast<unsigned>(SelectorsLoaded.size());
   }
 
+  /// \brief Returns the number of macro definitions found in the chain.
+  unsigned getTotalNumMacroDefinitions() const {
+    return static_cast<unsigned>(MacroDefinitionsLoaded.size());
+  }
+      
   /// \brief Reads a TemplateArgumentLocInfo appropriate for the
   /// given TemplateArgument kind.
   TemplateArgumentLocInfo
index 95964e0ea557ea19e619ff56b2768fc0884cb5a8..528580ec03dc6d1974f8cf105ff815462ff682f1 100644 (file)
@@ -163,7 +163,7 @@ private:
   /// \brief Offset of each selector within the method pool/selector
   /// table, indexed by the Selector ID (-1).
   std::vector<uint32_t> SelectorOffsets;
-
+  
   /// \brief Offsets of each of the macro identifiers into the
   /// bitstream.
   ///
@@ -172,6 +172,12 @@ private:
   /// defined.
   llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets;
 
+  /// \brief The first ID number we can use for our own macro definitions.
+  serialization::MacroID FirstMacroID;
+  
+  /// \brief The decl ID that will be assigned to the next new macro definition.
+  serialization::MacroID NextMacroID;
+  
   /// \brief Mapping from macro definitions (as they occur in the preprocessing
   /// record) to the macro IDs.
   llvm::DenseMap<const MacroDefinition *, serialization::MacroID>
@@ -481,7 +487,8 @@ public:
   void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
   void TypeRead(serialization::TypeIdx Idx, QualType T);
   void DeclRead(serialization::DeclID ID, const Decl *D);
-  void SelectorRead(serialization::SelectorID iD, Selector Sel);
+  void SelectorRead(serialization::SelectorID ID, Selector Sel);
+  void MacroDefinitionRead(serialization::MacroID ID, MacroDefinition *MD);
 };
 
 /// \brief AST and semantic-analysis consumer that generates a
index adb233ac144a24d3b1e18bcc8ba2f542ee260ec7..35a8cc9fab23a6ca4b7d259247ec1a9dbce029cf 100644 (file)
@@ -1493,19 +1493,29 @@ void ASTReader::ReadMacroRecord(llvm::BitstreamCursor &Stream, uint64_t Offset){
       if (PPRec.getPreprocessedEntity(Record[0]))
         return;
         
-      if (Record[1] >= MacroDefinitionsLoaded.size()) {
+      if (Record[1] > MacroDefinitionsLoaded.size()) {
         Error("out-of-bounds macro definition record");
         return;
       }
 
-      MacroDefinition *MD
-        = new (PPRec) MacroDefinition(DecodeIdentifierInfo(Record[4]),
+      // Decode the identifier info and then check again; if the macro is
+      // still defined and associated with the identifier, 
+      IdentifierInfo *II = DecodeIdentifierInfo(Record[4]);
+      if (!MacroDefinitionsLoaded[Record[1] - 1]) {
+        MacroDefinition *MD
+          = new (PPRec) MacroDefinition(II,
                                 SourceLocation::getFromRawEncoding(Record[5]),
                               SourceRange(
                                 SourceLocation::getFromRawEncoding(Record[2]),
                                 SourceLocation::getFromRawEncoding(Record[3])));
-      PPRec.SetPreallocatedEntity(Record[0], MD);
-      MacroDefinitionsLoaded[Record[1]] = MD;
+        
+        PPRec.SetPreallocatedEntity(Record[0], MD);
+        MacroDefinitionsLoaded[Record[1] - 1] = MD;
+        
+        if (DeserializationListener)
+          DeserializationListener->MacroDefinitionRead(Record[1], MD);
+      }
+      
       return;
     }
     }
@@ -1582,23 +1592,23 @@ void ASTReader::ReadDefinedMacros() {
 }
 
 MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) {
-  if (ID == 0 || ID >= MacroDefinitionsLoaded.size())
+  if (ID == 0 || ID > MacroDefinitionsLoaded.size())
     return 0;
 
-  if (!MacroDefinitionsLoaded[ID]) {
-    unsigned Index = ID;
+  if (!MacroDefinitionsLoaded[ID - 1]) {
+    unsigned Index = ID - 1;
     for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
       PerFileData &F = *Chain[N - I - 1];
       if (Index < F.LocalNumMacroDefinitions) {
-        ReadMacroRecord(F.Stream, F.MacroDefinitionOffsets[Index]);
+        ReadMacroRecord(F.Stream, F.MacroDefinitionOffsets[Index]);        
         break;
       }
       Index -= F.LocalNumMacroDefinitions;
     }
-    assert(MacroDefinitionsLoaded[ID] && "Broken chain");
+    assert(MacroDefinitionsLoaded[ID - 1] && "Broken chain");
   }
 
-  return MacroDefinitionsLoaded[ID];
+  return MacroDefinitionsLoaded[ID - 1];
 }
 
 /// \brief If we are loading a relocatable PCH file, and the filename is
index ef8c52f4be1cade8d221b3fce0ee52c463b9efa5..c89680e2a6ec0b1293fa8844d3b5a7165b41a823 100644 (file)
@@ -1360,11 +1360,17 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) {
       if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
         // Record this macro definition's location.
         MacroID ID = getMacroDefinitionID(MD);
-        if (ID != MacroDefinitionOffsets.size()) {
-          if (ID > MacroDefinitionOffsets.size())
-            MacroDefinitionOffsets.resize(ID + 1);
+        
+        // Don't write the macro definition if it is from another AST file.
+        if (ID < FirstMacroID)
+          continue;
+        
+        unsigned Position = ID - FirstMacroID;
+        if (Position != MacroDefinitionOffsets.size()) {
+          if (Position > MacroDefinitionOffsets.size())
+            MacroDefinitionOffsets.resize(Position + 1);
           
-          MacroDefinitionOffsets[ID] = Stream.GetCurrentBitNo();            
+          MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo();            
         } else
           MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo());
         
@@ -2206,7 +2212,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
   : Stream(Stream), Chain(0), FirstDeclID(1), NextDeclID(FirstDeclID),
     FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
     FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1),
-    NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit),
+    NextSelectorID(FirstSelectorID), FirstMacroID(1), NextMacroID(FirstMacroID),
+    CollectedStmts(&StmtsToEmit),
     NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
     NumVisibleDeclContexts(0) {
 }
@@ -2439,10 +2446,12 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   FirstTypeID += Chain->getTotalNumTypes();
   FirstIdentID += Chain->getTotalNumIdentifiers();
   FirstSelectorID += Chain->getTotalNumSelectors();
+  FirstMacroID += Chain->getTotalNumMacroDefinitions();
   NextDeclID = FirstDeclID;
   NextTypeID = FirstTypeID;
   NextIdentID = FirstIdentID;
   NextSelectorID = FirstSelectorID;
+  NextMacroID = FirstMacroID;
 
   ASTContext &Context = SemaRef.Context;
   Preprocessor &PP = SemaRef.PP;
@@ -2733,7 +2742,7 @@ MacroID ASTWriter::getMacroDefinitionID(MacroDefinition *MD) {
 
   MacroID &ID = MacroDefinitions[MD];
   if (ID == 0)
-    ID = MacroDefinitions.size();
+    ID = NextMacroID++;
   return ID;
 }
 
@@ -3106,6 +3115,7 @@ void ASTWriter::SetReader(ASTReader *Reader) {
          FirstTypeID == NextTypeID &&
          FirstIdentID == NextIdentID &&
          FirstSelectorID == NextSelectorID &&
+         FirstMacroID == NextMacroID &&
          "Setting chain after writing has started.");
   Chain = Reader;
 }
@@ -3125,3 +3135,8 @@ void ASTWriter::DeclRead(DeclID ID, const Decl *D) {
 void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
   SelectorIDs[S] = ID;
 }
+
+void ASTWriter::MacroDefinitionRead(serialization::MacroID ID, 
+                                    MacroDefinition *MD) {
+  MacroDefinitions[MD] = ID;
+}
index 449ed8c7a0c439a2871d159fc54463e218a88b4f..8e208815fb26442fae3c6748f1953ae3e0fa7db8 100644 (file)
@@ -1,9 +1,9 @@
 // Test this without pch.
-// RUN: %clang_cc1 -include %S/Inputs/chain-macro-override1.h -include %S/Inputs/chain-macro-override2.h -fsyntax-only -verify %s
+// RUN: %clang_cc1 -include %S/Inputs/chain-macro-override1.h -include %S/Inputs/chain-macro-override2.h -fsyntax-only -verify -detailed-preprocessing-record %s
 
 // Test with pch.
-// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-macro-override1.h
-// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-macro-override2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-macro-override1.h -detailed-preprocessing-record 
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-macro-override2.h -include-pch %t1 -chained-pch -detailed-preprocessing-record 
 // RUN: %clang_cc1 -include-pch %t2 -fsyntax-only -verify %s
 
 int foo() {
index b4dcdfe644d758d1ea85ffa72e93f8a9af2da476..68b18deb0811dde638cbbb852bc79e8053cb814f 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-macro1.h
-// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-macro2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -emit-pch -o %t1 -detailed-preprocessing-record %S/Inputs/chain-macro1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 -detailed-preprocessing-record %S/Inputs/chain-macro2.h -include-pch %t1 -chained-pch
 // RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s
 // RUN: %clang_cc1 -ast-print -include-pch %t2 %s | FileCheck %s