]> granicus.if.org Git - clang/commitdiff
Make declarations in the dependent PCH visible, for C at least.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 23 Jul 2010 23:49:55 +0000 (23:49 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 23 Jul 2010 23:49:55 +0000 (23:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109292 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/PCHDeserializationListener.h
include/clang/Frontend/PCHReader.h
include/clang/Frontend/PCHWriter.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Frontend/PCHWriterDecl.cpp
test/PCH/Inputs/chain-function1.h [new file with mode: 0644]
test/PCH/Inputs/chain-function2.h [new file with mode: 0644]
test/PCH/chain-function.c [new file with mode: 0644]

index 84d7f8c1f5a76f48deb5f98095fcef2852cdb5b4..fe9c75560538f11345dbb080257bb0fc39fdc005 100644 (file)
@@ -27,6 +27,8 @@ protected:
   virtual ~PCHDeserializationListener() {}
 
 public:
+  /// \brief An identifier was deserialized from the PCH.
+  virtual void IdentifierRead(pch::IdentID ID, IdentifierInfo *II) = 0;
   /// \brief A type was deserialized from the PCH. The ID here has the qualifier
   ///        bits already removed, and T is guaranteed to be locally unqualified
   virtual void TypeRead(pch::TypeID ID, QualType T) = 0;
index 17a733ce307594eef7d32c29345ea43218050bcb..8bf51e109e0f2f95611f2d6022cbd35508b545b9 100644 (file)
@@ -655,11 +655,16 @@ public:
   /// \brief Read preprocessed entities into the 
   virtual void ReadPreprocessedEntities();
 
-  /// \brief Returns the number of source locations found in this file.
+  /// \brief Returns the number of source locations found in the chain.
   unsigned getTotalNumSLocs() const {
     return TotalNumSLocEntries;
   }
 
+  /// \brief Returns the number of identifiers found in the chain.
+  unsigned getTotalNumIdentifiers() const {
+    return static_cast<unsigned>(IdentifiersLoaded.size());
+  }
+
   /// \brief Returns the number of types found in this file.
   unsigned getTotalNumTypes() const {
     return static_cast<unsigned>(TypesLoaded.size());
index ab6c6ef8c653e58a2f256702d2cbecf246b1123e..10b96e8a3c03499fbe63a57a9c03c694db696053 100644 (file)
@@ -113,6 +113,9 @@ private:
   /// \brief The first ID number we can use for our own declarations.
   pch::DeclID FirstDeclID;
 
+  /// \brief The decl ID that will be assigned to the next new decl.
+  pch::DeclID NextDeclID;
+
   /// \brief Map that provides the ID numbers of each declaration within
   /// the output stream, as well as those deserialized from a chained PCH.
   ///
@@ -128,6 +131,9 @@ private:
   /// \brief The first ID number we can use for our own types.
   pch::TypeID FirstTypeID;
 
+  /// \brief The type ID that will be assigned to the next new type.
+  pch::TypeID NextTypeID;
+
   /// \brief Map that provides the ID numbers of each type within the
   /// output stream, plus those deserialized from a chained PCH.
   ///
@@ -143,8 +149,11 @@ private:
   /// the type's ID.
   std::vector<uint32_t> TypeOffsets;
 
-  /// \brief The type ID that will be assigned to the next new type.
-  pch::TypeID NextTypeID;
+  /// \brief The first ID number we can use for our own identifiers.
+  pch::IdentID FirstIdentID;
+
+  /// \brief The identifier ID that will be assigned to the next new identifier.
+  pch::IdentID NextIdentID;
 
   /// \brief Map that provides the ID numbers of each identifier in
   /// the output stream.
@@ -405,7 +414,10 @@ public:
 
   unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
 
+  bool hasChain() const { return Chain; }
+
   // PCHDeserializationListener implementation
+  void IdentifierRead(pch::IdentID ID, IdentifierInfo *II);
   void TypeRead(pch::TypeID ID, QualType T);
   void DeclRead(pch::DeclID ID, const Decl *D);
 };
index b4564885a8c4402c8b1b68aa113258fdc92484e5..48d05ba826c3543126120b943d4219f1d1f69981 100644 (file)
@@ -3193,6 +3193,8 @@ void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
   assert(ID && "Non-zero identifier ID required");
   assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
   IdentifiersLoaded[ID - 1] = II;
+  if (DeserializationListener)
+    DeserializationListener->IdentifierRead(ID, II);
 }
 
 /// \brief Set the globally-visible declarations associated with the given
@@ -3277,6 +3279,8 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
                        | (((unsigned) StrLenPtr[1]) << 8)) - 1;
     IdentifiersLoaded[ID]
       = &PP->getIdentifierTable().get(Str, StrLen);
+    if (DeserializationListener)
+      DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
   }
 
   return IdentifiersLoaded[ID];
index 0b8c5b42582fa43de3fd16a9506fa9218aa7b8b4..4474eaef4856c0fa888c0960c5132f59bf8d09e2 100644 (file)
@@ -1851,12 +1851,14 @@ public:
     // "stat"), but IdentifierResolver::AddDeclToIdentifierChain()
     // adds declarations to the end of the list (so we need to see the
     // struct "status" before the function "status").
+    // Only emit declarations that aren't from a chained PCH, though.
     llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II),
                                         IdentifierResolver::end());
     for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
                                                       DEnd = Decls.rend();
          D != DEnd; ++D)
-      clang::io::Emit32(Out, Writer.getDeclID(*D));
+      if (!Writer.hasChain() || (*D)->getPCHLevel() == 0)
+        clang::io::Emit32(Out, Writer.getDeclID(*D));
   }
 };
 } // end anonymous namespace
