* gcc/cp/pt.c (make_fnparm_pack): Split out from...
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Mar 2009 21:03:01 +0000 (21:03 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Mar 2009 21:03:01 +0000 (21:03 +0000)
        (instantiate_decl): ...here.
        (tsubst_pack_expansion): Handle being called in a late-specified
        return type.
        * libiberty/cp-demangle.c (d_expression): Handle pack expansion.
        (d_find_pack): Handle DEMANGLE_COMPONENT_FUNCTION_PARAM.
        (d_print_subexpr): Don't wrap function parms in ().
        (d_print_comp) [DEMANGLE_COMPONENT_PACK_EXPANSION]: Handle
        not finding a pack.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145013 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/auto12.C
libiberty/ChangeLog
libiberty/cp-demangle.c
libiberty/testsuite/demangle-expected

index 77c195a..e9e424d 100644 (file)
@@ -1,5 +1,10 @@
 2009-03-23  Jason Merrill  <jason@redhat.com>
 
+       * pt.c (make_fnparm_pack): Split out from...
+       (instantiate_decl): ...here.
+       (tsubst_pack_expansion): Handle being called in a late-specified
+       return type.
+
        PR c++/39526
        * name-lookup.c (pushdecl_maybe_friend): Don't warn about shadowing
        a parm with a parm.
index 1c40823..5092c72 100644 (file)
@@ -174,6 +174,7 @@ static tree tsubst (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree, bool);
 static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_decl (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -7435,6 +7436,37 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   return r;
 }
 
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+   NONTYPE_ARGUMENT_PACK.  */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+  /* Collect all of the extra "packed" parameters into an
+     argument pack.  */
+  tree parmvec;
+  tree parmtypevec;
+  tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
+  tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+  int i, len = list_length (spec_parm);
+
+  /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters.  */
+  parmvec = make_tree_vec (len);
+  parmtypevec = make_tree_vec (len);
+  for (i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
+    {
+      TREE_VEC_ELT (parmvec, i) = spec_parm;
+      TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
+    }
+
+  /* Build the argument packs.  */
+  SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
+  SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
+  TREE_TYPE (argpack) = argtypepack;
+
+  return argpack;
+}        
+
 /* Substitute ARGS into T, which is an pack expansion
    (i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
    TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node
@@ -7449,6 +7481,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   tree first_arg_pack; int i, len = -1;
   tree result;
   int incomplete = 0;
+  bool very_local_specializations = false;
 
   gcc_assert (PACK_EXPANSION_P (t));
   pattern = PACK_EXPANSION_PATTERN (t);
@@ -7465,7 +7498,18 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
       tree orig_arg = NULL_TREE;
 
       if (TREE_CODE (parm_pack) == PARM_DECL)
-       arg_pack = retrieve_local_specialization (parm_pack);
+       {
+         arg_pack = retrieve_local_specialization (parm_pack);
+         if (arg_pack == NULL_TREE)
+           {
+             /* This can happen for a parameter name used later in a function
+                declaration (such as in a late-specified return type).  Just
+                make a dummy decl, since it's only used for its type.  */
+             gcc_assert (skip_evaluation);
+             arg_pack = tsubst_decl (parm_pack, args, complain);
+             arg_pack = make_fnparm_pack (arg_pack);
+           }
+       }
       else
         {
           int level, idx, levels;
@@ -7559,6 +7603,17 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   if (len < 0)
     return error_mark_node;
 
+  if (!local_specializations)
+    {
+      /* We're in a late-specified return type, so we don't have a local
+        specializations table.  Create one for doing this expansion.  */
+      very_local_specializations = true;
+      local_specializations = htab_create (37,
+                                          hash_local_specialization,
+                                          eq_local_specializations,
+                                          NULL);
+    }
+
   /* For each argument in each argument pack, substitute into the
      pattern.  */
   result = make_tree_vec (len + incomplete);
@@ -7620,7 +7675,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
          break;
        }
     }
-  
+
   /* Update ARGS to restore the substitution from parameter packs to
      their argument packs.  */
   for (pack = packs; pack; pack = TREE_CHAIN (pack))
@@ -7643,6 +7698,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
         }
     }
 
+  if (very_local_specializations)
+    {
+      htab_delete (local_specializations);
+      local_specializations = NULL;
+    }
+  
   return result;
 }
 
@@ -15477,37 +15538,12 @@ instantiate_decl (tree d, int defer_ok,
        }
       if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
         {
-          /* Collect all of the extra "packed" parameters into an
-             argument pack.  */
-          tree parmvec;
-          tree parmtypevec;
-          tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
-          tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
-          int i, len = 0;
-          tree t;
-          
-          /* Count how many parameters remain.  */
-          for (t = spec_parm; t; t = TREE_CHAIN (t))
-            len++;
-
-          /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters.  */
-          parmvec = make_tree_vec (len);
-          parmtypevec = make_tree_vec (len);
-          for(i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
-            {
-              TREE_VEC_ELT (parmvec, i) = spec_parm;
-              TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
-            }
-
-          /* Build the argument packs.  */
-          SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
-          SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
-          TREE_TYPE (argpack) = argtypepack;
-          
           /* Register the (value) argument pack as a specialization of
              TMPL_PARM, then move on.  */
+         tree argpack = make_fnparm_pack (spec_parm);
           register_local_specialization (argpack, tmpl_parm);
           tmpl_parm = TREE_CHAIN (tmpl_parm);
+         spec_parm = NULL_TREE;
         }
       gcc_assert (!spec_parm);
 
index 16a2c54..40205fa 100644 (file)
@@ -1,5 +1,7 @@
 2009-03-23  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/auto12.C: Add variadic test.
+       
        PR c++/39526
        * g++.dg/warn/Wshadow-4.C: New test.
 
index 45ceedf..34dc8c9 100644 (file)
@@ -35,6 +35,15 @@ auto A<T>::f(U u) -> decltype (u + i)
   return u + i;
 }
 
