[cfe-commits] r110125 - in /cfe/trunk: include/clang/AST/Redeclarable.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriter.cpp lib/Frontend/PCHWriterDecl.cpp test/PCH/cxx-templates.cpp test/PCH/cxx-templates.h

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Aug 3 10:30:10 PDT 2010


Author: akirtzidis
Date: Tue Aug  3 12:30:10 2010
New Revision: 110125

URL: http://llvm.org/viewvc/llvm-project?rev=110125&view=rev
Log:
Apart from storing/retrieving the previous redeclaration from PCH, also store/retrieve the most recent
redeclaration. That way we are sure that the full redeclarations chain is loaded.

When using chained PCHs, first declarations point to the most recent redeclarations in the same PCH.
To address this use a REDECLS_UPDATE_LATEST record block to keep track of which first declarations need
to point to a most recent redeclaration in another PCH.

Modified:
    cfe/trunk/include/clang/AST/Redeclarable.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/test/PCH/cxx-templates.cpp
    cfe/trunk/test/PCH/cxx-templates.h

Modified: cfe/trunk/include/clang/AST/Redeclarable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Redeclarable.h?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Redeclarable.h (original)
+++ cfe/trunk/include/clang/AST/Redeclarable.h Tue Aug  3 12:30:10 2010
@@ -177,6 +177,9 @@
                                           static_cast<const decl_type*>(this)));
   }
   redecl_iterator redecls_end() const { return redecl_iterator(); }
+
+  friend class PCHDeclReader;
+  friend class PCHDeclWriter;
 };
 
 }

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Tue Aug  3 12:30:10 2010
@@ -245,8 +245,12 @@
       /// declarations.
       TU_UPDATE_LEXICAL = 28,
 
+      /// \brief Record code for an update to first decls pointing to the
+      /// latest redeclarations.
+      REDECLS_UPDATE_LATEST = 29,
+
       /// \brief Record code for declarations that Sema keeps references of.
-      SEMA_DECL_REFS = 29
+      SEMA_DECL_REFS = 30
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Tue Aug  3 12:30:10 2010
@@ -319,6 +319,11 @@
   /// DeclContext.
   DeclContextOffsetsMap DeclContextOffsets;
 
+  typedef llvm::DenseMap<pch::DeclID, pch::DeclID> FirstLatestDeclIDMap;
+  /// \brief Map of first declarations from a chained PCH that point to the
+  /// most recent declarations in another PCH.
+  FirstLatestDeclIDMap FirstLatestDeclIDs;
+
   /// \brief Read the records that describe the contents of declcontexts.
   bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
                               const std::pair<uint64_t, uint64_t> &Offsets,
@@ -561,7 +566,7 @@
   QualType ReadTypeRecord(unsigned Index);
   RecordLocation TypeCursorForIndex(unsigned Index);
   void LoadedDecl(unsigned Index, Decl *D);
-  Decl *ReadDeclRecord(unsigned Index);
+  Decl *ReadDeclRecord(unsigned Index, pch::DeclID ID);
   RecordLocation DeclCursorForIndex(unsigned Index);
 
   void PassInterestingDeclsToConsumer();

Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Tue Aug  3 12:30:10 2010
@@ -79,6 +79,7 @@
 public:
   typedef llvm::SmallVector<uint64_t, 64> RecordData;
 
+  friend class PCHDeclWriter;
 private:
   /// \brief The bitstream writer used to emit this precompiled header.
   llvm::BitstreamWriter &Stream;
@@ -195,6 +196,11 @@
   /// \brief Mapping from the macro definition indices in \c MacroDefinitions
   /// to the corresponding offsets within the preprocessor block.
   std::vector<uint32_t> MacroDefinitionOffsets;
+
+  typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap;
+  /// \brief Map of first declarations from a chained PCH that point to the
+  /// most recent declarations in another PCH.
+  FirstLatestDeclMap FirstLatestDecls;
   
   /// \brief Declarations encountered that might be external
   /// definitions.

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Aug  3 12:30:10 2010
@@ -1557,6 +1557,18 @@
       break;
     }
 
