]> granicus.if.org Git - clang/commitdiff
Replace the representation of template template argument pack
authorDouglas Gregor <dgregor@apple.com>
Wed, 5 Jan 2011 18:58:31 +0000 (18:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 5 Jan 2011 18:58:31 +0000 (18:58 +0000)
expansions with something that is easier to use correctly: a new
template argment kind, rather than a bit on an existing kind. Update
all of the switch statements that deal with template arguments, fixing
a few latent bugs in the process. I"m happy with this representation,
now.

And, oh look! Template instantiation and deduction work for template
template argument pack expansions.

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

19 files changed:
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/TemplateBase.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/Decl.cpp
lib/AST/DumpXML.cpp
lib/AST/StmtProfile.cpp
lib/AST/TemplateBase.cpp
lib/CodeGen/Mangle.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateDeduction.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
test/CXX/temp/temp.decls/temp.variadic/p4.cpp
tools/libclang/CIndex.cpp
tools/libclang/CIndexUSRs.cpp

index 894ecdd29abc368e32608a8a4bc8fee43ac00929..7e39a344a6241ea493ff6d5a1f9897256e6500c3 100644 (file)
@@ -535,7 +535,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
     return getDerived().TraverseType(Arg.getAsType());
 
   case TemplateArgument::Template:
-    return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+  case TemplateArgument::TemplateExpansion:
+    return getDerived().TraverseTemplateName(
+                                          Arg.getAsTemplateOrTemplatePattern());
 
   case TemplateArgument::Expression:
     return getDerived().TraverseStmt(Arg.getAsExpr());
@@ -570,7 +572,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
   }
 
   case TemplateArgument::Template:
-    return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+  case TemplateArgument::TemplateExpansion:
+    return getDerived().TraverseTemplateName(
+                                         Arg.getAsTemplateOrTemplatePattern());
 
   case TemplateArgument::Expression:
     return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
index 758926c957971127c8343bfd569ae4aaf9165448..7f3e591a96535c352fbb78e01cad7ca424d6b02f 100644 (file)
@@ -55,6 +55,9 @@ public:
     /// The template argument is a template name that was provided for a 
     /// template template parameter.
     Template,
+    /// The template argument is a pack expansion of a template name that was 
+    /// provided for a template template parameter.
+    TemplateExpansion,
     /// The template argument is a value- or type-dependent expression
     /// stored in an Expr*.
     Expression,
@@ -77,10 +80,6 @@ private:
       TemplateArgument *Args;
       unsigned NumArgs;
     } Args;
-    struct {
-      void *Template;
-      bool PackExpansion;
-    } TemplateArg;
   };
 
 public:
@@ -119,10 +118,9 @@ public:
   /// \param Name The template name.
   /// \param PackExpansion Whether this template argument is a pack expansion.
   TemplateArgument(TemplateName Name, bool PackExpansion = false) 
-    : Kind(Template) 
+    : Kind(PackExpansion? TemplateExpansion : Template) 
   {
-    TemplateArg.Template = Name.getAsVoidPointer();
-    TemplateArg.PackExpansion = PackExpansion;
+    TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
   }
   
   /// \brief Construct a template argument that is an expression.
@@ -153,8 +151,6 @@ public:
     } else if (Kind == Pack) {
       Args.NumArgs = Other.Args.NumArgs;
       Args.Args = Other.Args.Args;
-    } else if (Kind == Template) {
-      TemplateArg = Other.TemplateArg;
     } else
       TypeOrValue = Other.TypeOrValue;
   }
@@ -181,8 +177,6 @@ public:
     } else if (Other.Kind == Pack) {
       Args.NumArgs = Other.Args.NumArgs;
       Args.Args = Other.Args.Args;
-    } else if (Other.Kind == Template) {
-      TemplateArg = Other.TemplateArg;
     } else {
       TypeOrValue = Other.TypeOrValue;
     }
@@ -234,9 +228,20 @@ public:
     if (Kind != Template)
       return TemplateName();
     
