Core DR 904 PR c++/41933
authorJason Merrill <jason@redhat.com>
Sun, 15 Sep 2013 19:34:42 +0000 (15:34 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 15 Sep 2013 19:34:42 +0000 (15:34 -0400)
Core DR 904
PR c++/41933
* parser.c (cp_parser_lambda_introducer): Handle variadic capture.
* lambda.c (add_capture): Handle variadic capture.
(add_default_capture, lambda_capture_field_type): Likewise.
(build_capture_proxy, register_capture_members): Likewise.
* pt.c (register_specialization): Allow FIELD_DECL.
(retrieve_specialization): Likewise.
(find_parameter_packs_r): Handle FIELD_DECL and VAR_DECL.
(tsubst_pack_expansion): Handle FIELD_DECL packs.
(gen_elem_of_pack_expansion_instantiation): Likewise.
(instantiate_class_template_1): Likewise.
(tsubst_decl, tsubst_copy): Likewise.
(tsubst_expr) [DECL_EXPR]: Handle capture proxy packs.
(tsubst_copy_and_build) [VAR_DECL]: Likewise.
* semantics.c (finish_non_static_data_member): Don't try to represent
the type of a COMPOUND_REF of a FIELD_DECL pack.

From-SVN: r202605

gcc/cp/ChangeLog
gcc/cp/lambda.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic2.C [new file with mode: 0644]

index 9234ade438a9b9f8ee33592e21ed3b2540fd1290..c3c2edeb414dddc79085f06dd407e538ab172b91 100644 (file)
@@ -1,5 +1,23 @@
 2013-09-15  Jason Merrill  <jason@redhat.com>
 
+       Core DR 904
+       PR c++/41933
+       * parser.c (cp_parser_lambda_introducer): Handle variadic capture.
+       * lambda.c (add_capture): Handle variadic capture.
+       (add_default_capture, lambda_capture_field_type): Likewise.
+       (build_capture_proxy, register_capture_members): Likewise.
+       * pt.c (register_specialization): Allow FIELD_DECL.
+       (retrieve_specialization): Likewise.
+       (find_parameter_packs_r): Handle FIELD_DECL and VAR_DECL.
+       (tsubst_pack_expansion): Handle FIELD_DECL packs.
+       (gen_elem_of_pack_expansion_instantiation): Likewise.
+       (instantiate_class_template_1): Likewise.
+       (tsubst_decl, tsubst_copy): Likewise.
+       (tsubst_expr) [DECL_EXPR]: Handle capture proxy packs.
+       (tsubst_copy_and_build) [VAR_DECL]: Likewise.
+       * semantics.c (finish_non_static_data_member): Don't try to represent
+       the type of a COMPOUND_REF of a FIELD_DECL pack.
+
        PR c++/41933
        * cp-tree.h (DECL_PACK_P): Replace FUNCTION_PARAMETER_PACK_P.
        * cxx-pretty-print.c (direct_declarator): Adjust.
index bf758348816c235c5637226e4a2b617fcf98ca92..1af301d47afae6be2bb39aa21260f2f9a74d20dc 100644 (file)
@@ -215,7 +215,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p)
     }
   else
     type = non_reference (unlowered_expr_type (expr));