+    case pch::REDECLS_UPDATE_LATEST: {
+      assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
+      for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
+        pch::DeclID First = Record[i], Latest = Record[i+1];
+        assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
+                Latest > FirstLatestDeclIDs[First]) &&
+               "The new latest is supposed to come after the previous latest");
+        FirstLatestDeclIDs[First] = Latest;
+      }
+      break;
+    }
+
     case pch::LANGUAGE_OPTIONS:
       if (ParseLanguageOptions(Record) && !DisableValidation)
         return IgnorePCH;
@@ -2868,7 +2880,7 @@
 
 TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() {
   if (!DeclsLoaded[0]) {
-    ReadDeclRecord(0);
+    ReadDeclRecord(0, 0);
     if (DeserializationListener)
       DeserializationListener->DeclRead(1, DeclsLoaded[0]);
   }
@@ -2887,7 +2899,7 @@
 
   unsigned Index = ID - 1;
   if (!DeclsLoaded[Index]) {
-    ReadDeclRecord(Index);
+    ReadDeclRecord(Index, ID);
     if (DeserializationListener)
       DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
   }

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Tue Aug  3 12:30:10 2010
@@ -31,6 +31,7 @@
   class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> {
     PCHReader &Reader;
     llvm::BitstreamCursor &Cursor;
+    const pch::DeclID ThisDeclID;
     const PCHReader::RecordData &Record;
     unsigned &Idx;
     pch::TypeID TypeIDForTypeDecl;
@@ -39,9 +40,10 @@
 
   public:
     PCHDeclReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor,
-                  const PCHReader::RecordData &Record, unsigned &Idx)
-      : Reader(Reader), Cursor(Cursor), Record(Record), Idx(Idx),
-        TypeIDForTypeDecl(0) { }
+                  pch::DeclID thisDeclID, const PCHReader::RecordData &Record,
+                  unsigned &Idx)
+      : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record),
+        Idx(Idx), TypeIDForTypeDecl(0) { }
 
     void Visit(Decl *D);
 
@@ -93,6 +95,7 @@
     void VisitBlockDecl(BlockDecl *BD);
 
     std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
 
     // FIXME: Reorder according to DeclNodes.td?
     void VisitObjCMethodDecl(ObjCMethodDecl *D);
@@ -178,8 +181,7 @@
 void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
   VisitTypeDecl(TD);
   TD->IdentifierNamespace = Record[Idx++];
-  TD->setPreviousDeclaration(
-                        cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++])));
+  VisitRedeclarable(TD);
   TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
   TD->setDefinition(Record[Idx++]);
   TD->setEmbeddedInDeclarator(Record[Idx++]);
@@ -305,10 +307,7 @@
   // FunctionDecl's body is handled last at PCHReaderDecl::Visit,
   // after everything else is read.
 
-  // Avoid side effects and invariant checking of FunctionDecl's
-  // setPreviousDeclaration.
-  FD->redeclarable_base::setPreviousDeclaration(
-                   cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
+  VisitRedeclarable(FD);
   FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
   FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]);
   FD->setInlineSpecified(Record[Idx++]);
@@ -550,8 +549,7 @@
   VD->setDeclaredInCondition(Record[Idx++]);
   VD->setExceptionVariable(Record[Idx++]);
   VD->setNRVOVariable(Record[Idx++]);
-  VD->setPreviousDeclaration(
-                         cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+  VisitRedeclarable(VD);
   if (Record[Idx++])
     VD->setInit(Reader.ReadExpr(Cursor));
 
@@ -918,6 +916,25 @@
 
     RedeclarableTemplateDecl *LatestDecl = 
         cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+  
+    // This decl is a first one and the latest declaration that it points to is
+    // in the same PCH. However, if this actually needs to point to a
+    // redeclaration in another chained PCH, we need to update it by checking
+    // the FirstLatestDeclIDs map which tracks this kind of decls.
+    assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
+    PCHReader::FirstLatestDeclIDMap::iterator I
+        = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+    if (I != Reader.FirstLatestDeclIDs.end()) {
+      Decl *NewLatest = Reader.GetDecl(I->second);
+      assert((LatestDecl->getLocation().isInvalid() ||
+              NewLatest->getLocation().isInvalid()  ||
+              Reader.SourceMgr.isBeforeInTranslationUnit(
+                                                   LatestDecl->getLocation(),
+                                                   NewLatest->getLocation())) &&
+             "The new latest is supposed to come after the previous latest");
+      LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
+    }
+
     assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
     D->getCommonPtr()->Latest = LatestDecl;
   }