-    return TemplateName::getFromVoidPointer(TemplateArg.Template);
+    return TemplateName::getFromVoidPointer(
+                                          reinterpret_cast<void*>(TypeOrValue));
   }
-  
+
+  /// \brief Retrieve the template argument as a template name; if the argument
+  /// is a pack expansion, return the pattern as a template name.
+  TemplateName getAsTemplateOrTemplatePattern() const {
+    if (Kind != Template && Kind != TemplateExpansion)
+      return TemplateName();
+    
+    return TemplateName::getFromVoidPointer(
+                                          reinterpret_cast<void*>(TypeOrValue));
+  }
+
   /// \brief Retrieve the template argument as an integral value.
   llvm::APSInt *getAsIntegral() {
     if (Kind != Integral)
@@ -394,12 +399,14 @@ public:
                       SourceLocation EllipsisLoc = SourceLocation())
     : Argument(Argument), 
       LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
-    assert(Argument.getKind() == TemplateArgument::Template);
+    assert(Argument.getKind() == TemplateArgument::Template ||
+           Argument.getKind() == TemplateArgument::TemplateExpansion);
   }
   
   /// \brief - Fetches the primary location of the argument.
   SourceLocation getLocation() const {
-    if (Argument.getKind() == TemplateArgument::Template)
+    if (Argument.getKind() == TemplateArgument::Template ||
+        Argument.getKind() == TemplateArgument::TemplateExpansion)
       return getTemplateNameLoc();
     
     return getSourceRange().getBegin();
@@ -432,17 +439,19 @@ public:
   }
   
   SourceRange getTemplateQualifierRange() const {
-    assert(Argument.getKind() == TemplateArgument::Template);
+    assert(Argument.getKind() == TemplateArgument::Template ||
+           Argument.getKind() == TemplateArgument::TemplateExpansion);
     return LocInfo.getTemplateQualifierRange();
   }
   
   SourceLocation getTemplateNameLoc() const {
-    assert(Argument.getKind() == TemplateArgument::Template);
+    assert(Argument.getKind() == TemplateArgument::Template ||
+           Argument.getKind() == TemplateArgument::TemplateExpansion);
     return LocInfo.getTemplateNameLoc();
   }  
   
   SourceLocation getTemplateEllipsisLoc() const {
-    assert(Argument.getKind() == TemplateArgument::Template);
+    assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
     return LocInfo.getTemplateEllipsisLoc();
   }
   
index b4520609ff78521c512f600ade974b7f1cbca4c6..6e7f7c31ea59cf913ed8e2d84559f51f1f55413a 100644 (file)
@@ -2692,7 +2692,12 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
 
     case TemplateArgument::Template:
       return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
-      
+
+    case TemplateArgument::TemplateExpansion:
+      return TemplateArgument(getCanonicalTemplateName(
+                                         Arg.getAsTemplateOrTemplatePattern()),
+                              true);
+
     case TemplateArgument::Integral:
       return TemplateArgument(*Arg.getAsIntegral(),
                               getCanonicalType(Arg.getIntegralType()));
index 70c863204709cb2545ffe7932771ddee01d770e9..5a94de902010fb27178768843781d7d6e94caddf 100644 (file)
@@ -301,7 +301,12 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return IsStructurallyEquivalent(Context, 
                                     Arg1.getAsTemplate(), 
                                     Arg2.getAsTemplate());
-      
+
+  case TemplateArgument::TemplateExpansion:
+    return IsStructurallyEquivalent(Context, 
+                                    Arg1.getAsTemplateOrTemplatePattern(), 
+                                    Arg2.getAsTemplateOrTemplatePattern());
+
   case TemplateArgument::Expression:
     return IsStructurallyEquivalent(Context, 
                                     Arg1.getAsExpr(), Arg2.getAsExpr());
@@ -1785,7 +1790,16 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
     
     return TemplateArgument(ToTemplate);
   }