-  if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type))
+  if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type)
+      || DECL_PACK_P (expr))
     {
       type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
@@ -320,15 +321,21 @@ tree
 lambda_proxy_type (tree ref)
 {
   tree type;
+  if (ref == error_mark_node)
+    return error_mark_node;
   if (REFERENCE_REF_P (ref))
     ref = TREE_OPERAND (ref, 0);
+  gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
   type = TREE_TYPE (ref);
-  if (type && !WILDCARD_TYPE_P (non_reference (type)))
-    return type;
-  type = cxx_make_type (DECLTYPE_TYPE);
-  DECLTYPE_TYPE_EXPR (type) = ref;
-  DECLTYPE_FOR_LAMBDA_PROXY (type) = true;
-  SET_TYPE_STRUCTURAL_EQUALITY (type);
+  if (!type || WILDCARD_TYPE_P (non_reference (type)))
+    {
+      type = cxx_make_type (DECLTYPE_TYPE);
+      DECLTYPE_TYPE_EXPR (type) = ref;
+      DECLTYPE_FOR_LAMBDA_PROXY (type) = true;
+      SET_TYPE_STRUCTURAL_EQUALITY (type);
+    }
+  if (DECL_PACK_P (TREE_OPERAND (ref, 1)))
+    type = make_pack_expansion (type);
   return type;
 }
 
@@ -341,6 +348,9 @@ build_capture_proxy (tree member)
 {
   tree var, object, fn, closure, name, lam, type;
 
+  if (PACK_EXPANSION_P (member))
+    member = PACK_EXPANSION_PATTERN (member);
+
   closure = DECL_CONTEXT (member);
   fn = lambda_function (closure);
   lam = CLASSTYPE_LAMBDA_EXPR (closure);
@@ -422,12 +432,20 @@ vla_capture_type (tree array_type)
    and return it.  */
 
 tree
-add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
+add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
             bool explicit_init_p)
 {
   char *buf;
   tree type, member, name;
   bool vla = false;
+  bool variadic = false;
+  tree initializer = orig_init;
+
+  if (PACK_EXPANSION_P (initializer))
+    {
+      initializer = PACK_EXPANSION_PATTERN (initializer);
+      variadic = true;
+    }
 
   if (TREE_CODE (initializer) == TREE_LIST)
     initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
@@ -498,6 +516,9 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
       IDENTIFIER_MARKED (name) = true;
     }
 
+  if (variadic)
+    type = make_pack_expansion (type);
+
   /* Make member variable.  */
   member = build_decl (input_location, FIELD_DECL, name, type);
   DECL_VLA_CAPTURE_P (member) = vla;
@@ -518,8 +539,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
       && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
     finish_member_declaration (member);
 
+  tree listmem = member;
+  if (variadic)
+    {
+      listmem = make_pack_expansion (member);
+      initializer = orig_init;
+    }
   LAMBDA_EXPR_CAPTURE_LIST (lambda)
-    = tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
+    = tree_cons (listmem, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
 
   if (LAMBDA_EXPR_CLOSURE (lambda))
     return build_capture_proxy (member);
@@ -538,9 +565,14 @@ register_capture_members (tree captures)
     return;
 
   register_capture_members (TREE_CHAIN (captures));
+
+  tree field = TREE_PURPOSE (captures);
+  if (PACK_EXPANSION_P (field))
+    field = PACK_EXPANSION_PATTERN (field);
+
   /* We set this in add_capture to avoid duplicates.  */
-  IDENTIFIER_MARKED (DECL_NAME (TREE_PURPOSE (captures))) = false;
-  finish_member_declaration (TREE_PURPOSE (captures));
+  IDENTIFIER_MARKED (DECL_NAME (field)) = false;
+  finish_member_declaration (field);
 }
 
 /* Similar to add_capture, except this works on a stack of nested lambdas.
@@ -565,6 +597,8 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
       tree lambda = TREE_VALUE (node);
 
       current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
+      if (DECL_PACK_P (initializer))
+       initializer = make_pack_expansion (initializer);
       var = add_capture (lambda,
                             id,
                             initializer,
index e00e56c6e012a7cf0f9f8e6206f65ab47e56d0ad..2b0695ae1e5c179a5ed1a6fac78c32ad2d974037 100644 (file)
@@ -8753,6 +8753,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
                  /*template_arg_p=*/false,
                  &error_msg,
                  capture_token->location);
+
+         if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+           {
+             cp_lexer_consume_token (parser->lexer);
+             capture_init_expr = make_pack_expansion (capture_init_expr);
+           }
+         else
+           check_for_bare_parameter_packs (capture_init_expr);
        }
 
       if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
index ecae904312f6694c3ae2775049c75453c370e0da..2ef160aacf892149c48281d712e2328176d6187a 100644 (file)
@@ -1004,7 +1004,10 @@ optimize_specialization_lookup_p (tree tmpl)
 
    If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true,
    then we search for a partial specialization matching ARGS.  This
-   parameter is ignored if TMPL is not a class template.  */
+   parameter is ignored if TMPL is not a class template.
+
+   We can also look up a FIELD_DECL, if it is a lambda capture pack; the
+   result is a NONTYPE_ARGUMENT_PACK.  */
 
 static tree
 retrieve_specialization (tree tmpl, tree args, hashval_t hash)
