]> granicus.if.org Git - clang/commitdiff
Implement the last bullet of [temp.deduct.type]p5 and part of the last
authorDouglas Gregor <dgregor@apple.com>
Tue, 11 Jan 2011 01:52:23 +0000 (01:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 11 Jan 2011 01:52:23 +0000 (01:52 +0000)
sentence of [temp.deduct.call]p1, both of which concern the
non-deducibility of parameter packs not at the end of a
parameter-type-list. The latter isn't fully implemented yet; see the
new FIXME.

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

lib/AST/Decl.cpp
lib/AST/Type.cpp
lib/Sema/SemaTemplateDeduction.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp [new file with mode: 0644]

index 24fc45f4be1dd6a3592017305eb3eb8ed2da18b0..786f28a60da3094958632ea6c65060bc8aa494ce 100644 (file)
@@ -1444,6 +1444,9 @@ void FunctionDecl::setParams(ASTContext &C,
 /// function parameters, if some of the parameters have default
 /// arguments (in C++) or the last parameter is a parameter pack.
 unsigned FunctionDecl::getMinRequiredArguments() const {
+  if (!getASTContext().getLangOptions().CPlusPlus)
+    return getNumParams();
+  
   unsigned NumRequiredArgs = getNumParams();  
   
   // If the last parameter is a parameter pack, we don't need an argument for 
@@ -1458,6 +1461,16 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
          getParamDecl(NumRequiredArgs-1)->hasDefaultArg())
     --NumRequiredArgs;
 
+  // We might have parameter packs before the end. These can't be deduced,
+  // but they can still handle multiple arguments.
+  unsigned ArgIdx = NumRequiredArgs;
+  while (ArgIdx > 0) {
+    if (getParamDecl(ArgIdx - 1)->isParameterPack())
+      NumRequiredArgs = ArgIdx;
+    
+    --ArgIdx;
+  }
+  
   return NumRequiredArgs;
 }
 
index 708c344bc783d48b1a6a13d20d8ea60c714deb28..cc0d7f16e7fadb382c875e55e104aff5d776af67 100644 (file)
@@ -1144,7 +1144,11 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
 }
 
 bool FunctionProtoType::isTemplateVariadic() const {
-  return getNumArgs() && isa<PackExpansionType>(getArgType(getNumArgs() - 1));
+  for (unsigned ArgIdx = getNumArgs(); ArgIdx; --ArgIdx)
+    if (isa<PackExpansionType>(getArgType(ArgIdx - 1)))
+      return true;
+  
+  return false;
 }
 
 void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
index 842ad5c188c1eaabbe5706c05de27b42b9d09ac6..1bc24db27aa1f836b1219191fa2a698a0cf18054 100644 (file)
@@ -666,6 +666,13 @@ DeduceTemplateArguments(Sema &S,
       continue;
     }
     
+    // C++0x [temp.deduct.type]p5:
+    //   The non-deduced contexts are:
+    //     - A function parameter pack that does not occur at the end of the 
+    //       parameter-declaration-clause.
+    if (ParamIdx + 1 < NumParams)
+      return Sema::TDK_Success;
+
     // C++0x [temp.deduct.type]p10:
     //   If the parameter-declaration corresponding to Pi is a function 
     //   parameter pack, then the type of its declarator- id is compared with
@@ -2483,7 +2490,12 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
     //   the call is compared with the type P of the declarator-id of the 
     //   function parameter pack. Each comparison deduces template arguments 
     //   for subsequent positions in the template parameter packs expanded by 
-    //   the function parameter pack.
+    //   the function parameter pack. For a function parameter pack that does
+    //   not occur at the end of the parameter-declaration-list, the type of 
+    //   the parameter pack is a non-deduced context.
+    if (ParamIdx + 1 < NumParams)
+      break;
+    
     QualType ParamPattern = ParamExpansion->getPattern();
     llvm::SmallVector<unsigned, 2> PackIndices;
     {
index c29ff865b2a53f1b6b13228833ca919b8b92b71b..50b24dc41d3280f7edcc771caf3ec8b9482bba09 100644 (file)
@@ -1894,6 +1894,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
         // Parameter pack: make the instantiation an argument pack.
         SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
                                                                       OldParam);
+        // FIXME: Variadic templates. Figure out how many arguments are in the
+        // expansion of OldParam, so we don't gobble all of the arguments here.
         while (NewIdx < NumNewParams) {
           ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
           Params.push_back(NewParam);
index 46a6b1e081f50e06e2bd818d07c180e2d0e7ec98..4b480ddd3f1e6ccb29339b509b6990688ced7e3d 100644 (file)
@@ -74,3 +74,18 @@ void test_pair_deduction(int *ip, float *fp, double *dp) {
 
   first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}}
 }
+
+// For a function parameter pack that does not occur at the end of the
+// parameter-declaration-list, the type of the parameter pack is a
+// non-deduced context.
+// FIXME: We're not in a position to handle this yet.
+#if 0
+template<typename ...Types> struct tuple { };
+
+template<typename ...Types>
+void pack_not_at_end(tuple<Types...>, Types... values, int);
+
+void test_pack_not_at_end(tuple<int*, double*> t2) {
+  pack_not_at_end(t2, 0, 0, 0);
+}
+#endif
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp
new file mode 100644 (file)
index 0000000..cf68a01
--- /dev/null
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// FIXME: More bullets to go!
+
+template<typename T, typename U>
+struct has_nondeduced_pack_test {
+  static const bool value = false;
+};
+
+template<typename R, typename FirstType, typename ...Types>
+struct has_nondeduced_pack_test<R(FirstType, Types..., int), 
+                                R(FirstType, Types...)> {
+  static const bool value = true;
+};
+
+// - A function parameter pack that does not occur at the end of the
+//   parameter-declaration-clause.
+int check_nondeduced_pack_test0[
+                   has_nondeduced_pack_test<int(float, double, int),
+                                            int(float, double)>::value? 1 : -1];
+
+