@@ -1072,6 +1089,54 @@
   return std::make_pair(LexicalOffset, VisibleOffset);
 }
 
+template <typename T>
+void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
+  enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+  RedeclKind Kind = (RedeclKind)Record[Idx++];
+  switch (Kind) {
+  default:
+    assert(0 && "Out of sync with PCHDeclWriter::VisitRedeclarable or messed up"
+                " reading");
+  case NoRedeclaration:
+    break;
+  case PointsToPrevious:
+    D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
+                                cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+    break;
+  case PointsToLatest:
+    D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
+                                cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+    break;
+  }
+
+  assert(!(Kind == PointsToPrevious &&
+           Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
+               Reader.FirstLatestDeclIDs.end()) &&
+         "This decl is not first, it should not be in the map");
+  if (Kind == PointsToPrevious)
+    return;
+
+  // This decl is a first one and the latest declaration that it points to is in
+  // the same PCH. However, if this actually needs to point to a redeclaration
+  // in another chained PCH, we need to update it by checking the
+  // FirstLatestDeclIDs map which tracks this kind of decls.
+  assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
+         "Invalid ThisDeclID ?");
+  PCHReader::FirstLatestDeclIDMap::iterator I
+      = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+  if (I != Reader.FirstLatestDeclIDs.end()) {
+    Decl *NewLatest = Reader.GetDecl(I->second);
+    assert((D->getMostRecentDeclaration()->getLocation().isInvalid() ||
+            NewLatest->getLocation().isInvalid() ||
+            Reader.SourceMgr.isBeforeInTranslationUnit(
+                                   D->getMostRecentDeclaration()->getLocation(),
+                                   NewLatest->getLocation())) &&
+           "The new latest is supposed to come after the previous latest");
+    D->RedeclLink
+        = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Attribute Reading
 //===----------------------------------------------------------------------===//
@@ -1304,7 +1369,7 @@
 }
 
 /// \brief Read the declaration at the given offset from the PCH file.
-Decl *PCHReader::ReadDeclRecord(unsigned Index) {
+Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) {
   RecordLocation Loc = DeclCursorForIndex(Index);
   llvm::BitstreamCursor &DeclsCursor = *Loc.first;
   // Keep track of where we are in the stream, then jump back there
@@ -1320,7 +1385,7 @@
   RecordData Record;
   unsigned Code = DeclsCursor.ReadCode();
   unsigned Idx = 0;
-  PCHDeclReader Reader(*this, DeclsCursor, Record, Idx);
+  PCHDeclReader Reader(*this, DeclsCursor, ID, Record, Idx);
 
   Decl *D = 0;
   switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) {

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Aug  3 12:30:10 2010
@@ -2410,6 +2410,19 @@
   WriteIdentifierTable(PP);
   WriteTypeDeclOffsets();
 
+  /// Build a record containing first declarations from a chained PCH and the
+  /// most recent declarations in this PCH that they point to.
+  RecordData FirstLatestDeclIDs;
+  for (FirstLatestDeclMap::iterator
+        I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) {
+    assert(I->first->getPCHLevel() > I->second->getPCHLevel() &&
+           "Expected first & second to be in different PCHs");
+    AddDeclRef(I->first, FirstLatestDeclIDs);
+    AddDeclRef(I->second, FirstLatestDeclIDs);
+  }
+  if (!FirstLatestDeclIDs.empty())
+    Stream.EmitRecord(pch::REDECLS_UPDATE_LATEST, FirstLatestDeclIDs);
+
   // Write the record containing external, unnamed definitions.
   if (!ExternalDefinitions.empty())
     Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Tue Aug  3 12:30:10 2010
@@ -92,6 +92,7 @@
 
     void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
                           uint64_t VisibleOffset);
