]> granicus.if.org Git - clang/commitdiff
Introduce a new kind of TemplateName that captures a substituted
authorDouglas Gregor <dgregor@apple.com>
Sat, 15 Jan 2011 06:45:20 +0000 (06:45 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 15 Jan 2011 06:45:20 +0000 (06:45 +0000)
template template parameter pack that cannot be fully expanded because
its enclosing pack expansion could not be expanded. This form of
TemplateName plays the same role as SubstTemplateTypeParmPackType and
SubstNonTypeTemplateParmPackExpr do for template type parameter packs
and non-type template parameter packs, respectively.

We should now handle these multi-level pack expansion substitutions
anywhere. The largest remaining gap in our variadic-templates support
is that we cannot cope with non-type template parameter packs whose
type is a pack expansion.

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

14 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/TemplateName.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Serialization/ASTReader.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/TemplateName.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
tools/libclang/CIndex.cpp

index 93b793eb784bfbe68d6ab115a369a5dcdec19a7d..97388dc0909c39528a9a73506d40a24ba56754bc 100644 (file)
@@ -119,7 +119,9 @@ class ASTContext {
 
   mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
   mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
-
+  mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage> 
+    SubstTemplateTemplateParmPacks;
+  
   /// \brief The set of nested name specifiers.
   ///
   /// This set is managed by the NestedNameSpecifier class.
@@ -936,7 +938,9 @@ public:
                                         const IdentifierInfo *Name) const;
   TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
                                         OverloadedOperatorKind Operator) const;
