[cfe-commits] r152618 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.decls/temp.variadic/p4.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Mar 12 23:56:52 PDT 2012


Author: rsmith
Date: Tue Mar 13 01:56:52 2012
New Revision: 152618

URL: http://llvm.org/viewvc/llvm-project?rev=152618&view=rev
Log:
PR11850 + duplicates: don't assume that a function parameter pack expansion is
at the end of the parameter list.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=152618&r1=152617&r2=152618&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Mar 13 01:56:52 2012
@@ -2115,6 +2115,8 @@
            OldIdx != NumOldParams; ++OldIdx) {
         ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);
         if (!OldParam->isParameterPack() ||
+            // FIXME: Is this right? OldParam could expand to an empty parameter
+            // pack and the next parameter could be an unexpanded parameter pack
             (NewIdx < NumNewParams &&
              NewProtoLoc->getArg(NewIdx)->isParameterPack())) {
           // Simple case: normal parameter, or a parameter pack that's
@@ -2458,6 +2460,13 @@
 
   LocalInstantiationScope Scope(*this, MergeWithParentScope);
 
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  Sema::ContextRAII savedContext(*this, Function);
+
+  MultiLevelTemplateArgumentList TemplateArgs =
+    getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
+
   // Introduce the instantiated function parameters into the local
   // instantiation scope, and set the parameter names to those used
   // in the template.
@@ -2467,7 +2476,7 @@
     if (!PatternParam->isParameterPack()) {
       // Simple case: not a parameter pack.
       assert(FParamIdx < Function->getNumParams());
-      ParmVarDecl *FunctionParam = Function->getParamDecl(I);
+      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
       FunctionParam->setDeclName(PatternParam->getDeclName());
       Scope.InstantiatedLocal(PatternParam, FunctionParam);
       ++FParamIdx;
@@ -2476,22 +2485,16 @@
 
     // Expand the parameter pack.
     Scope.MakeInstantiatedLocalArgPack(PatternParam);
-    for (unsigned NumFParams = Function->getNumParams();
-         FParamIdx < NumFParams;
-         ++FParamIdx) {
+    unsigned NumArgumentsInExpansion
+      = getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
+    for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
       ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
       FunctionParam->setDeclName(PatternParam->getDeclName());
       Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+      ++FParamIdx;
     }
   }
 
-  // Enter the scope of this instantiation. We don't use
-  // PushDeclContext because we don't have a scope.
-  Sema::ContextRAII savedContext(*this, Function);
-
-  MultiLevelTemplateArgumentList TemplateArgs =
-    getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
-
   if (PatternDecl->isDefaulted()) {
     ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
 

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp?rev=152618&r1=152617&r2=152618&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp Tue Mar 13 01:56:52 2012
@@ -20,6 +20,52 @@
 
 // FIXME: Several more bullets to go
 
+// In a function parameter pack, the pattern is the parameter-declaration
+// without the ellipsis.
+namespace PR11850 {
+  template<typename ...T> struct S {
+    int f(T...a, int b) { return b; }
+  };
+  S<> s;
+  S<int*, char, const double&> t;
+  int k = s.f(0);
+  int l = t.f(&k, 'x', 5.9, 4);
+
+  template<typename ...As> struct A {
+    template<typename ...Bs> struct B {
+      template<typename ...Cs> struct C {
+        C(As..., Bs..., int &k, Cs...);
+      };
+    };
+  };
+  A<>::B<>::C<> c000(k);
+  A<int>::B<>::C<int> c101(1, k, 3);
+  A<>::B<int>::C<int> c011(1, k, 3);
+  A<int>::B<int>::C<> c110(1, 2, k);
+  A<int, int>::B<int, int>::C<int, int> c222(1, 2, 3, 4, k, 5, 6);
+  A<int, int, int>::B<>::C<> c300(1, 2, 3, k);
+
+  int &f();
+  char &f(void*);
+  template<typename ...A> struct U {
+    template<typename ...B> struct V {
+      auto g(A...a, B...b) -> decltype(f(a...));
+    };
+  };
+  U<>::V<int*> v0;
+  U<int*>::V<> v1;
+  int &v0f = v0.g(0);
+  char &v1f = v1.g(0);
+}
+namespace PR12096 {
+  void Foo(int) {}
+  void Foo(int, int) = delete;
+  template<typename ...Args> struct Var {
+    Var(const Args &...args, int *) { Foo(args...); }
+  };
+  Var<int> var(1, 0);
+}
+
 // In an initializer-list (8.5); the pattern is an initializer-clause.
 // Note: this also covers expression-lists, since expression-list is
 // just defined as initializer-list.





More information about the cfe-commits mailing list