mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 01:40:39 +08:00
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.
This commit is contained in:
parent
f4e05eebd6
commit
2a26351b59
@ -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)
|
||||
|
||||
|
@ -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. */
|
||||
|
19
gcc/cp/pt.c
19
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);
|
||||
|
27
gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C
Normal file
27
gcc/testsuite/g++.dg/cpp2a/lambda-pack-init6.C
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user