-
+  TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
+                                        const TemplateArgument &ArgPack) const;
+  
   enum GetBuiltinTypeError {
     GE_None,              //< No error
     GE_Missing_stdio,     //< Missing a type from <stdio.h>
index c85b72f08796df7b678259dbca9748d9b378bcd0..1721973e8229e135ee3ec79b67824ae498517b97 100644 (file)
@@ -23,27 +23,67 @@ namespace llvm {
 }
 
 namespace clang {
-
+  
+class ASTContext;
 class DependentTemplateName;
 class DiagnosticBuilder;
 class IdentifierInfo;
 class NestedNameSpecifier;
+class OverloadedTemplateStorage;
 struct PrintingPolicy;
 class QualifiedTemplateName;
 class NamedDecl;
+class SubstTemplateTemplateParmPackStorage;
+class TemplateArgument;
 class TemplateDecl;
-
-/// \brief A structure for storing the information associated with an
-/// overloaded template name.
-class OverloadedTemplateStorage {
+class TemplateTemplateParmDecl;
+  
+/// \brief Implementation class used to describe either a set of overloaded
+/// template names or an already-substituted template template parameter pack.
+class UncommonTemplateNameStorage {
+protected:
   union {
-    unsigned Size;
+    struct {
+      /// \brief If true, this is an OverloadedTemplateStorage instance; 
+      /// otherwise, it's a SubstTemplateTemplateParmPackStorage instance.
+      unsigned IsOverloadedStorage : 1;
+      
+      /// \brief The number of stored templates or template arguments,
+      /// depending on which subclass we have.
+      unsigned Size : 31;
+    } Bits;
+    
     void *PointerAlignment;
   };
   
+  UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) {
+    Bits.IsOverloadedStorage = OverloadedStorage;
+    Bits.Size = Size;
+  }
+  
+public:
+  unsigned size() const { return Bits.Size; }
+  
+  OverloadedTemplateStorage *getAsOverloadedStorage()  {
+    return Bits.IsOverloadedStorage
+             ? reinterpret_cast<OverloadedTemplateStorage *>(this) 
+             : 0;
+  }
+  
+  SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
+    return Bits.IsOverloadedStorage
+             ? 0
+             : reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ;
+  }
+};
+  
+/// \brief A structure for storing the information associated with an
+/// overloaded template name.
+class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
   friend class ASTContext;
 
-  OverloadedTemplateStorage(unsigned Size) : Size(Size) {}
+  OverloadedTemplateStorage(unsigned Size) 
+    : UncommonTemplateNameStorage(Size, true) { }
 
   NamedDecl **getStorage() {
     return reinterpret_cast<NamedDecl **>(this + 1);
@@ -55,11 +95,47 @@ class OverloadedTemplateStorage {
 public:
   typedef NamedDecl *const *iterator;
 
-  unsigned size() const { return Size; }
-
   iterator begin() const { return getStorage(); }
   iterator end() const { return getStorage() + size(); }
 };
+  
+  
+/// \brief A structure for storing an already-substituted template template
+/// parameter pack.
+///
+/// This kind of template names occurs when the parameter pack has been 
+/// provided with a template template argument pack in a context where its
+/// enclosing pack expansion could not be fully expanded.
+class SubstTemplateTemplateParmPackStorage
+  : public UncommonTemplateNameStorage, public llvm::FoldingSetNode
+{
+  ASTContext &Context;
+  TemplateTemplateParmDecl *Parameter;
+  const TemplateArgument *Arguments;
+  
+public:
+  SubstTemplateTemplateParmPackStorage(ASTContext &Context,
+                                       TemplateTemplateParmDecl *Parameter,
+                                       unsigned Size, 
+                                       const TemplateArgument *Arguments)
+    : UncommonTemplateNameStorage(Size, false), Context(Context),
+      Parameter(Parameter), Arguments(Arguments) { }
+  
+  /// \brief Retrieve the template template parameter pack being substituted.
+  TemplateTemplateParmDecl *getParameterPack() const {
+    return Parameter;
+  }
+  
+  /// \brief Retrieve the template template argument pack with which this
+  /// parameter was substituted.
+  TemplateArgument getArgumentPack() const;
+  
+  void Profile(llvm::FoldingSetNodeID &ID);
+  
+  static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+                      TemplateTemplateParmDecl *Parameter,
+                      const TemplateArgument &ArgPack);
+};
 
 /// \brief Represents a C++ template name within the type system.
 ///
@@ -90,7 +166,7 @@ public:
 /// only be understood in the context of
 class TemplateName {
   typedef llvm::PointerUnion4<TemplateDecl *,
-                              OverloadedTemplateStorage *,
+                              UncommonTemplateNameStorage *,
                               QualifiedTemplateName *,
                               DependentTemplateName *> StorageType;
 
@@ -103,16 +179,28 @@ class TemplateName {
 public:
   // \brief Kind of name that is actually stored.
   enum NameKind {
+    /// \brief A single template declaration.
     Template,
+    /// \brief A set of overloaded template declarations.
     OverloadedTemplate,
+    /// \brief A qualified template name, where the qualification is kept 
+    /// to describe the source code as written.
     QualifiedTemplate,
-    DependentTemplate
+    /// \brief A dependent template name that has not been resolved to a 
+    /// template (or set of templates).
+    DependentTemplate,
+    /// \brief A template template parameter pack that has been substituted for 
+    /// a template template argument pack, but has not yet been expanded into
+    /// individual arguments.
+    SubstTemplateTemplateParmPack
   };
 
   TemplateName() : Storage() { }
   explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
   explicit TemplateName(OverloadedTemplateStorage *Storage)
     : Storage(Storage) { }
+  explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
+    : Storage(Storage) { }
   explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
   explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
 
@@ -122,7 +210,7 @@ public:
   // \brief Get the kind of name that is actually stored.
   NameKind getKind() const;
 
-  /// \brief Retrieve the the underlying template declaration that
+  /// \brief Retrieve the underlying template declaration that
   /// this template name refers to, if known.
   ///
   /// \returns The template declaration that this template name refers
@@ -131,7 +219,7 @@ public:
   /// set of function templates, returns NULL.
   TemplateDecl *getAsTemplateDecl() const;
 
-  /// \brief Retrieve the the underlying, overloaded function template
+  /// \brief Retrieve the underlying, overloaded function template
   // declarations that this template name refers to, if known.
   ///
   /// \returns The set of overloaded function templates that this template
@@ -139,7 +227,25 @@ public:
   /// specific set of function templates because it is a dependent name or
   /// refers to a single template, returns NULL.
   OverloadedTemplateStorage *getAsOverloadedTemplate() const {
-    return Storage.dyn_cast<OverloadedTemplateStorage *>();
+    if (UncommonTemplateNameStorage *Uncommon = 
+                              Storage.dyn_cast<UncommonTemplateNameStorage *>())
+      return Uncommon->getAsOverloadedStorage();
+    
+    return 0;
+  }
+
+  /// \brief Retrieve the substituted template template parameter pack, if 
+  /// known.
+  ///
+  /// \returns The storage for the substituted template template parameter pack,
+  /// if known. Otherwise, returns NULL.
+  SubstTemplateTemplateParmPackStorage *
+  getAsSubstTemplateTemplateParmPack() const {
+    if (UncommonTemplateNameStorage *Uncommon = 
+        Storage.dyn_cast<UncommonTemplateNameStorage *>())
+      return Uncommon->getAsSubstTemplateTemplateParmPack();
+    
+    return 0;
   }
 
   /// \brief Retrieve the underlying qualified template name
index aaccaabd7529f72d2dcb1ca20f83325fd0286103..491df7f75d081e39f952e0c63e94ead25af1314d 100644 (file)
@@ -1885,10 +1885,6 @@ def err_ellipsis_in_declarator_not_parameter : Error<
 def err_sizeof_pack_no_pack_name : Error<
   "%0 does not refer to the name of a parameter pack">;
 
-// Unsupported variadic templates features
-def err_pack_expansion_mismatch_unsupported : Error<
-  "clang cannot yet instantiate pack expansions with mismatched pack levels">;
-
 def err_unexpected_typedef : Error<
   "unexpected type name %0: expected expression">;
 def err_unexpected_namespace : Error<
index 10c23c0834b33dc3cd02aa07cc6f8d87ff14d4e5..38b0c57d221c768dbe4c7094d5c8d2a01260bf4a 100644 (file)
@@ -1073,7 +1073,8 @@ public:
                                                unsigned &Idx);
 
   /// \brief Read a template name.
-  TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx);
+  TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record, 
+                                unsigned &Idx);
 
   /// \brief Read a template argument.
   TemplateArgument ReadTemplateArgument(PerFileData &F,
index e1e6fd08aa20998372d4d382e1b772d80dacec2e..a18247d7cee7d6c891df843a8495681a23c84b6b 100644 (file)
@@ -2737,6 +2737,15 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
     return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
   }
 