@@ -1884,13 +1886,17 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
          ID != IDEnd; ++ID)
       getIdentifierRef(ID->second);
 
-    // Create the on-disk hash table representation.
-    IdentifierOffsets.resize(IdentifierIDs.size());
+    // Create the on-disk hash table representation. We only store offsets
+    // for identifiers that appear here for the first time.
+    IdentifierOffsets.resize(NextIdentID - FirstIdentID);
     for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
            ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
          ID != IDEnd; ++ID) {
       assert(ID->first && "NULL identifier in identifier table");
-      Generator.insert(ID->first, ID->second);
+      // FIXME: Right now, we only write identifiers that are new to this file.
+      // We need to write older identifiers that changed too, though.
+      if (ID->second >= FirstIdentID)
+        Generator.insert(ID->first, ID->second);
     }
 
     // Create the on-disk hash table in a buffer.
@@ -2116,7 +2122,11 @@ void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
 /// \brief Note that the identifier II occurs at the given offset
 /// within the identifier table.
 void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
-  IdentifierOffsets[IdentifierIDs[II] - 1] = Offset;
+  pch::IdentID ID = IdentifierIDs[II];
+  // Only store offsets new to this PCH file. Other identifier names are looked
+  // up earlier in the chain and thus don't need an offset.
+  if (ID >= FirstIdentID)
+    IdentifierOffsets[ID - FirstIdentID] = Offset;
 }
 
 /// \brief Note that the selector Sel occurs at the given offset
@@ -2129,15 +2139,18 @@ void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
 
 PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain)
   : Stream(Stream), Chain(Chain), FirstDeclID(1),
-    FirstTypeID(pch::NUM_PREDEF_TYPE_IDS),
+    FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), FirstIdentID(1),
     CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
     NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) {
   if (Chain) {
     Chain->setDeserializationListener(this);
     FirstDeclID += Chain->getTotalNumDecls();
     FirstTypeID += Chain->getTotalNumTypes();
+    FirstIdentID += Chain->getTotalNumIdentifiers();
   }
+  NextDeclID = FirstDeclID;
   NextTypeID = FirstTypeID;
+  NextIdentID = FirstIdentID;
 }
 
 void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
@@ -2165,6 +2178,7 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
 
   // The translation unit is the first declaration we'll emit.
   DeclIDs[Context.getTranslationUnitDecl()] = 1;
+  ++NextDeclID;
   DeclTypesToEmit.push(Context.getTranslationUnitDecl());
 
   // Make sure that we emit IdentifierInfos (and any attached
@@ -2334,6 +2348,9 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   // We don't start with the translation unit, but with its decls that
   // don't come from the other PCH.
   const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+  // The TU was loaded before we managed to register ourselves as a listener.
+  // Thus we need to add it manually.
+  DeclIDs[TU] = 1;
   // FIXME: We don't want to iterate over everything here, because it needlessly
   // deserializes the entire original PCH. Instead we only want to iterate over
   // the stuff that's already there.
@@ -2359,7 +2376,7 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
 
   // FIXME: Preprocessor
   // FIXME: Method pool
-  // FIXME: Identifier table
+  WriteIdentifierTable(PP);
   WriteTypeDeclOffsets();
   // FIXME: External unnamed definitions
   // FIXME: Tentative definitions
@@ -2407,7 +2424,7 @@ pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) {
 
   pch::IdentID &ID = IdentifierIDs[II];
   if (ID == 0)
-    ID = IdentifierIDs.size();
+    ID = NextIdentID++;
   return ID;
 }
 
@@ -2576,7 +2593,7 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
   if (ID == 0) {
     // We haven't seen this declaration before. Give it a new ID and
     // enqueue it in the list of declarations to emit.
-    ID = DeclIDs.size();
+    ID = NextDeclID++;
     DeclTypesToEmit.push(const_cast<Decl *>(D));
   }
 
@@ -2777,6 +2794,10 @@ void PCHWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
   AddSourceRange(Base.getSourceRange(), Record);
 }
 
+void PCHWriter::IdentifierRead(pch::IdentID ID, IdentifierInfo *II) {
+  IdentifierIDs[II] = ID;
+}
+
 void PCHWriter::TypeRead(pch::TypeID ID, QualType T) {
   TypeIDs[T] = ID;
 }
index 7c4a21adb65a86090a2526826d6dfe81f89ba0c2..09cafe2c33bc64a0786cdcef4818ee265e865968 100644 (file)
@@ -1144,9 +1144,9 @@ void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
   // Determine the ID for this declaration
   pch::DeclID &ID = DeclIDs[D];
   if (ID == 0)
-    ID = DeclIDs.size();
+    ID = NextDeclID++;
 
-  unsigned Index = ID - 1;
+  unsigned Index = ID - FirstDeclID;
 
   // Record the offset for this declaration
   if (DeclOffsets.size() == Index)
diff --git a/test/PCH/Inputs/chain-function1.h b/test/PCH/Inputs/chain-function1.h
new file mode 100644 (file)
index 0000000..789447c
--- /dev/null
@@ -0,0 +1 @@
+void f();
diff --git a/test/PCH/Inputs/chain-function2.h b/test/PCH/Inputs/chain-function2.h
new file mode 100644 (file)
index 0000000..e8fc965
--- /dev/null
@@ -0,0 +1 @@
+void g();
diff --git a/test/PCH/chain-function.c b/test/PCH/chain-function.c
new file mode 100644 (file)
index 0000000..29bfdd4
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-function1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-function2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s
+
+void h() {
+  f();
+  g();
+}