]> granicus.if.org Git - clang/commitdiff
AST writer support for having specializations of templates from earlier in the chain...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 24 Aug 2010 22:50:24 +0000 (22:50 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 24 Aug 2010 22:50:24 +0000 (22:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111986 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Serialization/ASTWriter.h
lib/Serialization/ASTWriter.cpp
lib/Serialization/ASTWriterDecl.cpp
test/PCH/Inputs/chain-cxx1.h
test/PCH/Inputs/chain-cxx2.h
test/PCH/chain-cxx.cpp

index 6bdba097c9b56a7a7c812d428f0486d3a6c4f939..b8bff27f57e33228432ab9ac7b1b70c7106cd2b2 100644 (file)
@@ -217,6 +217,16 @@ private:
   llvm::SmallVector<std::pair<serialization::DeclID, uint64_t>, 16>
       ReplacedDecls;
 
+  typedef llvm::SmallVector<serialization::DeclID, 4>
+      AdditionalTemplateSpecializationsList;
+  typedef llvm::DenseMap<serialization::DeclID,
+                         AdditionalTemplateSpecializationsList>
+      AdditionalTemplateSpecializationsMap;
+
+  /// \brief Additional specializations (including partial) of templates that
+  /// were introduced after the template was serialized.
+  AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializations;
+
   /// \brief Statements that we've encountered while serializing a
   /// declaration or type.
   llvm::SmallVector<Stmt *, 16> StmtsToEmit;
@@ -266,6 +276,7 @@ private:
   void WriteAttributeRecord(const AttrVec &Attrs);
   void WriteDeclUpdateBlock();
   void WriteDeclContextVisibleUpdate(const DeclContext *DC);
+  void WriteAdditionalTemplateSpecializations();
 
   unsigned ParmVarDeclAbbrev;
   unsigned DeclContextLexicalAbbrev;
@@ -420,6 +431,13 @@ public:
     UpdatedNamespaces.insert(NS);
   }
 
+  /// \brief Record a template specialization or partial specialization of
+  /// a template from a previous PCH file.
+  void AddAdditionalTemplateSpecialization(serialization::DeclID Templ,
+                                           serialization::DeclID Spec) {
+    AdditionalTemplateSpecializations[Templ].push_back(Spec);
+  }
+
   /// \brief Note that the identifier II occurs at the given offset
   /// within the identifier table.
   void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset);
index 5c3e24a0a272106223cf240f3c81e1b0a0663368..be181f44069b9c6ba50c177125e842318e7ea567 100644 (file)
@@ -2129,6 +2129,21 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
   Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str());
 }
 
+/// \brief Write ADDITIONAL_TEMPLATE_SPECIALIZATIONS blocks for all templates
+/// that have new specializations in the current AST file.
+void ASTWriter::WriteAdditionalTemplateSpecializations() {
+  RecordData Record;
+  for (AdditionalTemplateSpecializationsMap::iterator
+           I = AdditionalTemplateSpecializations.begin(),
+           E = AdditionalTemplateSpecializations.end();
+       I != E; ++I) {
+    Record.clear();
+    Record.push_back(I->first);
+    Record.insert(Record.end(), I->second.begin(), I->second.end());
+    Stream.EmitRecord(ADDITIONAL_TEMPLATE_SPECIALIZATIONS, Record);
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // General Serialization Routines
 //===----------------------------------------------------------------------===//
@@ -2638,6 +2653,10 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
          I != E; ++I)
     WriteDeclContextVisibleUpdate(*I);
 
+  // Write the updates to C++ template specialization lists.
+  if (!AdditionalTemplateSpecializations.empty())
+    WriteAdditionalTemplateSpecializations();
+
   Record.clear();
   Record.push_back(NumStatements);
   Record.push_back(NumMacros);
index 3edb6302f8f744efa167b6dbc49866a98ba21e5e..413f544f4c1a9c371e81d6debba704f7d71c62db 100644 (file)
@@ -888,13 +888,21 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
   llvm::PointerUnion<ClassTemplateDecl *,
                      ClassTemplatePartialSpecializationDecl *> InstFrom
     = D->getSpecializedTemplateOrPartial();
+  Decl *InstFromD;
   if (InstFrom.is<ClassTemplateDecl *>()) {
-    Writer.AddDeclRef(InstFrom.get<ClassTemplateDecl *>(), Record);
+    InstFromD = InstFrom.get<ClassTemplateDecl *>();
+    Writer.AddDeclRef(InstFromD, Record);
   } else {
-    Writer.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>(),
-                      Record);
+    InstFromD = InstFrom.get<ClassTemplatePartialSpecializationDecl *>();
+    Writer.AddDeclRef(InstFromD, Record);
     Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record);
+    InstFromD = cast<ClassTemplatePartialSpecializationDecl>(InstFromD)->
+                    getSpecializedTemplate();
   }
+  // Is this a specialization of an already-serialized template?
+  if (InstFromD->getCanonicalDecl()->getPCHLevel() != 0)
+    Writer.AddAdditionalTemplateSpecialization(Writer.getDeclID(InstFromD),
+                                               Writer.getDeclID(D));
 
   // Explicit info.
   Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record);
index 747bdbc7f42786fe6e5e36ea62aafc20d7404952..7ea3ffb61c8fb712ba55bd22a6ee8ffe46d3e957 100644 (file)
@@ -12,4 +12,8 @@ namespace ns {
 }
 
 template <typename T>
-struct S {};
+struct S { typedef int G; };
+
+// Partially specialize
+template <typename T>
+struct S<T *> { typedef int H; };
index ff22e538d4d20c0b3334046cdda113258f150d23..adc10fd8368148198931384295356356a2b276d4 100644 (file)
@@ -18,3 +18,15 @@ namespace ns {
 // Specialize template from primary
 template <>
 struct S<int> { typedef int I; };
+
+// Partially specialize
+template <typename T>
+struct S<T &> { typedef int J; };
+
+// Specialize previous partial specialization
+template <>
+struct S<int *> { typedef int K; };
+
+// Specialize the partial specialization from this file
+template <>
+struct S<int &> { typedef int L; };
index 450a791828638b2cadffdfc0be7a946fad7a0834..3e46214c70b83ecde52dbfdb0768642591e34e14 100644 (file)
@@ -19,5 +19,10 @@ void test() {
   ns::pg();
   ns::g2();
 
-  //typedef S<int>::I J;
+  typedef S<double>::G T1;
+  typedef S<double *>::H T2;
+  typedef S<int>::I T3;
+  typedef S<double &>::J T4;
+  typedef S<int *>::K T5;
+  typedef S<int &>::L T6;
 }