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:
Patrick Palka 2022-02-08 08:46:13 -05:00
parent 61b783995f
commit 34ba3d9a2b
4 changed files with 51 additions and 10 deletions

View file

@ -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

View file

@ -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 *);

View file

@ -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);

View 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" }