+  if (SubstTemplateTemplateParmPackStorage *SubstPack
+                                  = Name.getAsSubstTemplateTemplateParmPack()) {
+    TemplateTemplateParmDecl *CanonParam
+      = getCanonicalTemplateTemplateParmDecl(SubstPack->getParameterPack());
+    TemplateArgument CanonArgPack
+      = getCanonicalTemplateArgument(SubstPack->getArgumentPack());
+    return getSubstTemplateTemplateParmPack(CanonParam, CanonArgPack);
+  }
+      
   assert(!Name.getAsOverloadedTemplate());
 
   DependentTemplateName *DTN = Name.getAsDependentTemplateName();
@@ -4344,6 +4353,27 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
   return TemplateName(QTN);
 }
 
+TemplateName 
+ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
+                                       const TemplateArgument &ArgPack) const {
+  ASTContext &Self = const_cast<ASTContext &>(*this);
+  llvm::FoldingSetNodeID ID;
+  SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack);
+  
+  void *InsertPos = 0;
+  SubstTemplateTemplateParmPackStorage *Subst
+    = SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
+  
+  if (!Subst) {
+    Subst = new (*this) SubstTemplateTemplateParmPackStorage(Self, Param, 
+                                                           ArgPack.pack_size(),
+                                                         ArgPack.pack_begin());
+    SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
+  }
+
+  return TemplateName(Subst);
+}
+
 /// getFromTargetType - Given one of the integer types provided by
 /// TargetInfo, produce the corresponding type. The unsigned @p Type
 /// is actually a value of type @c TargetInfo::IntType.
index f9fe18f5dfb7a967c302c65b852dab9341709fa8..eaab3d3e6c96380422427daac64c50febdb544f6 100644 (file)
@@ -4079,6 +4079,24 @@ TemplateName ASTImporter::Import(TemplateName From) {
     
     return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator());
   }
