aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-04-02 11:05:46 -0400
committerJason Merrill <jason@redhat.com>2021-04-02 12:46:54 -0400
commit2a26351b598242c2fbce95d2a0baacce0084aec6 (patch)
tree5eee86e5ccc2ea0657eeec2543dce1913473296c
parentf4e05eebd6aac6118cbd9e0a04c011b6ed682826 (diff)
downloadgcc-2a26351b598242c2fbce95d2a0baacce0084aec6.zip
gcc-2a26351b598242c2fbce95d2a0baacce0084aec6.tar.gz
gcc-2a26351b598242c2fbce95d2a0baacce0084aec6.tar.bz2
c++: lambda pack init-capture within generic lambda
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.
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/lambda.c7
-rw-r--r--gcc/cp/pt.c19
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C27
4 files changed, 51 insertions, 6 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 66bba7b..a5d9d7ac 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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)
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 421685c..b0fd6ec 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -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. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7956e83..524a16a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 0000000..3ee500e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C
@@ -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);
+}