c++: lambda in concept [PR105652]

We currently check satisfaction in the context of the constrained
declaration (which may be wrong, see PR104111).  When checking C<int>
for S<int>, we currently substitute into the lambda in the context of
S<T> (rather than S<int>, which seems wrong if the above isn't wrong), so
the new closure type thinks its context is S<T>, which confuses debug
output.  For the moment, let's work around all of this by overriding the
context of the closure.

	PR c++/105652

gcc/cp/ChangeLog:

	* pt.cc (tsubst_lambda_expr): Don't let a namespace-scope lambda
	instantiate into a class-scope lambda.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/concepts-lambda20.C: New test.
This commit is contained in:
Jason Merrill 2022-05-26 22:43:05 -04:00
parent d81be519fd
commit 102a1472ab
2 changed files with 29 additions and 5 deletions

View File

@ -19724,11 +19724,18 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
/* A lambda in a default argument outside a class gets no
LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
tsubst_default_argument calls start_lambda_scope, so we need to
specifically ignore it here, and use the global scope. */
record_null_lambda_scope (r);
{
/* A lambda in a default argument outside a class gets no
LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
tsubst_default_argument calls start_lambda_scope, so we need to
specifically ignore it here, and use the global scope. */
record_null_lambda_scope (r);
/* If we're pushed into another scope (PR105652), fix it. */
if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t)))
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type))
= TYPE_CONTEXT (TREE_TYPE (t));
}
else
record_lambda_scope (r);

View File

@ -0,0 +1,17 @@
// PR c++/105652
// { dg-do compile { target c++20 } }
// { dg-additional-options -g }
template<int>
struct I {};
template<class T>
concept C = []<int N>(I<N>) { return true; } (I<0>{});
template<class T>
struct S { };
template<C T>
struct S<T> { constexpr static bool value = true; };
static_assert(S<int>::value);