r186713 - Fix for template substitution with packs.

Eli Friedman eli.friedman at gmail.com
Fri Jul 19 12:40:38 PDT 2013


Author: efriedma
Date: Fri Jul 19 14:40:38 2013
New Revision: 186713

URL: http://llvm.org/viewvc/llvm-project?rev=186713&view=rev
Log:
Fix for template substitution with packs.

When we see a pack, and replace it with a template argument which is
also a pack, we want to use the pack pattern, not the expanded pack.
The caller should take care of expanding the pack afterwards.

Fixes PR16646.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaTemplate/alias-templates.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=186713&r1=186712&r2=186713&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jul 19 14:40:38 2013
@@ -883,6 +883,16 @@ bool TemplateInstantiator::AlreadyTransf
   return true;
 }
 
+static TemplateArgument
+getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
+  assert(S.ArgumentPackSubstitutionIndex >= 0);        
+  assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+  Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex];
+  if (Arg.isPackExpansion())
+    Arg = Arg.getPackExpansionPattern();
+  return Arg;
+}
+
 Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
   if (!D)
     return 0;
@@ -902,10 +912,7 @@ Decl *TemplateInstantiator::TransformDec
       if (TTP->isParameterPack()) {
         assert(Arg.getKind() == TemplateArgument::Pack && 
                "Missing argument pack");
-        
-        assert(getSema().ArgumentPackSubstitutionIndex >= 0);        
-        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
-        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+        Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
       }
 
       TemplateName Template = Arg.getAsTemplate();
@@ -950,8 +957,7 @@ TemplateInstantiator::TransformFirstQual
         if (getSema().ArgumentPackSubstitutionIndex == -1)
           return 0;
         
-        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
-        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+        Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
       }
 
       QualType T = Arg.getAsType();
@@ -1053,9 +1059,8 @@ TemplateName TemplateInstantiator::Trans
           // keep the entire argument pack.
           return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
         }
-        
-        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
-        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+
+        Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
       }
       
       TemplateName Template = Arg.getAsTemplate();
@@ -1077,11 +1082,9 @@ TemplateName TemplateInstantiator::Trans
     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();
+    TemplateArgument Arg = SubstPack->getArgumentPack();
+    Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+    return Arg.getAsTemplate();
   }
   
   return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, 
@@ -1146,8 +1149,7 @@ TemplateInstantiator::TransformTemplateP
                                                                     Arg);
     }
     
-    assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
-    Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+    Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
   }
 
   return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
@@ -1160,14 +1162,6 @@ ExprResult TemplateInstantiator::transfo
   ExprResult result;
   QualType type;
 
-  // If the argument is a pack expansion, the parameter must actually be a
-  // parameter pack, and we should substitute the pattern itself, producing
-  // an expression which contains an unexpanded parameter pack.
-  if (arg.isPackExpansion()) {
-    assert(parm->isParameterPack() && "pack expansion for non-pack");
-    arg = arg.getPackExpansionPattern();
-  }
-
   // The template argument itself might be an expression, in which
   // case we just return that expression.
   if (arg.getKind() == TemplateArgument::Expression) {
@@ -1233,12 +1227,9 @@ TemplateInstantiator::TransformSubstNonT
     // We aren't expanding the parameter pack, so just return ourselves.
     return getSema().Owned(E);
   }
-  
-  const TemplateArgument &ArgPack = E->getArgumentPack();
-  unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
-  assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
-  
-  const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
+
+  TemplateArgument Arg = E->getArgumentPack();
+  Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
   return transformNonTypeTemplateParmRef(E->getParameterPack(),
                                          E->getParameterPackLocation(),
                                          Arg);
@@ -1409,8 +1400,7 @@ TemplateInstantiator::TransformTemplateT
         return Result;
       }
       
-      assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
-      Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+      Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
     }
     
     assert(Arg.getKind() == TemplateArgument::Type &&
@@ -1458,12 +1448,11 @@ TemplateInstantiator::TransformSubstTemp
     NewTL.setNameLoc(TL.getNameLoc());
     return TL.getType();
   }
-  
-  const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack();
-  unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
-  assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
-  
-  QualType Result = ArgPack.pack_begin()[Index].getAsType();
+
+  TemplateArgument Arg = TL.getTypePtr()->getArgumentPack();
+  Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+  QualType Result = Arg.getAsType();
+
   Result = getSema().Context.getSubstTemplateTypeParmType(
                                       TL.getTypePtr()->getReplacedParameter(),
                                                           Result);

Modified: cfe/trunk/test/SemaTemplate/alias-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/alias-templates.cpp?rev=186713&r1=186712&r2=186713&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/alias-templates.cpp (original)
+++ cfe/trunk/test/SemaTemplate/alias-templates.cpp Fri Jul 19 14:40:38 2013
@@ -166,3 +166,26 @@ namespace PR13136 {
     return 0;
   }
 }
+
+namespace PR16646 {
+  namespace test1 {
+    template <typename T> struct DefaultValue { const T value=0;};
+    template <typename ... Args> struct tuple {};
+    template <typename ... Args> using Zero = tuple<DefaultValue<Args> ...>;
+    template <typename ... Args> void f(const Zero<Args ...> &t);
+    void f() {
+        f(Zero<int,double,double>());
+    }
+  }
+
+  namespace test2 {
+    template<int x> struct X {};
+    template <template<int x> class temp> struct DefaultValue { const temp<0> value; };
+    template <typename ... Args> struct tuple {};
+    template <template<int x> class... Args> using Zero = tuple<DefaultValue<Args> ...>;
+    template <template<int x> class... Args> void f(const Zero<Args ...> &t);
+    void f() {
+      f(Zero<X,X,X>());
+    }
+  }
+}





More information about the cfe-commits mailing list