+      
+  case TemplateName::SubstTemplateTemplateParmPack: {
+    SubstTemplateTemplateParmPackStorage *SubstPack
+      = From.getAsSubstTemplateTemplateParmPack();
+    TemplateTemplateParmDecl *Param
+      = cast_or_null<TemplateTemplateParmDecl>(
+                                        Import(SubstPack->getParameterPack()));
+    if (!Param)
+      return TemplateName();
+    
+    ASTNodeImporter Importer(*this);
+    TemplateArgument ArgPack 
+      = Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
+    if (ArgPack.isNull())
+      return TemplateName();
+    
+    return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
+  }
   }
   
   llvm_unreachable("Invalid template name kind");
index 2f8be294f2c56fa58256d90436beaff8e88ad851..15cd7f7f8d834d735fee4292a4a5ad4498637dec 100644 (file)
@@ -1017,6 +1017,12 @@ void CXXNameMangler::mangleType(TemplateName TN) {
     break;
   }
 
+  case TemplateName::SubstTemplateTemplateParmPack: {
+    SubstTemplateTemplateParmPackStorage *SubstPack
+      = TN.getAsSubstTemplateTemplateParmPack();
+    mangleTemplateParameter(SubstPack->getParameterPack()->getIndex());
+    break;
+  }
   }
 
   addSubstitution(TN);
index 73ff402b074e8612a9d4dca405ed8762da7272a5..6b378a00110174b219e8deea2f478175a8001b4b 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/TemplateName.h"
+#include "clang/AST/TemplateBase.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/PrettyPrinter.h"
 using namespace clang;
 using namespace llvm;
 
+TemplateArgument 
+SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
+  return TemplateArgument(Arguments, size());
+}
+
+void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID) {
+  Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
+}
+
+void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, 
+                                                   ASTContext &Context,
+                                           TemplateTemplateParmDecl *Parameter,
+                                             const TemplateArgument &ArgPack) {
+  ID.AddPointer(Parameter);
+  ArgPack.Profile(ID, Context);
+}
+
 TemplateName::NameKind TemplateName::getKind() const {
   if (Storage.is<TemplateDecl *>())
     return Template;
-  if (Storage.is<OverloadedTemplateStorage *>())
-    return OverloadedTemplate;
+  if (Storage.is<DependentTemplateName *>())
+    return DependentTemplate;
   if (Storage.is<QualifiedTemplateName *>())
     return QualifiedTemplate;
-  assert(Storage.is<DependentTemplateName *>() && "There's a case unhandled!");
-  return DependentTemplate;
+  
+  return getAsOverloadedTemplate()? OverloadedTemplate
+                                  : SubstTemplateTemplateParmPack;
 }
 
 TemplateDecl *TemplateName::getAsTemplateDecl() const {
@@ -73,7 +92,7 @@ bool TemplateName::containsUnexpandedParameterPack() const {
     return DTN->getQualifier() && 
       DTN->getQualifier()->containsUnexpandedParameterPack();
 
-  return false;
+  return getAsSubstTemplateTemplateParmPack() != 0;
 }
 
 void
@@ -96,7 +115,9 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
       OS << DTN->getIdentifier()->getName();
     else
       OS << "operator " << getOperatorSpelling(DTN->getOperator());
-  }
+  } else if (SubstTemplateTemplateParmPackStorage *SubstPack
+                                        = getAsSubstTemplateTemplateParmPack())
+    OS << SubstPack->getParameterPack()->getNameAsString();
 }
 
 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
index 8943daa36983c2f4790dbf9ca8e3fc6662010ab5..98fa390febc2756521f1980356c464796dc50381 100644 (file)
@@ -697,6 +697,10 @@ namespace {
                                    ElaboratedTypeKeyword Keyword,
                                    NestedNameSpecifier *NNS, QualType T);
 
+    TemplateName TransformTemplateName(TemplateName Name,
+                                       QualType ObjectType = QualType(),
+                                       NamedDecl *FirstQualifierInScope = 0);
+
     ExprResult TransformPredefinedExpr(PredefinedExpr *E);
     ExprResult TransformDeclRefExpr(DeclRefExpr *E);
     ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
@@ -762,12 +766,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
         assert(Arg.getKind() == TemplateArgument::Pack && 
                "Missing argument pack");
         