@@ -1015,12 +1018,15 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)
   if (args == error_mark_node)
     return NULL_TREE;
 
-  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
+  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL
+             || TREE_CODE (tmpl) == FIELD_DECL);
 
   /* There should be as many levels of arguments as there are
      levels of parameters.  */
   gcc_assert (TMPL_ARGS_DEPTH (args)
-             == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
+             == (TREE_CODE (tmpl) == TEMPLATE_DECL
+                 ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
+                 : template_class_depth (DECL_CONTEXT (tmpl))));
 
   if (optimize_specialization_lookup_p (tmpl))
     {
@@ -1311,7 +1317,10 @@ is_specialization_of_friend (tree decl, tree friend_decl)
 /* Register the specialization SPEC as a specialization of TMPL with
    the indicated ARGS.  IS_FRIEND indicates whether the specialization
    is actually just a friend declaration.  Returns SPEC, or an
-   equivalent prior declaration, if available.  */
+   equivalent prior declaration, if available.
+
+   We also store instantiations of field packs in the hash table, even
+   though they are not themselves templates, to make lookup easier.  */
 
 static tree
 register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
@@ -1321,7 +1330,9 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
   void **slot = NULL;
   spec_entry elt;
 
-  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec));
+  gcc_assert ((TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec))
+             || (TREE_CODE (tmpl) == FIELD_DECL
+                 && TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK));
 
   if (TREE_CODE (spec) == FUNCTION_DECL
       && uses_template_parms (DECL_TI_ARGS (spec)))
@@ -1443,7 +1454,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
 
   /* A specialization must be declared in the same namespace as the
      template it is specializing.  */
-  if (DECL_TEMPLATE_SPECIALIZATION (spec)
+  if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec)
       && !check_specialization_namespace (tmpl))
     DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
 
@@ -3084,6 +3095,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
         parameter_pack_p = true;
       break;
 
+    case FIELD_DECL:
     case PARM_DECL:
       if (DECL_PACK_P (t))
         {
@@ -3094,6 +3106,18 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
         }
       break;
 
+      /* Look through a lambda capture proxy to the field pack.  */
+    case VAR_DECL:
+      if (DECL_HAS_VALUE_EXPR_P (t))
+       {
+         tree v = DECL_VALUE_EXPR (t);
+         cp_walk_tree (&v,
+                       &find_parameter_packs_r,
+                       ppd, ppd->visited);
+         *walk_subtrees = 0;
+       }
+      break;
+
     case BASES:
       parameter_pack_p = true;
       break;
@@ -8913,6 +8937,8 @@ instantiate_class_template_1 (tree type)
              else if (TREE_CODE (t) != CONST_DECL)
                {
                  tree r;
+                 tree vec = NULL_TREE;
+                 int len = 1;
 
                  /* The file and line for this declaration, to
                     assist in error message reporting.  Since we
@@ -8925,55 +8951,68 @@ instantiate_class_template_1 (tree type)
                  r = tsubst (t, args, tf_warning_or_error, NULL_TREE);
                  if (TREE_CODE (t) == TEMPLATE_DECL)
                    --processing_template_decl;
-                 if (VAR_P (r))
+
+                 if (TREE_CODE (r) == TREE_VEC)
                    {
-                     /* In [temp.inst]:
-
-                          [t]he initialization (and any associated
-                          side-effects) of a static data member does
-                          not occur unless the static data member is
-                          itself used in a way that requires the
-                          definition of the static data member to
-                          exist.
-
-                        Therefore, we do not substitute into the
-                        initialized for the static data member here.  */
-                     finish_static_data_member_decl
-                       (r,
-                        /*init=*/NULL_TREE,
-                        /*init_const_expr_p=*/false,
-                        /*asmspec_tree=*/NULL_TREE,
-                        /*flags=*/0);
-                     /* Instantiate members marked with attribute used.  */
-                     if (r != error_mark_node && DECL_PRESERVE_P (r))
-                       mark_used (r);
+                     /* A capture pack became multiple fields.  */
+                     vec = r;
+                     len = TREE_VEC_LENGTH (vec);
                    }