+    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
 
 
     // FIXME: Put in the same order is DeclNodes.td?
@@ -163,7 +164,7 @@
 void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
   VisitTypeDecl(D);
   Record.push_back(D->getIdentifierNamespace());
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  VisitRedeclarable(D);
   Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
   Record.push_back(D->isDefinition());
   Record.push_back(D->isEmbeddedInDeclarator());
@@ -279,7 +280,7 @@
   // FunctionDecl's body is handled last at PCHWriterDecl::Visit,
   // after everything else is written.
 
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  VisitRedeclarable(D);
   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
   Record.push_back(D->getStorageClassAsWritten());
   Record.push_back(D->isInlineSpecified());
@@ -500,7 +501,7 @@
   Record.push_back(D->isDeclaredInCondition());
   Record.push_back(D->isExceptionVariable());
   Record.push_back(D->isNRVOVariable());
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  VisitRedeclarable(D);
   Record.push_back(D->getInit() ? 1 : 0);
   if (D->getInit())
     Writer.AddStmt(D->getInit());
@@ -854,6 +855,18 @@
       Record.push_back(D->isMemberSpecialization());
 
     Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
+  } else {
+    RedeclarableTemplateDecl *First = D->getFirstDeclaration();
+    assert(First != D);
+    // If this is a most recent redeclaration that is pointed to by a first decl
+    // in a chained PCH, keep track of the association with the map so we can
+    // update the first decl during PCH reading.
+    if (First->getMostRecentDeclaration() == D &&
+        First->getPCHLevel() > D->getPCHLevel()) {
+      assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
+             && "The latest is already set");
+      Writer.FirstLatestDecls[First] = D;
+    }
   }
 }
 
@@ -1016,6 +1029,29 @@
   Record.push_back(VisibleOffset);
 }
 
+template <typename T>
+void PCHDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
+  enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+  if (D->RedeclLink.getNext() == D) {
+    Record.push_back(NoRedeclaration);
+  } else {
+    Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious
+                                                    : PointsToLatest);
+    Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
+  }
+
+  T *First = D->getFirstDeclaration();
+  T *ThisDecl = static_cast<T*>(D);
+  // If this is a most recent redeclaration that is pointed to by a first decl
+  // in a chained PCH, keep track of the association with the map so we can
+  // update the first decl during PCH reading.
+  if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
+      First->getPCHLevel() > ThisDecl->getPCHLevel()) {
+    assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
+           && "The latest is already set");
+    Writer.FirstLatestDecls[First] = ThisDecl;
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // PCHWriter Implementation

Modified: cfe/trunk/test/PCH/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.cpp?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-templates.cpp (original)
+++ cfe/trunk/test/PCH/cxx-templates.cpp Tue Aug  3 12:30:10 2010
@@ -1,9 +1,13 @@
 // Test this without pch.
-// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump
+// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump 1>/dev/null
+// RUN: %clang_cc1 -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s
 
 // Test with pch.
 // RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-templates.h
-// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump 
+// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump  1>/dev/null
+// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: define linkonce_odr void @_ZN2S3IiE1mEv
 
 struct A {
   typedef int type;
@@ -22,4 +26,7 @@
   Dep<A>::Ty ty;
   Dep<A> a;
   a.f();
+  
+  S3<int> s3;
+  s3.m();
 }

Modified: cfe/trunk/test/PCH/cxx-templates.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.h?rev=110125&r1=110124&r2=110125&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-templates.h (original)
+++ cfe/trunk/test/PCH/cxx-templates.h Tue Aug  3 12:30:10 2010
@@ -116,3 +116,11 @@
 };
 
 extern template class S2<true>;
+
+template <typename T>
+struct S3 {
+    void m();
+};
+
+template <typename T>
+inline void S3<T>::m() { }





More information about the cfe-commits mailing list