]> granicus.if.org Git - clang/commitdiff
Implement more of C++0x [temp.arg.explicit]p9, allowing extension of
authorDouglas Gregor <dgregor@apple.com>
Mon, 10 Jan 2011 20:53:55 +0000 (20:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 10 Jan 2011 20:53:55 +0000 (20:53 +0000)
pack expansions in template argument lists and function parameter
lists. The implementation of this paragraph should be complete
*except* for cases where we're substituting into one of the unexpanded
packs in a pack expansion; that's a general issue I haven't solved yet.

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

lib/Sema/SemaTemplateDeduction.cpp
lib/Sema/TreeTransform.h
test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp

index 02e1a42dc3965d3917e4a48e4bd25fbcf17cc276..842ad5c188c1eaabbe5706c05de27b42b9d09ac6 100644 (file)
@@ -636,8 +636,7 @@ DeduceTemplateArguments(Sema &S,
   if (NumParams != NumArgs &&
       !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
       !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
-    return NumArgs < NumParams ? Sema::TDK_TooFewArguments 
-                               : Sema::TDK_TooManyArguments;
+    return Sema::TDK_NonDeducedMismatch;
   
   // C++0x [temp.deduct.type]p10:
   //   Similarly, if P has a form that contains (T), then each parameter type 
@@ -654,7 +653,7 @@ DeduceTemplateArguments(Sema &S,
       
       // Make sure we have an argument.
       if (ArgIdx >= NumArgs)
-        return Sema::TDK_TooFewArguments;
+        return Sema::TDK_NonDeducedMismatch;
           
       if (Sema::TemplateDeductionResult Result
           = DeduceTemplateArguments(S, TemplateParams,
@@ -736,7 +735,7 @@ DeduceTemplateArguments(Sema &S,
   
   // Make sure we don't have any extra arguments.
   if (ArgIdx < NumArgs)
-    return Sema::TDK_TooManyArguments;
+    return Sema::TDK_NonDeducedMismatch;
   
   return Sema::TDK_Success;
 }
@@ -788,10 +787,8 @@ DeduceTemplateArguments(Sema &S,
 
   // If the parameter type is not dependent, there is nothing to deduce.
   if (!Param->isDependentType()) {
-    if (!(TDF & TDF_SkipNonDependent) && Param != Arg) {
-      
+    if (!(TDF & TDF_SkipNonDependent) && Param != Arg)
       return Sema::TDK_NonDeducedMismatch;
-    }
     
     return Sema::TDK_Success;
   }
@@ -1365,7 +1362,7 @@ DeduceTemplateArguments(Sema &S,
       
       // Check whether we have enough arguments.
       if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
-        return NumberOfArgumentsMustMatch? Sema::TDK_TooFewArguments 
+        return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
                                          : Sema::TDK_Success;
       
       // Perform deduction for this Pi/Ai pair.
@@ -1459,7 +1456,7 @@ DeduceTemplateArguments(Sema &S,
   // If there is an argument remaining, then we had too many arguments.
   if (NumberOfArgumentsMustMatch &&
       hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
-    return Sema::TDK_TooManyArguments;
+    return Sema::TDK_NonDeducedMismatch;
   
   return Sema::TDK_Success;
 }
index 7eee4441740faea25e177e3c306f5e65ad805786..bc1ac1e6ae9b3308bb51297e4452d923a96317f1 100644 (file)
@@ -2850,7 +2850,20 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
         Outputs.addArgument(Out);
       }
       
-      // FIXME: Variadic templates retain expansion!
+      // If we're supposed to retain a pack expansion, do so by temporarily
+      // forgetting the partially-substituted parameter pack.
+      if (RetainExpansion) {
+        ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+        
+        if (getDerived().TransformTemplateArgument(Pattern, Out))
+          return true;
+        
+        Out = getDerived().RebuildPackExpansion(Out, Ellipsis);
+        if (Out.getArgument().isNull())
+          return true;
+        
+        Outputs.addArgument(Out);
+      }
       
       continue;
     }
@@ -3564,7 +3577,18 @@ bool TreeTransform<Derived>::
         continue;
       }
       
-      // FIXME: Variadic templates retain pack expansion!
+      // If we're supposed to retain a pack expansion, do so by temporarily
+      // forgetting the partially-substituted parameter pack.
+      if (RetainExpansion) {
+        ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+        QualType NewType = getDerived().TransformType(Pattern);
+        if (NewType.isNull())
+          return true;
+        
+        OutParamTypes.push_back(NewType);
+        if (PVars)
+          PVars->push_back(0);
+      }
 
       // We'll substitute the parameter now without expanding the pack 
       // expansion.
index 66ffb82adc98ecf54eecbc140f1cf54eba232e9a..b38cc2760937d4c56f2002bf1c84b6b59b1d57ab 100644 (file)
@@ -43,3 +43,26 @@ void test_explicit_spec_extension(double *dp) {
   double *dp1 = first_arg<>(dp);
 }
 
+template<typename ...Types> 
+struct tuple { };
+
+template<typename ...Types>
+void accept_tuple(tuple<Types...>);
+
+void test_explicit_spec_extension_targs(tuple<int, float, double> t3) {
+  accept_tuple(t3);
+  accept_tuple<int, float, double>(t3);
+  accept_tuple<int>(t3);
+  accept_tuple<int, float>(t3);
+}
+
+template<typename R, typename ...ParmTypes>
+void accept_function_ptr(R(*)(ParmTypes...));
+
+void test_explicit_spec_extension_funcparms(int (*f3)(int, float, double)) {
+  accept_function_ptr(f3);
+  accept_function_ptr<int>(f3);
+  accept_function_ptr<int, int>(f3);
+  accept_function_ptr<int, int, float>(f3);
+  accept_function_ptr<int, int, float, double>(f3);
+}