-      
+
+  case TemplateArgument::TemplateExpansion: {
+    TemplateName ToTemplate 
+      = Importer.Import(From.getAsTemplateOrTemplatePattern());
+    if (ToTemplate.isNull())
+      return TemplateArgument();
+    
+    return TemplateArgument(ToTemplate, true);
+  }
+
   case TemplateArgument::Expression:
     if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
       return TemplateArgument(ToExpr);
index 08272e76ca4fb7720d63d9cc79a8659e90b38b41..5b82ddd7c69f7b542c8c65b1e0cc1457be1991aa 100644 (file)
@@ -179,7 +179,9 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
       break;
 
     case TemplateArgument::Template:
-      if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
+    case TemplateArgument::TemplateExpansion:
+      if (TemplateDecl *Template 
+                = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
         LV = merge(LV, getLVForDecl(Template, F));
       break;
 
index 7465ea410d73e36161984701b30d2dad037f6fa1..65a18aa8d1b256afe5c27dd25148c49bb4393c17 100644 (file)
@@ -319,6 +319,10 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
       break;
     }
     case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
+      // FIXME: Implement!
+      break;
+        
     case TemplateArgument::Declaration: {
       visitDeclRef(A.getAsDecl());
       break;
index 17a9326cc0b9b94dfcdabd41d9d7b7cfdc6e50ed..63c3197ebce2cdb0a76019ab9f3846ebea51c066 100644 (file)
@@ -972,7 +972,8 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
     break;
 
   case TemplateArgument::Template:
-    VisitTemplateName(Arg.getAsTemplate());
+  case TemplateArgument::TemplateExpansion:
+    VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
     break;
       
   case TemplateArgument::Declaration:
index 6eae6a4192f8b7477743c36708d859543f2d4302..de5531f0f715af369c487fd259192dc502949850 100644 (file)
@@ -39,7 +39,10 @@ bool TemplateArgument::isDependent() const {
 
   case Template:
     return getAsTemplate().isDependent();
-      
+
+  case TemplateExpansion:
+    return true;
+
   case Declaration:
     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
       return DC->isDependentContext();
@@ -70,14 +73,15 @@ bool TemplateArgument::isPackExpansion() const {
   case Declaration:
   case Integral:
   case Pack:    
+  case Template:
     return false;
       
+  case TemplateExpansion:
+    return true;
+      
   case Type:
     return isa<PackExpansionType>(getAsType());
-      
-  case Template:
-    return TemplateArg.PackExpansion;
-    
+          
   case Expression:
     return isa<PackExpansionExpr>(getAsExpr());
   }
@@ -90,6 +94,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
   case Null:
   case Declaration:
   case Integral:
+  case TemplateExpansion:
     break;
 
   case Type:
@@ -98,8 +103,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
     break;
 
   case Template:
-    if (!TemplateArg.PackExpansion && 
-        getAsTemplate().containsUnexpandedParameterPack())
+    if (getAsTemplate().containsUnexpandedParameterPack())
       return true;
     break;
         
@@ -135,20 +139,22 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
     break;
 
   case Template:
-    ID.AddBoolean(TemplateArg.PackExpansion);
+  case TemplateExpansion: {
+    TemplateName Template = getAsTemplateOrTemplatePattern();
     if (TemplateTemplateParmDecl *TTP
           = dyn_cast_or_null<TemplateTemplateParmDecl>(
-                                       getAsTemplate().getAsTemplateDecl())) {
+                                                Template.getAsTemplateDecl())) {
       ID.AddBoolean(true);
       ID.AddInteger(TTP->getDepth());
       ID.AddInteger(TTP->getPosition());
       ID.AddBoolean(TTP->isParameterPack());
     } else {
       ID.AddBoolean(false);
-      ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
-                      .getAsVoidPointer());
+      ID.AddPointer(Context.getCanonicalTemplateName(Template)
+                                                          .getAsVoidPointer());
     }
     break;
+  }
       
   case Integral:
     getAsIntegral()->Profile(ID);