-        if (getSema().ArgumentPackSubstitutionIndex == -1) {
-          // FIXME: Variadic templates fun case.
-          getSema().Diag(Loc,  diag::err_pack_expansion_mismatch_unsupported);
-          return 0;
-        }
-        
+        assert(getSema().ArgumentPackSubstitutionIndex >= 0);        
         assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
         Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
       }
@@ -887,6 +886,60 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
                                                                     NNS, T);
 }
 
+TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name,
+                                                         QualType ObjectType,
+                                             NamedDecl *FirstQualifierInScope) {
+  if (TemplateTemplateParmDecl *TTP
+       = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      // If the corresponding template argument is NULL or non-existent, it's
+      // because we are performing instantiation from explicitly-specified
+      // template arguments in a function template, but there were some
+      // arguments left unspecified.
+      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+                                            TTP->getPosition()))
+        return Name;
+      
+      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+      
+      if (TTP->isParameterPack()) {
+        assert(Arg.getKind() == TemplateArgument::Pack && 
+               "Missing argument pack");
+        
+        if (getSema().ArgumentPackSubstitutionIndex == -1) {
+          // We have the template argument pack to substitute, but we're not
+          // actually expanding the enclosing pack expansion yet. So, just
+          // keep the entire argument pack.
+          return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
+        }
+        
+        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+      }
+      
+      TemplateName Template = Arg.getAsTemplate();
+      assert(!Template.isNull() && Template.getAsTemplateDecl() &&
+             "Wrong kind of template template argument");
+      return Template;
+    }
+  }
+  
+  if (SubstTemplateTemplateParmPackStorage *SubstPack
+                                  = Name.getAsSubstTemplateTemplateParmPack()) {
+    if (getSema().ArgumentPackSubstitutionIndex == -1)
+      return Name;
+
+    const TemplateArgument &ArgPack = SubstPack->getArgumentPack();
+    assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() &&
+           "Pack substitution index out-of-range");
+    return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex]
+                                                               .getAsTemplate();
+  }
+  
+  return inherited::TransformTemplateName(Name, ObjectType, 
+                                          FirstQualifierInScope);
+}
+
 ExprResult 
 TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
   if (!E->isTypeDependent())
index 73982a71c28218356d7f275eb2f7068a8e797f7b..be4d82c39a68baa8fdc01c89922e8fcae7d714bc 100644 (file)
@@ -891,7 +891,19 @@ public:
   TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
                                    OverloadedOperatorKind Operator,
                                    QualType ObjectType);
-  
+
+  /// \brief Build a new template name given a template template parameter pack
+  /// and the 
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param,
+                                   const TemplateArgument &ArgPack) {
+    return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
+  }
+
   /// \brief Build a new compound statement.
   ///
   /// By default, performs semantic analysis to build the new statement.
@@ -2590,6 +2602,22 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
     return TemplateName(TransTemplate);
   }
 
+  if (SubstTemplateTemplateParmPackStorage *SubstPack
+                                 = Name.getAsSubstTemplateTemplateParmPack()) {
+    TemplateTemplateParmDecl *TransParam
+      = cast_or_null<TemplateTemplateParmDecl>(
+               getDerived().TransformDecl(Loc, SubstPack->getParameterPack()));
+    if (!TransParam)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        TransParam == SubstPack->getParameterPack())
+      return Name;
+    
+    return getDerived().RebuildTemplateName(TransParam, 
+                                            SubstPack->getArgumentPack());
+  }
+  
   // These should be getting filtered out before they reach the AST.
   llvm_unreachable("overloaded function decl survived to here");
   return TemplateName();
index 584abfbcd1d71de599a6dc080ccd58b3c98fa190..6f87e4015988d02899e39f736aae0240b48c1278 100644 (file)
@@ -3082,7 +3082,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
   case TYPE_TEMPLATE_SPECIALIZATION: {
     unsigned Idx = 0;
     bool IsDependent = Record[Idx++];
-    TemplateName Name = ReadTemplateName(Record, Idx);
+    TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
     llvm::SmallVector<TemplateArgument, 8> Args;
     ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);
     QualType Canon = GetType(Record[Idx++]);
