]> gcc.gnu.org Git - gcc.git/commitdiff
c++: lambda pack init-capture within generic lambda
authorJason Merrill <jason@redhat.com>
Fri, 2 Apr 2021 15:05:46 +0000 (11:05 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 2 Apr 2021 16:46:54 +0000 (12:46 -0400)
We represent the type of a pack init-capture as auto... with packs from the
initializer stuck into PACK_EXPANSION_PARAMETER_PACKS so that expanding it
produces the right number of elements.  But when partially instantiating the
auto..., we were changing PACK_EXPANSION_PARAMETER_PACKS to refer to only
the auto itself.  Fixed thus.

gcc/cp/ChangeLog:

PR c++/97938
* cp-tree.h (PACK_EXPANSION_AUTO_P): New.
* lambda.c (add_capture): Set it.
* pt.c (tsubst_pack_expansion): Handle it.

gcc/testsuite/ChangeLog:

PR c++/97938
* g++.dg/cpp2a/lambda-pack-init6.C: New test.

gcc/cp/cp-tree.h
gcc/cp/lambda.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C [new file with mode: 0644]

index 66bba7b4d43e2c30acb9c5a971fe24cf89d3511c..a5d9d7ac62590f291a6bb21ead6f79f7559a3fb0 100644 (file)
@@ -481,6 +481,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       SWITCH_STMT_NO_BREAK_P (in SWITCH_STMT)
       LAMBDA_EXPR_CAPTURE_OPTIMIZED (in LAMBDA_EXPR)
       IMPLICIT_CONV_EXPR_BRACED_INIT (in IMPLICIT_CONV_EXPR)
+      PACK_EXPANSION_AUTO_P (in *_PACK_EXPANSION)
    3: IMPLICIT_RVALUE_P (in NON_LVALUE_EXPR or STATIC_CAST_EXPR)
       ICS_BAD_FLAG (in _CONV)
       FN_TRY_BLOCK_P (in TRY_BLOCK)
@@ -3855,6 +3856,9 @@ struct GTY(()) lang_decl {
 /* True iff this pack expansion is for sizeof....  */
 #define PACK_EXPANSION_SIZEOF_P(NODE) TREE_LANG_FLAG_1 (NODE)
 
+/* True iff this pack expansion is for auto... in lambda init-capture.  */
+#define PACK_EXPANSION_AUTO_P(NODE) TREE_LANG_FLAG_2 (NODE)
+
 /* True iff the wildcard can match a template parameter pack.  */
 #define WILDCARD_PACK_P(NODE) TREE_LANG_FLAG_0 (NODE)
 
index 421685cbc2d49f197abdc854371fd06b89f441d0..b0fd6ecc57ea17b169e73688438b5ba4daf3be81 100644 (file)
@@ -606,8 +606,11 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
           parameter pack in this context.  We will want as many fields as we
           have elements in the expansion of the initializer, so use its packs
           instead.  */
-       PACK_EXPANSION_PARAMETER_PACKS (type)
-         = uses_parameter_packs (initializer);
+       {
+         PACK_EXPANSION_PARAMETER_PACKS (type)
+           = uses_parameter_packs (initializer);
+         PACK_EXPANSION_AUTO_P (type) = true;
+       }
     }
 
   /* Make member variable.  */
index 7956e83c1de414d4e9054869438907f5784e67fb..524a16ab0c6602624b1f51abd067d36947ad7ed1 100644 (file)
@@ -13114,12 +13114,23 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
         pattern and return a PACK_EXPANSION_*. The caller will need to
         deal with that.  */
       if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
-       t = tsubst_expr (pattern, args, complain, in_decl,
+       result = tsubst_expr (pattern, args, complain, in_decl,
                         /*integral_constant_expression_p=*/false);
       else
-       t = tsubst (pattern, args, complain, in_decl);
-      t = make_pack_expansion (t, complain);
-      return t;
+       result = tsubst (pattern, args, complain, in_decl);
+      result = make_pack_expansion (result, complain);
+      if (PACK_EXPANSION_AUTO_P (t))
+       {
+         /* This is a fake auto... pack expansion created in add_capture with
+            _PACKS that don't appear in the pattern.  Copy one over.  */
+         packs = PACK_EXPANSION_PARAMETER_PACKS (t);
+         pack = retrieve_local_specialization (TREE_VALUE (packs));
+         gcc_checking_assert (DECL_PACK_P (pack));
+         PACK_EXPANSION_PARAMETER_PACKS (result)
+           = build_tree_list (NULL_TREE, pack);
+         PACK_EXPANSION_AUTO_P (result) = true;
+       }
+      return result;
     }
 
   gcc_assert (len >= 0);
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C b/gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C
new file mode 100644 (file)
index 0000000..3ee500e
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/97938
+// { dg-do compile { target c++20 } }
+
+template <typename... Args>
+int sink(Args&&... args) { return 2; }
+
+auto fwd1(const auto&&... ts1) {
+  return
+    [...ts1 = ts1] {
+      return sink(ts1...);
+    }();
+}
+
+template <typename T1>
+auto fwd2(const T1& t1) {
+  return
+    [] (auto&&... ts1) {
+      return
+       [...ts1 = ts1] {
+         return sink(ts1...);
+       }();
+    }();
+}
+
+int main() {
+  return fwd1() + fwd2(1);
+}
This page took 0.101607 seconds and 5 git commands to generate.