According to [temp.concept]/6 and [temp.pre]/9, a concept definition and
a requires clause are both unevaluated contexts, and hence satisfaction
deals only with unevaluated operands, so we should set cp_unevaluated in
these three situations.
gcc/cp/ChangeLog:
PR c++/99961
PR c++/99994
* constraint.cc (satisfy_normalized_constraints): Set
cp_unevaluated.
* parser.c (cp_parser_concept_definition): Likewise.
(cp_parser_requires_clause_opt): Likewise.
gcc/testsuite/ChangeLog:
PR c++/99961
PR c++/99994
* g++.dg/cpp2a/concepts-uneval1.C: New test.
* g++.dg/cpp2a/concepts-uneval2.C: New test.
/* We need to check access during satisfaction. */
deferring_access_check_sentinel acs (dk_no_deferred);
+ /* Constraints are unevaluated operands. */
+ cp_unevaluated u;
+
return satisfy_constraint_r (t, args, info);
}
static tree
cp_parser_concept_definition (cp_parser *parser)
{
+ /* A concept definition is an unevaluated context. */
+ cp_unevaluated u;
+
gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT));
cp_lexer_consume_token (parser->lexer);
static tree
cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p)
{
+ /* A requires clause is an unevaluated context. */
+ cp_unevaluated u;
+
cp_token *tok = cp_lexer_peek_token (parser->lexer);
if (tok->keyword != RID_REQUIRES)
{
--- /dev/null
+// PR c++/99961
+// { dg-do compile { target c++20 } }
+
+struct A { static const int x = 42; bool y; };
+
+void f(auto a) requires (a.x == 42) { }
+template void f(A);
+
+template <bool V> concept C = V || A::y;
+static_assert(C<true>);
--- /dev/null
+// PR c++/99994
+// { dg-do compile { target c++20 } }
+
+int main() {
+ auto f = [](int) { return true; };
+ int n = [&](auto i) requires (f(sizeof(i))) { return 99; }(12);
+ int m = [](auto i) requires (f(sizeof(i))) { return 99; }(12);
+}