@@ -4238,7 +4238,8 @@ void ASTReader::ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
 }
 
 TemplateName
-ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadTemplateName(PerFileData &F, const RecordData &Record, 
+                            unsigned &Idx) {
   TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
   switch (Kind) {
   case TemplateName::Template:
@@ -4268,6 +4269,19 @@ ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
     return Context->getDependentTemplateName(NNS,
                                          (OverloadedOperatorKind)Record[Idx++]);
   }
+      
+  case TemplateName::SubstTemplateTemplateParmPack: {
+    TemplateTemplateParmDecl *Param 
+      = cast_or_null<TemplateTemplateParmDecl>(GetDecl(Record[Idx++]));
+    if (!Param)
+      return TemplateName();
+    
+    TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
+    if (ArgPack.getKind() != TemplateArgument::Pack)
+      return TemplateName();
+    
+    return Context->getSubstTemplateTemplateParmPack(Param, ArgPack);
+  }
   }
 
   assert(0 && "Unhandled template name kind!");
@@ -4291,9 +4305,9 @@ ASTReader::ReadTemplateArgument(PerFileData &F,
     return TemplateArgument(Value, T);
   }
   case TemplateArgument::Template: 
-    return TemplateArgument(ReadTemplateName(Record, Idx));
+    return TemplateArgument(ReadTemplateName(F, Record, Idx));
   case TemplateArgument::TemplateExpansion: {
-    TemplateName Name = ReadTemplateName(Record, Idx);
+    TemplateName Name = ReadTemplateName(F, Record, Idx);
     llvm::Optional<unsigned> NumTemplateExpansions;
     if (unsigned NumExpansions = Record[Idx++])
       NumTemplateExpansions = NumExpansions - 1;
index 4fa48faec529200622c85c9dbb07b7aed8ba2225..8a6461fb4f27298fc32b10ff81547d81b0fd737c 100644 (file)
@@ -3214,6 +3214,14 @@ void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) {
       Record.push_back(DepT->getOperator());
     break;
   }
+      
+  case TemplateName::SubstTemplateTemplateParmPack: {
+    SubstTemplateTemplateParmPackStorage *SubstPack
+      = Name.getAsSubstTemplateTemplateParmPack();
+    AddDeclRef(SubstPack->getParameterPack(), Record);
+    AddTemplateArgument(SubstPack->getArgumentPack(), Record);
+    break;
+  }
   }
 }
 
index 01d5759188a8e20bc01f1a0128ee4b2f750cd8f5..8a53f544568cf88dcf8eb7a8821568c3ea1fa213 100644 (file)
@@ -149,4 +149,30 @@ namespace PacksAtDifferentLevels {
                                    unsigned_pair<3, 4>,
                                    unsigned_pair<5, 6>>
                              >::value == 0? 1 : -1];
+
+  template<class> struct add_reference;
+  template<class> struct add_pointer;
+  template<class> struct add_const;
+
+  template<template<class> class ...Templates>
+  struct X5 {
+    template<typename> struct Inner {
+      static const unsigned value = 0;
+    };
+
+    template<typename ...Types>
+    struct Inner<tuple<Templates<Types>...>> {
+      static const unsigned value = 1;
+    };
+  };
+
+  int check10[X5<add_reference, add_pointer, add_const>
+                ::Inner<tuple<add_reference<int>,
+                              add_pointer<float>,
+                              add_const<double>>>::value == 1? 1 : -1];
+  int check11[X5<add_reference, add_pointer>
+                ::Inner<tuple<add_reference<int>,
+                              add_pointer<float>,
+                              add_const<double>>>::value == 0? 1 : -1];
+
 }
index 574b4c8b4efb016a6d2877b1f424a4516fb306f1..910f44989431d67631c003c55ad1f9667fbc78ab 100644 (file)
@@ -1228,6 +1228,11 @@ bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
     return Visit(MakeCursorTemplateRef(
                                   Name.getAsQualifiedTemplateName()->getDecl(), 
                                        Loc, TU));
+      
+  case TemplateName::SubstTemplateTemplateParmPack:
+    return Visit(MakeCursorTemplateRef(
+                  Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),
+                                       Loc, TU));
   }
                  
   return false;