-                 else if (TREE_CODE (r) == FIELD_DECL)
+
+                 for (int i = 0; i < len; ++i)
                    {
-                     /* Determine whether R has a valid type and can be
-                        completed later.  If R is invalid, then its type is
-                        replaced by error_mark_node.  */
-                     tree rtype = TREE_TYPE (r);
-                     if (can_complete_type_without_circularity (rtype))
-                       complete_type (rtype);
-
-                     if (!COMPLETE_TYPE_P (rtype))
+                     if (vec)
+                       r = TREE_VEC_ELT (vec, i);
+                     if (VAR_P (r))
                        {
-                         cxx_incomplete_type_error (r, rtype);
-                         TREE_TYPE (r) = error_mark_node;
+                         /* In [temp.inst]:
+
+                            [t]he initialization (and any associated
+                            side-effects) of a static data member does
+                            not occur unless the static data member is
+                            itself used in a way that requires the
+                            definition of the static data member to
+                            exist.
+
+                            Therefore, we do not substitute into the
+                            initialized for the static data member here.  */
+                         finish_static_data_member_decl
+                           (r,
+                            /*init=*/NULL_TREE,
+                            /*init_const_expr_p=*/false,
+                            /*asmspec_tree=*/NULL_TREE,
+                            /*flags=*/0);
+                         /* Instantiate members marked with attribute used. */
+                         if (r != error_mark_node && DECL_PRESERVE_P (r))
+                           mark_used (r);
+                       }
+                     else if (TREE_CODE (r) == FIELD_DECL)
+                       {
+                         /* Determine whether R has a valid type and can be
+                            completed later.  If R is invalid, then its type
+                            is replaced by error_mark_node.  */
+                         tree rtype = TREE_TYPE (r);
+                         if (can_complete_type_without_circularity (rtype))
+                           complete_type (rtype);
+
+                         if (!COMPLETE_TYPE_P (rtype))
+                           {
+                             cxx_incomplete_type_error (r, rtype);
+                             TREE_TYPE (r) = error_mark_node;
+                           }
                        }
-                   }
 
-                 /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
-                    such a thing will already have been added to the field
-                    list by tsubst_enum in finish_member_declaration in the
-                    CLASSTYPE_NESTED_UTDS case above.  */
-                 if (!(TREE_CODE (r) == TYPE_DECL
-                       && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
-                       && DECL_ARTIFICIAL (r)))
-                   {
-                     set_current_access_from_decl (r);
-                     finish_member_declaration (r);
+                     /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
+                        such a thing will already have been added to the field
+                        list by tsubst_enum in finish_member_declaration in the
+                        CLASSTYPE_NESTED_UTDS case above.  */
+                     if (!(TREE_CODE (r) == TYPE_DECL
+                           && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
+                           && DECL_ARTIFICIAL (r)))
+                       {
+                         set_current_access_from_decl (r);
+                         finish_member_declaration (r);
+                       }
                    }
                }
            }
@@ -9367,7 +9406,8 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
        argument_pack_element_is_expansion_p (arg_pack, index);
 
       /* Select the Ith argument from the pack.  */
-      if (TREE_CODE (parm) == PARM_DECL)
+      if (TREE_CODE (parm) == PARM_DECL
+         || TREE_CODE (parm) == FIELD_DECL)
        {
          if (index == 0)
            {
@@ -9481,6 +9521,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
              need_local_specializations = true;
            }
        }
