Initial support for reading templates from PCH.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106392 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 85b7960..1fcf923 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -155,6 +155,21 @@
   return Template;
 }
 
+void ClassTemplateDecl::initPreviousDeclaration(ASTContext &C,
+                                                ClassTemplateDecl *PrevDecl) {
+  assert(PreviousDeclaration == 0 && "PreviousDeclaration already set!");
+  assert(CommonPtr == 0 && "initPreviousDeclaration already called!");
+
+  PreviousDeclaration = PrevDecl;
+
+  if (PrevDecl)
+    CommonPtr = PrevDecl->CommonPtr;
+  else {
+    CommonPtr = new (C) Common;
+    C.AddDeallocation(DeallocateCommon, CommonPtr);
+  }
+}
+
 ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
                                              DeclContext *DC,
                                              SourceLocation L,
@@ -162,16 +177,9 @@
                                              TemplateParameterList *Params,
                                              NamedDecl *Decl,
                                              ClassTemplateDecl *PrevDecl) {
-  Common *CommonPtr;
-  if (PrevDecl)
-    CommonPtr = PrevDecl->CommonPtr;
-  else {
-    CommonPtr = new (C) Common;
-    C.AddDeallocation(DeallocateCommon, CommonPtr);
-  }
-
-  return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl,
-                                   CommonPtr);
+  ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
+  New->initPreviousDeclaration(C, PrevDecl);
+  return New;
 }
 
 ClassTemplateDecl::~ClassTemplateDecl() {
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 99c28d4..c8663bc 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2208,13 +2208,26 @@
     return Context->getInjectedClassNameType(D, TST);
   }
   
-  case pch::TYPE_TEMPLATE_TYPE_PARM:
-    assert(false && "can't read template type parm types yet");
-    break;
+  case pch::TYPE_TEMPLATE_TYPE_PARM: {
+    unsigned Idx = 0;
+    unsigned Depth = Record[Idx++];
+    unsigned Index = Record[Idx++];
+    bool Pack = Record[Idx++];
+    IdentifierInfo *Name = GetIdentifierInfo(Record, Idx);
+    return Context->getTemplateTypeParmType(Depth, Index, Pack, Name);
+  }
 
-  case pch::TYPE_TEMPLATE_SPECIALIZATION:
-    assert(false && "can't read template specialization types yet");
-    break;
+  case pch::TYPE_TEMPLATE_SPECIALIZATION: {
+    unsigned Idx = 0;
+    TemplateName Name = ReadTemplateName(Record, Idx);
+    unsigned NumArgs = Record[Idx++];
+    llvm::SmallVector<TemplateArgument, 8> Args;
+    Args.reserve(NumArgs);
+    while (NumArgs--)
+      Args.push_back(ReadTemplateArgument(Record, Idx));
+    return Context->getTemplateSpecializationType(Name, Args.data(),Args.size(),
+                                                  QualType());
+  }
   }
   // Suppress a GCC warning
   return QualType();
@@ -2932,6 +2945,74 @@
   return DeclarationName();
 }
 
+TemplateName
+PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
+  TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; 
+  switch (Kind) {
+  case TemplateName::Template:
+    return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++])));
+
+  case TemplateName::OverloadedTemplate: {
+    unsigned size = Record[Idx++];
+    UnresolvedSet<8> Decls;
+    while (size--)
+      Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++])));
+
+    return Context->getOverloadedTemplateName(Decls.begin(), Decls.end());
+  }
+    
+  case TemplateName::QualifiedTemplate: {
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+    bool hasTemplKeyword = Record[Idx++];
+    TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++]));
+    return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
+  }
+    
+  case TemplateName::DependentTemplate: {
+    NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+    if (Record[Idx++])  // isIdentifier
+      return Context->getDependentTemplateName(NNS,
+                                               GetIdentifierInfo(Record, Idx));
+    return Context->getDependentTemplateName(NNS,
+                                             (OverloadedOperatorKind)Record[Idx++]);
+  }
+  }
+  
+  assert(0 && "Unhandled template name kind!");
+  return TemplateName();
+}
+
+TemplateArgument
+PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) {
+  switch ((TemplateArgument::ArgKind)Record[Idx++]) {
+  case TemplateArgument::Null:
+    return TemplateArgument();
+  case TemplateArgument::Type:
+    return TemplateArgument(GetType(Record[Idx++]));
+  case TemplateArgument::Declaration:
+    return TemplateArgument(GetDecl(Record[Idx++]));
+  case TemplateArgument::Integral:
+    return TemplateArgument(ReadAPSInt(Record, Idx), GetType(Record[Idx++]));
+  case TemplateArgument::Template:
+    return TemplateArgument(ReadTemplateName(Record, Idx));
+  case TemplateArgument::Expression:
+    return TemplateArgument(ReadDeclExpr());
+  case TemplateArgument::Pack: {
+    unsigned NumArgs = Record[Idx++];
+    llvm::SmallVector<TemplateArgument, 8> Args;
+    Args.reserve(NumArgs);
+    while (NumArgs--)
+      Args.push_back(ReadTemplateArgument(Record, Idx));
+    TemplateArgument TemplArg;
+    TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true);
+    return TemplArg;
+  }
+  }
+  
+  assert(0 && "Unhandled template argument kind!");
+  return TemplateArgument();
+}
+
 NestedNameSpecifier *
 PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
   unsigned N = Record[Idx++];
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index cbc0da6..fe11ca7 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -567,6 +567,28 @@
 void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
   // assert(false && "cannot read CXXRecordDecl");
   VisitRecordDecl(D);
