https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99874
--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Patrick Palka <ppa...@gcc.gnu.org>: https://gcc.gnu.org/g:123b3e03c911a43054c1f88f5d3110e1d084dd4e commit r11-8065-g123b3e03c911a43054c1f88f5d3110e1d084dd4e Author: Patrick Palka <ppa...@redhat.com> Date: Thu Apr 8 13:07:43 2021 -0400 c++: Don't substitute into constraints on lambdas [PR99874] We currently substitute through a lambda's constraints whenever we regenerate it via tsubst_lambda_expr. This is the wrong approach because it can lead to hard errors due to constraints being evaluated out of order (as in the testcase concepts-lambda17.C below), and because it doesn't mesh well with the recently added REQUIRES_EXPR_EXTRA_ARGS mechanism for delaying substitution into requires-expressions, which is the cause of this PR. But in order to avoid substituting through a lambda's constraints during regeneration, we need to be able to get at all in-scope template parameters and corresponding template arguments during constraint checking of a lambda's op(). And this information is not easily available when we need it, it seems. To that end, the approach that this patch takes is to add two new fields to LAMBDA_EXPR (and remove one): LAMBDA_EXPR_REGENERATED_FROM (replacing LAMBDA_EXPR_INSTANTIATED), and LAMBDA_EXPR_REGENERATING_TARGS. The former allows us to obtain the complete set of template parameters that are in-scope for a lambda's op(), and the latter gives us all outer template arguments that were used to regenerate the lambda (analogous to the TI_TEMPLATE and TI_ARGS of a TEMPLATE_INFO, respectively). LAMBDA_EXPR_REGENERATING_TARGS is not strictly necessary -- in an earlier prototype, I walked LAMBDA_EXPR_EXTRA_SCOPE to build up this set of outer template arguments on demand, but it seems cleaner to do it this way. (We'd need to walk LAMBDA_EXPR_EXTRA_SCOPE and not DECL/TYPE_CONTEXT because the latter skips over variable template scopes.) This patch also renames the predicate instantiated_lambda_fn_p to regenerated_lambda_fn_p, for sake of consistency with the rest of the patch which uses "regenerated" instead of "instantiated". gcc/cp/ChangeLog: PR c++/99874 * constraint.cc (get_normalized_constraints_from_decl): Handle regenerated lambdas. (satisfy_declaration_constraints): Likewise. Check for dependent args later. * cp-tree.h (LAMBDA_EXPR_INSTANTIATED): Replace with ... (LAMBDA_EXPR_REGENERATED_FROM): ... this. (LAMBDA_EXPR_REGENERATING_TARGS): New. (tree_lambda_expr::regenerated_from): New data member. (tree_lambda_expr::regenerating_targs): New data member. (add_to_template_args): Declare. (regenerated_lambda_fn_p): Likewise. (most_general_lambda): Likewise. * lambda.c (build_lambda_expr): Set LAMBDA_EXPR_REGENERATED_FROM and LAMBDA_EXPR_REGENERATING_TARGS. * pt.c (add_to_template_args): No longer static. (tsubst_function_decl): Unconditionally propagate constraints on the substituted function decl. (instantiated_lambda_fn_p): Rename to ... (regenerated_lambda_fn_p): ... this. Check LAMBDA_EXPR_REGENERATED_FROM instead of LAMBDA_EXPR_INSTANTIATED. (most_general_lambda): Define. (enclosing_instantiation_of): Adjust after renaming instantiated_lambda_fn_p. (tsubst_lambda_expr): Don't set LAMBDA_EXPR_INSTANTIATED. Set LAMBDA_EXPR_REGENERATED_FROM and LAMBDA_EXPR_REGENERATING_TARGS. Don't substitute or set constraints on the regenerated lambda. gcc/testsuite/ChangeLog: PR c++/99874 * g++.dg/cpp2a/concepts-lambda16.C: New test. * g++.dg/cpp2a/concepts-lambda17.C: New test.