This patch makes tsubst_requires_expr avoid substituting into a requires-expression when partially instantiating a generic lambda. This is necessary in general to ensure that we always check requirements in lexical order (as in the first testcase below). A mechanism similar to PACK_EXPANSION_EXTRA_ARGS is added to remember template arguments and defer substitution of requires-expressions. Incidentally, this change also fixes the two mentioned PRs -- the problem there is that tsubst_requires_expr was performing semantic checks on template trees, and some of the checks are not prepared to handle such trees. With this patch, tsubst_requires_expr no longer does any semantic checking at all when processing_template_decl. gcc/cp/ChangeLog: PR c++/96409 PR c++/96410 * constraint.cc (tsubst_requires_expr): Use REQUIRES_EXPR_PARMS and REQUIRES_EXPR_REQS. Use REQUIRES_EXPR_EXTRA_ARGS, add_extra_args and build_extra_args to defer substitution until we have all the template arguments. (finish_requires_expr): Adjust the call to build_min so that REQUIRES_EXPR_EXTRA_ARGS gets set to NULL_TREE. * cp-tree.def (REQUIRES_EXPR): Give it a third operand. * cp-tree.h (REQUIRES_EXPR_PARMS, REQUIRES_EXPR_REQS, REQUIRES_EXPR_EXTRA_ARGS): Define. (add_extra_args, build_extra_args): Declare. gcc/testsuite/ChangeLog: PR c++/96409 PR c++/96410 * g++.dg/cpp2a/concepts-lambda13.C: New test. * g++.dg/cpp2a/concepts-lambda14.C: New test.
19 lines
430 B
C
19 lines
430 B
C
// { dg-do compile { target c++20 } }
|
|
|
|
template<typename T>
|
|
struct S {
|
|
using type = T::type; // { dg-bogus "" }
|
|
};
|
|
|
|
template<typename T>
|
|
auto f() {
|
|
return [] <typename U> (U) {
|
|
// Verify that partial instantiation of this generic lambda doesn't cause
|
|
// these requirements to get checked out of order.
|
|
static_assert(!requires { typename U::type; typename S<T>::type; });
|
|
return 0;
|
|
};
|
|
}
|
|
|
|
int a = f<int>()(0);
|