@@ -173,13 +179,11 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
   case Null:
   case Type:
   case Declaration:
-  case Expression:
+  case Expression:      
+  case Template:
+  case TemplateExpansion:
     return TypeOrValue == Other.TypeOrValue;
 
-  case Template:
-    return TemplateArg.Template == Other.TemplateArg.Template &&
-           TemplateArg.PackExpansion == Other.TemplateArg.PackExpansion;
-      
   case Integral:
     return getIntegralType() == Other.getIntegralType() &&
            *getAsIntegral() == *Other.getAsIntegral();
@@ -206,13 +210,14 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
   case Expression:
     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
     
-  case Template:
-    return TemplateArgument(getAsTemplate(), false);
+  case TemplateExpansion:
+    return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
     
   case Declaration:
   case Integral:
   case Pack:
   case Null:
+  case Template:
     return TemplateArgument();
   }
   
@@ -248,13 +253,15 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
     break;
   }
     
-  case Template: {
+  case Template:
     getAsTemplate().print(Out, Policy);
-    if (TemplateArg.PackExpansion)
-      Out << "...";
     break;
-  }
-    
+
+  case TemplateExpansion:
+    getAsTemplateOrTemplatePattern().print(Out, Policy);
+    Out << "...";
+    break;
+      
   case Integral: {
     Out << getAsIntegral()->toString(10);
     break;
@@ -299,15 +306,18 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
     else
       return SourceRange();
 
-  case TemplateArgument::Template: {
-    SourceLocation End = getTemplateNameLoc();
-    if (getTemplateEllipsisLoc().isValid())
-      End = getTemplateEllipsisLoc();
+  case TemplateArgument::Template:
     if (getTemplateQualifierRange().isValid())
-      return SourceRange(getTemplateQualifierRange().getBegin(), End);
-    return SourceRange(getTemplateNameLoc(), End);
-  }
-      
+      return SourceRange(getTemplateQualifierRange().getBegin(), 
+                         getTemplateNameLoc());
+    return SourceRange(getTemplateNameLoc());
+
+  case TemplateArgument::TemplateExpansion:
+    if (getTemplateQualifierRange().isValid())
+      return SourceRange(getTemplateQualifierRange().getBegin(), 
+                         getTemplateEllipsisLoc());
+    return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
+
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
@@ -355,13 +365,14 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
     Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
     return TemplateArgumentLoc(Pattern, Pattern);
   }
-      
-  case TemplateArgument::Template:
+
+  case TemplateArgument::TemplateExpansion:
     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
                                getTemplateQualifierRange(),
                                getTemplateNameLoc());
     
   case TemplateArgument::Declaration:
+  case TemplateArgument::Template:
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
@@ -389,11 +400,11 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
     return DB << Arg.getAsIntegral()->toString(10);
       
   case TemplateArgument::Template:
