In the below testcase, semantic analysis of the requires-expressions in the generic lambda must be delayed until instantiation of the lambda because the requirements depend on the lambda's template arguments. But tsubst_requires_expr does semantic analysis even during regeneration of the lambda, which leads to various bogus errors and ICEs since some subroutines aren't prepared to handle dependent/template trees.
This patch adjusts subroutines of tsubst_requires_expr to avoid doing some problematic semantic analyses when processing_template_decl. In particular, expr_noexcept_p generally can't be checked on a dependent expression. Next, tsubst_nested_requirement should avoid checking satisfaction when processing_template_decl. And similarly for convert_to_void (called from tsubst_valid_expression_requirement). Bootstrapped and regtested on x86_64-pc-linux-gnu, and also tested against the cmcstl2 project. Does this look OK to commit? gcc/cp/ChangeLog: PR c++/96409 PR c++/96410 * constraint.cc (tsubst_compound_requirement): When processing_template_decl, don't check noexcept of the substituted expression. (tsubst_nested_requirement): Just substitute into the constraint when processing_template_decl. * cvt.c (convert_to_void): Don't resolve concept checks when processing_template_decl. gcc/testsuite/ChangeLog: PR c++/96409 PR c++/96410 * g++.dg/cpp2a/concepts-lambda13.C: New test. --- gcc/cp/constraint.cc | 9 ++++++- gcc/cp/cvt.c | 2 +- .../g++.dg/cpp2a/concepts-lambda13.C | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-lambda13.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index e4aace596e7..db2036502a7 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1993,7 +1993,8 @@ tsubst_compound_requirement (tree t, tree args, subst_info info) /* Check the noexcept condition. */ bool noexcept_p = COMPOUND_REQ_NOEXCEPT_P (t); - if (noexcept_p && !expr_noexcept_p (expr, tf_none)) + if (!processing_template_decl + && noexcept_p && !expr_noexcept_p (expr, tf_none)) return error_mark_node; /* Substitute through the type expression, if any. */ @@ -2023,6 +2024,12 @@ static tree tsubst_nested_requirement (tree t, tree args, subst_info info) { /* Ensure that we're in an evaluation context prior to satisfaction. */ + if (processing_template_decl) + { + tree r = tsubst_constraint (TREE_OPERAND (t, 0), args, + info.complain, info.in_decl); + return finish_nested_requirement (EXPR_LOCATION (t), r); + } tree norm = TREE_TYPE (t); tree result = satisfy_constraint (norm, args, info); if (result == error_mark_node && info.quiet ()) diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index c9e7b1ff044..1d2c2d3351c 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1159,7 +1159,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) /* Explicitly evaluate void-converted concept checks since their satisfaction may produce ill-formed programs. */ - if (concept_check_p (expr)) + if (!processing_template_decl && concept_check_p (expr)) expr = evaluate_concept_check (expr, tf_warning_or_error); if (VOID_TYPE_P (TREE_TYPE (expr))) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda13.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda13.C new file mode 100644 index 00000000000..9757ce49d67 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda13.C @@ -0,0 +1,25 @@ +// PR c++/96410 +// { dg-do compile { target c++20 } } + +struct S { using blah = void; }; + +template <typename T> constexpr bool trait = !__is_same(T, S); +template <typename T> concept C = trait<T>; + +template<typename T> +void foo() noexcept(!__is_same(T, void)) { } + +template<typename U> +auto f() { + return []<typename T>(T){ + static_assert(requires { requires C<U> && (C<T> || C<T>); }); // { dg-error "assert" } + static_assert(requires { C<T>; }); + static_assert(requires { { foo<T>() } noexcept -> C; }); + static_assert(!requires { typename T::blah; }); // { dg-error "assert" } + return 0; + }; +} + +auto g = f<int>(); // { dg-bogus "" } +int n = g(0); // { dg-bogus "" } +int m = g(S{}); // { dg-message "required from here" } -- 2.28.0.97.gdc04167d37