c++: constrained auto in lambda using outer tparms [PR103706]
Here we're crashing during satisfaction of the lambda's placeholder type constraints because the constraints depend on the template arguments from the enclosing scope, which aren't part of the lambda's DECL_TI_ARGS. This patch fixes this by making do_auto_deduction consider the "regenerating" template arguments of a lambda for satisfaction, mirroring what's done in satisfy_declaration_constraints. PR c++/103706 gcc/cp/ChangeLog: * constraint.cc (satisfy_declaration_constraints): Use lambda_regenerating_args instead. * cp-tree.h (lambda_regenerating_args): Declare. * pt.cc (lambda_regenerating_args): Define, split out from satisfy_declaration_constraints. (do_auto_deduction): Use lambda_regenerating_args to obtain the full set of outer template arguments for satisfaction when inside a lambda. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-lambda18.C: New test.
This commit is contained in:
parent
61b783995f
commit
34ba3d9a2b
4 changed files with 51 additions and 10 deletions
|
@ -3154,12 +3154,11 @@ satisfy_declaration_constraints (tree t, sat_info info)
|
|||
set of template arguments. Augment this with the outer template
|
||||
arguments that were used to regenerate the lambda. */
|
||||
gcc_assert (!args || TMPL_ARGS_DEPTH (args) == 1);
|
||||
tree lambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t));
|
||||
tree outer_args = TI_ARGS (LAMBDA_EXPR_REGEN_INFO (lambda));
|
||||
tree regen_args = lambda_regenerating_args (t);
|
||||
if (args)
|
||||
args = add_to_template_args (outer_args, args);
|
||||
args = add_to_template_args (regen_args, args);
|
||||
else
|
||||
args = outer_args;
|
||||
args = regen_args;
|
||||
}
|
||||
|
||||
/* If any arguments depend on template parameters, we can't
|
||||
|
|
|
@ -7742,6 +7742,7 @@ extern void finish_lambda_scope (void);
|
|||
extern tree start_lambda_function (tree fn, tree lambda_expr);
|
||||
extern void finish_lambda_function (tree body);
|
||||
extern bool regenerated_lambda_fn_p (tree);
|
||||
extern tree lambda_regenerating_args (tree);
|
||||
extern tree most_general_lambda (tree);
|
||||
extern tree finish_omp_target (location_t, tree, tree, bool);
|
||||
extern void finish_omp_target_clauses (location_t, tree, tree *);
|
||||
|
|
39
gcc/cp/pt.cc
39
gcc/cp/pt.cc
|
@ -14446,6 +14446,21 @@ most_general_lambda (tree t)
|
|||
return t;
|
||||
}
|
||||
|
||||
/* Return the set of template arguments used to regenerate the lambda T
|
||||
from its most general lambda. */
|
||||
|
||||
tree
|
||||
lambda_regenerating_args (tree t)
|
||||
{
|
||||
if (LAMBDA_FUNCTION_P (t))
|
||||
t = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t));
|
||||
gcc_assert (TREE_CODE (t) == LAMBDA_EXPR);
|
||||
if (tree ti = LAMBDA_EXPR_REGEN_INFO (t))
|
||||
return TI_ARGS (ti);
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* We're instantiating a variable from template function TCTX. Return the
|
||||
corresponding current enclosing scope. We can match them up using
|
||||
DECL_SOURCE_LOCATION because lambdas only ever have one source location, and
|
||||
|
@ -30127,12 +30142,24 @@ do_auto_deduction (tree type, tree init, tree auto_node,
|
|||
return type;
|
||||
}
|
||||
|
||||
if ((context == adc_return_type
|
||||
|| context == adc_variable_type
|
||||
|| context == adc_decomp_type)
|
||||
&& current_function_decl
|
||||
&& DECL_TEMPLATE_INFO (current_function_decl))
|
||||
outer_targs = DECL_TI_ARGS (current_function_decl);
|
||||
if (context == adc_return_type
|
||||
|| context == adc_variable_type
|
||||
|| context == adc_decomp_type)
|
||||
if (tree fn = current_function_decl)
|
||||
if (DECL_TEMPLATE_INFO (fn) || LAMBDA_FUNCTION_P (fn))
|
||||
{
|
||||
outer_targs = DECL_TEMPLATE_INFO (fn)
|
||||
? DECL_TI_ARGS (fn) : NULL_TREE;
|
||||
if (LAMBDA_FUNCTION_P (fn))
|
||||
{
|
||||
/* As in satisfy_declaration_constraints. */
|
||||
tree regen_args = lambda_regenerating_args (fn);
|
||||
if (outer_targs)
|
||||
outer_targs = add_to_template_args (regen_args, outer_targs);
|
||||
else
|
||||
outer_targs = regen_args;
|
||||
}
|
||||
}
|
||||
|
||||
tree full_targs = add_to_template_args (outer_targs, targs);
|
||||
|
||||
|
|
14
gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C
Normal file
14
gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C
Normal file
|
@ -0,0 +1,14 @@
|
|||
// PR c++/103706
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template<class T, class U> concept C = __is_same(U, int);
|
||||
|
||||
template<class T> void f() {
|
||||
[]() -> C<T> auto {
|
||||
C<T> auto x = T(); // { dg-error "constraints" }
|
||||
return T(); // { dg-error "constraints" }
|
||||
}();
|
||||
}
|
||||
|
||||
template void f<int>(); // { dg-bogus "" }
|
||||
template void f<char>(); // { dg-message "required from here" }
|
Loading…
Add table
Reference in a new issue