+template <class... Args>
+int f (Args... args);
+
+template <class... Args>
+auto g (Args... args) -> decltype (f ((args+1)...))
+{
+  return (f ((args+1)...));
+}
+
 int main()
 {
   // { dg-final { scan-assembler  "_ZN1AIiE1fIiEEDTplfp_L_ZNS0_1iEEET_" } }
@@ -49,4 +58,6 @@ int main()
   A<int>().h(1);
   // { dg-final { scan-assembler  "_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_" } }
   A<int>().j(1);
+  // { dg-final { scan-assembler  "_Z1gIIidEEDTclL_Z1fEspplfp_Li1EEEDpT_" } }  
+  g(42, 1.0);
 }
index 00aa57a..a15a860 100644 (file)
@@ -1,3 +1,11 @@
+2009-03-23  Jason Merrill  <jason@redhat.com>
+
+       * cp-demangle.c (d_expression): Handle pack expansion.
+       (d_find_pack): Handle DEMANGLE_COMPONENT_FUNCTION_PARAM.
+       (d_print_subexpr): Don't wrap function parms in ().
+       (d_print_comp) [DEMANGLE_COMPONENT_PACK_EXPANSION]: Handle
+       not finding a pack.
+
 2009-03-17  Jason Merrill  <jason@redhat.com>
 
        * cp-demangle.c (d_make_function_param): new fn.
index e6d3d5e..b02f9bb 100644 (file)
@@ -2586,6 +2586,12 @@ d_expression (struct d_info *di)
                            d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
                                         d_template_args (di)));
     }
+  else if (peek == 's' && d_peek_next_char (di) == 'p')
+    {
+      d_advance (di, 2);
+      return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
+                         d_expression (di), NULL);
+    }
   else if (peek == 'f' && d_peek_next_char (di) == 'p')
     {
       /* Function parameter used in a late-specified return type.  */
@@ -3244,6 +3250,7 @@ d_find_pack (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
     case DEMANGLE_COMPONENT_SUB_STD:
     case DEMANGLE_COMPONENT_CHARACTER:
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
       return NULL;
 
     case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
@@ -3284,7 +3291,8 @@ d_print_subexpr (struct d_print_info *dpi,
                 const struct demangle_component *dc)
 {
   int simple = 0;
-  if (dc->type == DEMANGLE_COMPONENT_NAME)
+  if (dc->type == DEMANGLE_COMPONENT_NAME
+      || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
     simple = 1;
   if (!simple)
     d_append_char (dpi, '(');
@@ -4012,10 +4020,20 @@ d_print_comp (struct d_print_info *dpi,
 
     case DEMANGLE_COMPONENT_PACK_EXPANSION:
       {
-       struct demangle_component *a = d_find_pack (dpi, d_left (dc));
-       int len = d_pack_length (a);
+       int len;
        int i;
+       struct demangle_component *a = d_find_pack (dpi, d_left (dc));
+       if (a == NULL)
+         {
+           /* d_find_pack won't find anything if the only packs involved
+              in this expansion are function parameter packs; in that
+              case, just print the pattern and "...".  */
+           d_print_subexpr (dpi, d_left (dc));
+           d_append_string (dpi, "...");
+           return;
+         }
 
+       len = d_pack_length (a);
        dc = d_left (dc);
        for (i = 0; i < len; ++i)
          {
index cded6b5..0c45118 100644 (file)
@@ -3885,7 +3885,7 @@ java resource java/util/iso4217.properties
 # decltype/param placeholder test
 --format=gnu-v3
 _Z3addIidEDTplfp_fp0_ET_T0_
-decltype ((parm#1)+(parm#2)) add<int, double>(int, double)
+decltype (parm#1+parm#2) add<int, double>(int, double)
 # decltype/fn call test
 --format=gnu-v3
 _Z4add3IidEDTclL_Z1gEfp_fp0_EET_T0_
@@ -3901,8 +3901,12 @@ void f<int*, float*, double*>(int*, float*, double*)
 # '.' test
 --format=gnu-v3
 _Z1hI1AIiEdEDTcldtfp_1gIT0_EEET_S2_
-decltype (((parm#1).(g<double>))()) h<A<int>, double>(A<int>, double)
+decltype ((parm#1.(g<double>))()) h<A<int>, double>(A<int>, double)
 # test for typed function in decltype
 --format=gnu-v3
 _ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_
-decltype ((parm#1)+((x())())) A<int>::j<int>(int)
+decltype (parm#1+((x())())) A<int>::j<int>(int)
+# test for expansion of function parameter pack
+--format=gnu-v3
+_Z1gIIidEEDTclL_Z1fEspplfp_Li1EEEDpT_
+decltype (f((parm#1+(1))...)) g<int, double>(int, double)