+      else if (TREE_CODE (parm_pack) == FIELD_DECL)
+       arg_pack = tsubst_copy (parm_pack, args, complain, in_decl);
       else
         {
          int idx;
@@ -9605,7 +9647,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
     {
       tree parm = TREE_PURPOSE (pack);
 
-      if (TREE_CODE (parm) == PARM_DECL)
+      if (TREE_CODE (parm) == PARM_DECL
+         || TREE_CODE (parm) == FIELD_DECL)
         register_local_specialization (TREE_TYPE (pack), parm);
       else
         {
@@ -10572,39 +10615,88 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 
     case FIELD_DECL:
       {
-       tree type;
+       tree type = NULL_TREE;
+       tree vec = NULL_TREE;
+       tree expanded_types = NULL_TREE;
+       int len = 1;
 
-       r = copy_decl (t);
-       type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-       if (type == error_mark_node)
-         RETURN (error_mark_node);
-       TREE_TYPE (r) = type;
-       cp_apply_type_quals_to_decl (cp_type_quals (type), r);
+       if (PACK_EXPANSION_P (TREE_TYPE (t)))
+         {
+           /* This field is a lambda capture pack.  Return a TREE_VEC of
+              the expanded fields to instantiate_class_template_1 and
+              store them in the specializations hash table as a
+              NONTYPE_ARGUMENT_PACK so that tsubst_copy can find them.  */
+            expanded_types = tsubst_pack_expansion (TREE_TYPE (t), args,
+                                                   complain, in_decl);
+            if (TREE_CODE (expanded_types) == TREE_VEC)
+              {
+                len = TREE_VEC_LENGTH (expanded_types);
+               vec = make_tree_vec (len);
+              }
+            else
+              {
+                /* All we did was update the type. Make a note of that.  */
+                type = expanded_types;
+                expanded_types = NULL_TREE;
+              }
+         }
 
-       if (DECL_C_BIT_FIELD (r))
-         /* For bit-fields, DECL_INITIAL gives the number of bits.  For
-            non-bit-fields DECL_INITIAL is a non-static data member
-            initializer, which gets deferred instantiation.  */
-         DECL_INITIAL (r)
-           = tsubst_expr (DECL_INITIAL (t), args,
-                          complain, in_decl,
-                          /*integral_constant_expression_p=*/true);
-       else if (DECL_INITIAL (t))
+       for (int i = 0; i < len; ++i)
          {
-           /* Set up DECL_TEMPLATE_INFO so that we can get at the
-              NSDMI in perform_member_init.  Still set DECL_INITIAL
-              so that we know there is one.  */
-           DECL_INITIAL (r) = void_zero_node;
-           gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
-           retrofit_lang_decl (r);
-           DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
+           r = copy_decl (t);
+           if (expanded_types)
+             {
+               type = TREE_VEC_ELT (expanded_types, i);
+               DECL_NAME (r)
+                 = make_ith_pack_parameter_name (DECL_NAME (r), i);
+             }
+            else if (!type)
+              type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
+           if (type == error_mark_node)
+             RETURN (error_mark_node);
+           TREE_TYPE (r) = type;
+           cp_apply_type_quals_to_decl (cp_type_quals (type), r);
+
+           if (DECL_C_BIT_FIELD (r))
+             /* For bit-fields, DECL_INITIAL gives the number of bits.  For
+                non-bit-fields DECL_INITIAL is a non-static data member
+                initializer, which gets deferred instantiation.  */
+             DECL_INITIAL (r)
+               = tsubst_expr (DECL_INITIAL (t), args,
+                              complain, in_decl,
+                              /*integral_constant_expression_p=*/true);
+           else if (DECL_INITIAL (t))
+             {
+               /* Set up DECL_TEMPLATE_INFO so that we can get at the
+                  NSDMI in perform_member_init.  Still set DECL_INITIAL
+                  so that we know there is one.  */
+               DECL_INITIAL (r) = void_zero_node;
+               gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
+               retrofit_lang_decl (r);
+               DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
+             }
+           /* We don't have to set DECL_CONTEXT here; it is set by
+              finish_member_declaration.  */
+           DECL_CHAIN (r) = NULL_TREE;
+
+           apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+                                           args, complain, in_decl);
+
+           if (vec)
+             TREE_VEC_ELT (vec, i) = r;
          }
-       /* We don't have to set DECL_CONTEXT here; it is set by
-          finish_member_declaration.  */
-       DECL_CHAIN (r) = NULL_TREE;
 
-       apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
-                                       args, complain, in_decl);
+       if (vec)
+         {
+           r = vec;
+           tree pack = make_node (NONTYPE_ARGUMENT_PACK);
+           tree tpack = cxx_make_type (TYPE_ARGUMENT_PACK);
+           SET_ARGUMENT_PACK_ARGS (pack, vec);
+           SET_ARGUMENT_PACK_ARGS (tpack, expanded_types);
+           TREE_TYPE (pack) = tpack;
+           register_specialization (pack, t, args, false, 0);
+         }
       }
       break;
 
@@ -10753,14 +10845,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              {
                /* It may seem that this case cannot occur, since:
 
-                    typedef void f();
-                    void g() { f x; }
+                  typedef void f();
+                  void g() { f x; }
 
                   declares a function, not a variable.  However:
       
-                    typedef void f();
-                    template <typename T> void g() { T t; }
-                    template void g<f>();
+                  typedef void f();
+                  template <typename T> void g() { T t; }
+                  template void g<f>();
 
                   is an attempt to declare a variable with function
                   type.  */
@@ -12261,6 +12353,23 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       return t;
 
     case FIELD_DECL:
+      if (PACK_EXPANSION_P (TREE_TYPE (t)))
+       {
+         /* Check for a local specialization set up by
+            tsubst_pack_expansion.  */
+         tree r = retrieve_local_specialization (t);
+         if (r)
+           {
+             if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
+               r = ARGUMENT_PACK_SELECT_ARG (r);
+             return r;
+           }
+
+         /* Otherwise return the full NONTYPE_ARGUMENT_PACK that
+            tsubst_decl put in the hash table.  */
+         return retrieve_specialization (t, args, 0);
+       }
+
       if (DECL_CONTEXT (t))
        {
          tree ctx;
@@ -13020,6 +13129,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
            else
              do_local_using_decl (decl, scope, name);
          }
+       else if (DECL_PACK_P (decl))
+         {
+           /* Don't build up decls for a variadic capture proxy, we'll
+              instantiate the elements directly as needed.  */
+           break;
+         }
        else
          {
            init = DECL_INITIAL (decl);
@@ -14585,6 +14700,14 @@ tsubst_copy_and_build (tree t,
     case VAR_DECL:
       if (!args)
        RETURN (t);
+      else if (DECL_PACK_P (t))
+       {
+         /* We don't build decls for an instantiation of a
+            variadic capture proxy, we instantiate the elements
+            when needed.  */
+         gcc_assert (DECL_HAS_VALUE_EXPR_P (t));
+         return RECUR (DECL_VALUE_EXPR (t));
+       }
       /* Fall through */
 
     case PARM_DECL:
index 6d7f55f73198b9db40a28166aefe0be37f0fbbf2..0299b690fb19774cd721146c5bef7be38ebe0abf 100644 (file)
@@ -1604,6 +1604,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
       if (TREE_CODE (type) == REFERENCE_TYPE)
        /* Quals on the object don't matter.  */;
+      else if (PACK_EXPANSION_P (type))
+       /* Don't bother trying to represent this.  */
+       type = NULL_TREE;
       else
        {
          /* Set the cv qualifiers.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic2.C
new file mode 100644 (file)
index 0000000..fab1f6c
--- /dev/null
@@ -0,0 +1,57 @@
+// { dg-do run { target c++11 } }
+
+int g() { return 0; }
+template <class T, class... U>
+int g(T t, U... u)
+{
+  return t + g(u...);
+}
+
+template <class... T>
+int f1(T... t)
+{
+  return [t...] {
+    return g(t...);
+  }();
+}
+
+template <class... T>
+int f2(T... t)
+{
+  return [&t...] {
+    return g(t...);
+  }();
+}
+
+template <class... T>
+int f3(T... t)
+{
+  return [=] {
+    return g(t...);
+  }();
+}
+
+template <class... T>
+int f4(T... t)
+{
+  return [&] {
+    return g(t...);
+  }();
+}
+
+#define assert(E) do { if (!(E)) __builtin_abort(); } while(0)
+int main()
+{
+  assert (f1() == 0);
+  assert (f2() == 0);
+  assert (f3() == 0);
+  assert (f4() == 0);
+  assert (f1(42) == 42);
+  assert (f2(42) == 42);
+  assert (f3(42) == 42);
+  assert (f4(42) == 42);
+  assert (f1(1,2,3) == 6);
+  assert (f2(1,2,3) == 6);
+  assert (f3(1,2,3) == 6);
+  assert (f4(1,2,3) == 6);
+}