+  
+  enum CXXRecKind {
+    CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
+  };
+  switch ((CXXRecKind)Record[Idx++]) {
+  default:
+    assert(false && "Out of sync with PCHDeclWriter::VisitCXXRecordDecl?");
+  case CXXRecNotTemplate:
+    break;
+  case CXXRecTemplate:
+    D->setDescribedClassTemplate(
+                        cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])));
+    break;
+  case CXXRecMemberSpecialization: {
+    CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
+    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
+    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
+    D->setInstantiationOfMemberClass(RD, TSK);
+    D->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+    break;
+  }
+  }
 
   // FIXME: this is far from complete
 
@@ -618,11 +640,76 @@
 }
 
 void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
-  assert(false && "cannot read TemplateDecl");
+  VisitNamedDecl(D);
+
+  NamedDecl *TemplatedDecl = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+
+  // TemplateParams.
+  SourceLocation TemplateLoc = Reader.ReadSourceLocation(Record, Idx);
+  SourceLocation LAngleLoc = Reader.ReadSourceLocation(Record, Idx);
+  SourceLocation RAngleLoc = Reader.ReadSourceLocation(Record, Idx);
+
+  unsigned NumParams = Record[Idx++];
+  assert(NumParams && "No template params!");
+  llvm::SmallVector<NamedDecl *, 16> Params;
+  Params.reserve(NumParams);
+  while (NumParams--)
+    Params.push_back(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+    
+  TemplateParameterList* TemplateParams = 
+    TemplateParameterList::Create(*Reader.getContext(), TemplateLoc, LAngleLoc,
+                                  Params.data(), Params.size(), RAngleLoc);
+  
+  D->init(TemplatedDecl, TemplateParams);
 }
 
 void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
-  assert(false && "cannot read ClassTemplateDecl");
+  VisitTemplateDecl(D);
+
+  ClassTemplateDecl *PrevDecl =
+      cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+  D->initPreviousDeclaration(*Reader.getContext(), PrevDecl);
+  if (PrevDecl == 0) {
+    // This ClassTemplateDecl owns a CommonPtr; read it.
+
+    unsigned size = Record[Idx++];
+    while (size--) {
+      ClassTemplateSpecializationDecl *CTSD
+         = cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++]));
+      llvm::FoldingSetNodeID ID;
+      void *InsertPos = 0;
+      ClassTemplateSpecializationDecl::Profile(ID, 
+                                  CTSD->getTemplateArgs().getFlatArgumentList(),
+                                            CTSD->getTemplateArgs().flat_size(),
+                                               *Reader.getContext());
+      D->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+      D->getSpecializations().InsertNode(CTSD, InsertPos);
+    }
+
+    size = Record[Idx++];
+    while (size--) {
+      ClassTemplatePartialSpecializationDecl *CTSD
+         = cast<ClassTemplatePartialSpecializationDecl>(
+                                                 Reader.GetDecl(Record[Idx++]));
+      llvm::FoldingSetNodeID ID;
+      void *InsertPos = 0;
+      ClassTemplatePartialSpecializationDecl::Profile(ID, 
+                                  CTSD->getTemplateArgs().getFlatArgumentList(),
+                                            CTSD->getTemplateArgs().flat_size(),
+                                               *Reader.getContext());
+      D->getPartialSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+      D->getPartialSpecializations().InsertNode(CTSD, InsertPos);
+    }
+
+    // InjectedClassNameType is computed.
+
+    if (ClassTemplateDecl *CTD
+          = cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
+      D->setInstantiatedFromMemberTemplate(CTD);
+      if (Record[Idx++])
+        D->setMemberSpecialization();
+    }
+  }
 }
 
 void PCHDeclReader::VisitClassTemplateSpecializationDecl(
@@ -640,7 +727,14 @@
 }
 
 void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
-  assert(false && "cannot read TemplateTypeParmDecl");
+  VisitTypeDecl(D);
+
+  D->setDeclaredWithTypename(Record[Idx++]);
+  D->setParameterPack(Record[Idx++]);
+
+  bool Inherited = Record[Idx++];
+  TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Record, Idx);
+  D->setDefaultArgument(DefArg, Inherited);
 }
 
 void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
@@ -988,7 +1082,7 @@
     assert(false && "cannot read FriendTemplateDecl");
     break;
   case pch::DECL_CLASS_TEMPLATE:
-    assert(false && "cannot read ClassTemplateDecl");
+    D = ClassTemplateDecl::CreateEmpty(*Context);
     break;
   case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION:
     assert(false && "cannot read ClasstemplateSpecializationDecl");
@@ -1000,7 +1094,7 @@
     assert(false && "cannot read FunctionTemplateDecl");
     break;
   case pch::DECL_TEMPLATE_TYPE_PARM:
-    assert(false && "cannot read TemplateTypeParmDecl");
+    D = TemplateTypeParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,0,0);
     break;
   case pch::DECL_NON_TYPE_TEMPLATE_PARM:
     assert(false && "cannot read NonTypeTemplateParmDecl");