-    DB << Arg.getAsTemplate();
-    if (Arg.isPackExpansion())
-      DB << "...";
-    return DB;
-      
+    return DB << Arg.getAsTemplate();
+
+  case TemplateArgument::TemplateExpansion:
+    return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
+
   case TemplateArgument::Expression: {
     // This shouldn't actually ever happen, so it's okay that we're
     // regurgitating an expression here.
index 0969b8716f6406d2057785f3a377cebd4ed56e43..ff0e9223c818284b6a1d871350e46bf39699dc23 100644 (file)
@@ -2169,6 +2169,11 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
     // This is mangled as <type>.
     mangleType(A.getAsTemplate());
     break;
+  case TemplateArgument::TemplateExpansion:
+    // This is mangled as Dp <type>.
+    Out << "Dp";
+    mangleType(A.getAsTemplateOrTemplatePattern());
+    break;
   case TemplateArgument::Expression:
     Out << 'X';
     mangleExpression(A.getAsExpr());
index 5ed973b1a800a4129e97eb7b563f4143d765ac8f..161908e200701ce03c5bf6bbeed82a7434604a82 100644 (file)
@@ -1693,11 +1693,12 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
       addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
       break;
 
-    case TemplateArgument::Template: {
+    case TemplateArgument::Template: 
+    case TemplateArgument::TemplateExpansion: {
       // [...] the namespaces in which any template template arguments are
       // defined; and the classes in which any member templates used as
       // template template arguments are defined.
-      TemplateName Template = Arg.getAsTemplate();
+      TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
       if (ClassTemplateDecl *ClassTemplate
                  = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
         DeclContext *Ctx = ClassTemplate->getDeclContext();
index 9adcf1c81fd84fa2b10e7cedb614162edcec3915..2c9a4307ed54a3ff5a7741c780a8f887fb52fb3c 100644 (file)
@@ -2256,10 +2256,12 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
       break;
       
     case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
       // We were given a template template argument. It may not be ill-formed;
       // see below.
       if (DependentTemplateName *DTN
-            = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+            = Arg.getArgument().getAsTemplateOrTemplatePattern()
+                                              .getAsDependentTemplateName()) {
         // We have a template argument such as \c T::template X, which we
         // parsed as a template template argument. However, since we now
         // know that we need a non-type template argument, convert this
@@ -2273,6 +2275,17 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
                                                Arg.getTemplateQualifierRange(),
                                                     NameInfo);
         
+        // If we parsed the template argument as a pack expansion, create a
+        // pack expansion expression.
+        if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
+          ExprResult Expansion = ActOnPackExpansion(E, 
+                                                  Arg.getTemplateEllipsisLoc());
+          if (Expansion.isInvalid())
+            return true;
+          
+          E = Expansion.get();
+        }
+        
         TemplateArgument Result;
         if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
           return true;
@@ -2348,6 +2361,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
     return true;
     
   case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
     if (CheckTemplateArgument(TempParm, Arg))
       return true;
       
index a72a29378a8199c530b31ba5b7f41573870d064b..5837ebd8e541ff636386bab8f7a00c54712925a9 100644 (file)
@@ -168,7 +168,16 @@ checkDeducedTemplateArguments(ASTContext &Context,
     
     // All other combinations are incompatible.
     return DeducedTemplateArgument();      
-      
+
+  case TemplateArgument::TemplateExpansion:
+    if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+        Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(), 
+                                    Y.getAsTemplateOrTemplatePattern()))
+      return X;
+    
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();      
+
   case TemplateArgument::Expression:
     // If we deduced a dependent expression in one case and either an integral 
     // constant or a declaration in another case, keep the integral constant 
@@ -934,7 +943,7 @@ DeduceTemplateArguments(Sema &S,
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
-      
+
   case TemplateArgument::Template:
     if (Arg.getKind() == TemplateArgument::Template)
       return DeduceTemplateArguments(S, TemplateParams, 
@@ -943,6 +952,10 @@ DeduceTemplateArguments(Sema &S,
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::TemplateExpansion:
+    llvm_unreachable("caller should handle pack expansions");
+    break;
       
   case TemplateArgument::Declaration:
     if (Arg.getKind() == TemplateArgument::Declaration &&
@@ -1282,10 +1295,11 @@ static bool isSameTemplateArg(ASTContext &Context,
              Y.getAsDecl()->getCanonicalDecl();
 
     case TemplateArgument::Template:
-      return Context.getCanonicalTemplateName(X.getAsTemplate())
-               .getAsVoidPointer() ==
-             Context.getCanonicalTemplateName(Y.getAsTemplate())
-               .getAsVoidPointer();
+    case TemplateArgument::TemplateExpansion:
+      return Context.getCanonicalTemplateName(
+                    X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
+             Context.getCanonicalTemplateName(
+                    Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
       
     case TemplateArgument::Integral:
       return *X.getAsIntegral() == *Y.getAsIntegral();
@@ -1356,9 +1370,11 @@ getTrivialTemplateArgumentLoc(Sema &S,
   }
     
   case TemplateArgument::Template:
-    return TemplateArgumentLoc(Arg, SourceRange(), Loc,
-                               Arg.isPackExpansion()? Loc : SourceLocation());
-    
+    return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+
+  case TemplateArgument::TemplateExpansion:
+    return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+
   case TemplateArgument::Expression:
     return TemplateArgumentLoc(Arg, Arg.getAsExpr());
     
@@ -3244,7 +3260,9 @@ MarkUsedTemplateParameters(Sema &SemaRef,
     break;
 
   case TemplateArgument::Template:
-    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(), 
+  case TemplateArgument::TemplateExpansion:
+    MarkUsedTemplateParameters(SemaRef, 
+                               TemplateArg.getAsTemplateOrTemplatePattern(), 
                                OnlyDeduced, Depth, Used);
     break;
 
index 919f2c879c894a404cd7a68cdad256f93d8f6584..d15f91a745e6e62d9e4a01c222907649612d6c21 100644 (file)
@@ -2123,12 +2123,18 @@ public:
     }
         
     case TemplateArgument::Template:
-      llvm_unreachable("Unsupported pack expansion of templates");
+      return TemplateArgumentLoc(TemplateArgument(
+                                          Pattern.getArgument().getAsTemplate(),
+                                                  true),
+                                 Pattern.getTemplateQualifierRange(),
+                                 Pattern.getTemplateNameLoc(),
+                                 EllipsisLoc);
         
     case TemplateArgument::Null:
     case TemplateArgument::Integral:
     case TemplateArgument::Declaration:
     case TemplateArgument::Pack:
+    case TemplateArgument::TemplateExpansion:
       llvm_unreachable("Pack expansion pattern has no parameter packs");
         
     case TemplateArgument::Type:
@@ -2531,7 +2537,11 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
   case TemplateArgument::Template:
     Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
     break;
-      
+
+  case TemplateArgument::TemplateExpansion:
+    Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+    break;
+
   case TemplateArgument::Expression:
     Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
     break;
@@ -2600,7 +2610,10 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
                                  Input.getTemplateNameLoc());
     return false;
   }
-      
+
+  case TemplateArgument::TemplateExpansion:
+    llvm_unreachable("Caller should expand pack expansions");
+
   case TemplateArgument::Expression: {
     // Template argument expressions are not potentially evaluated.
     EnterExpressionEvaluationContext Unevaluated(getSema(),
index ed0e58f18fa90cb2e17e8aab58a3b1a0a5ffc3ae..3bf51e6a0e99e8188c2257dee1d0d97e89c0dfc6 100644 (file)
@@ -3379,6 +3379,12 @@ ASTReader::GetTemplateArgumentLocInfo(PerFileData &F,
   case TemplateArgument::Type:
     return GetTypeSourceInfo(F, Record, Index);
   case TemplateArgument::Template: {
+    SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
+    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+    return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+                                   SourceLocation());
+  }
+  case TemplateArgument::TemplateExpansion: {
     SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
     SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
     SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
@@ -4216,7 +4222,8 @@ ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
 TemplateArgument
 ASTReader::ReadTemplateArgument(PerFileData &F,
                                 const RecordData &Record, unsigned &Idx) {
-  switch ((TemplateArgument::ArgKind)Record[Idx++]) {
+  TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+  switch (Kind) {
   case TemplateArgument::Null:
     return TemplateArgument();
   case TemplateArgument::Type:
@@ -4228,10 +4235,10 @@ ASTReader::ReadTemplateArgument(PerFileData &F,
     QualType T = GetType(Record[Idx++]);
     return TemplateArgument(Value, T);
   }
-  case TemplateArgument::Template: {
+  case TemplateArgument::Template: 
+  case TemplateArgument::TemplateExpansion: {
     TemplateName Name = ReadTemplateName(Record, Idx);
-    bool IsPackExpansion = Record[Idx++];
-    return TemplateArgument(Name, IsPackExpansion);
+    return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
   }
   case TemplateArgument::Expression:
     return TemplateArgument(ReadExpr(F));
index 44f17e40b1a31c3ffad36ef809b444c19ae28845..2c0239de17e1483373600ce29de663189c977915 100644 (file)
@@ -2887,6 +2887,10 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
     AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record);
     break;
   case TemplateArgument::Template:
+    AddSourceRange(Arg.getTemplateQualifierRange(), Record);
+    AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+    break;
+  case TemplateArgument::TemplateExpansion:
     AddSourceRange(Arg.getTemplateQualifierRange(), Record);
     AddSourceLocation(Arg.getTemplateNameLoc(), Record);
     AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
@@ -3176,8 +3180,8 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg,
     AddTypeRef(Arg.getIntegralType(), Record);
     break;
   case TemplateArgument::Template:
-    AddTemplateName(Arg.getAsTemplate(), Record);
-    Record.push_back(Arg.isPackExpansion());
+  case TemplateArgument::TemplateExpansion:
+    AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
     break;
   case TemplateArgument::Expression:
     AddStmt(Arg.getAsExpr());
index 3e9e8f5fb27382c69fdce7ce74627220aa8e12aa..75181081ad908927b7b3f3f1fb317888a73164d3 100644 (file)
@@ -163,4 +163,44 @@ namespace TemplateTemplateApply {
   int check0[is_same<apply_each<int, 
                                 add_reference, add_pointer, add_const>::type,
                      tuple<int&, int*, int const>>::value? 1 : -1];
+
+  template<typename T, template<class> class ...Meta>
+  struct apply_each_indirect {
+    typedef typename apply_each<T, Meta...>::type type;
+  };
+
+  int check1[is_same<apply_each_indirect<int, add_reference, add_pointer, 
+                                         add_const>::type,
+                     tuple<int&, int*, int const>>::value? 1 : -1];
+
+  template<typename T, typename ...Meta>
+  struct apply_each_nested {
+    typedef typename apply_each<T, Meta::template apply...>::type type;
+  };
+
+  struct add_reference_meta {
+    template<typename T>
+    struct apply {
+      typedef T& type;
+    };
+  };
+
+  struct add_pointer_meta {
+    template<typename T>
+    struct apply {
+      typedef T* type;
+    };
+  };
+
+  struct add_const_meta {
+    template<typename T>
+    struct apply {
+      typedef const T type;
+    };
+  };
+
+  int check2[is_same<apply_each_nested<int, add_reference_meta, 
+                                       add_pointer_meta, add_const_meta>::type,
+                     tuple<int&, int*, int const>>::value? 1 : -1];
+
 }
index 7e6a6b0f0d332d25175ad322128ff8294a38139c..b865d51411ea9768738ecedbe65718f662f3e944 100644 (file)
@@ -18,7 +18,7 @@ struct is_same<T, T> {
   static const bool value = true;
 };
 
-// FIXME: Many more bullets to go
+// FIXME: Several more bullets to go
 
 // In an initializer-list (8.5); the pattern is an initializer-clause.
 // Note: this also covers expression-lists, since expression-list is
index f28115418bdc38802c79c76ea534f657b364dd9a..979d678d5ace0a823bf8c64a6d78fd7f4ad55aff 100644 (file)
@@ -1256,7 +1256,8 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
     return false;
   
   case TemplateArgument::Template:
-    return VisitTemplateName(TAL.getArgument().getAsTemplate(), 
+  case TemplateArgument::TemplateExpansion:
+    return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(), 
                              TAL.getTemplateNameLoc());
   }
   
index c96dad5cd0fe2e92325dfe25d7945d7c9eda8dd8..8aed372be67ef7a0345e47fdbdb973f86eb477fb 100644 (file)
@@ -708,7 +708,9 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
     break;
       
   case TemplateArgument::Template:
-    VisitTemplateName(Arg.getAsTemplate());
+  case TemplateArgument::TemplateExpansion:
+      // FIXME: variadic templates
+    VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
     break;
       
   case TemplateArgument::Expression: