]> gcc.gnu.org Git - gcc.git/commitdiff
c++: constraints are unevaluated operands [PR99961]
authorPatrick Palka <ppalka@redhat.com>
Tue, 13 Apr 2021 02:54:55 +0000 (22:54 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 13 Apr 2021 02:54:55 +0000 (22:54 -0400)
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.

gcc/cp/constraint.cc
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-uneval2.C [new file with mode: 0644]

index 0ddb2990dd95e846bc2f8e0eb5d86c55c2e721d2..0709695fd08fc295212afad788041b68ab85e402 100644 (file)
@@ -3066,6 +3066,9 @@ satisfy_normalized_constraints (tree t, tree args, sat_info info)
   /* 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);
 }
 
index b6f94bdda237be2a1e89772c9c2eabca9f10d286..8b7801b2be73215bfba59e8608507bbcff5748aa 100644 (file)
@@ -28353,6 +28353,9 @@ cp_parser_label_declaration (cp_parser* parser)
 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);
 
@@ -28714,6 +28717,9 @@ cp_parser_constraint_expression (cp_parser *parser)
 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)
     {
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C
new file mode 100644 (file)
index 0000000..4c5f1b5
--- /dev/null
@@ -0,0 +1,10 @@
+// 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>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-uneval2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval2.C
new file mode 100644 (file)
index 0000000..4793bd6
--- /dev/null
@@ -0,0 +1,8 @@
+// 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);
+}
This page took 0.096995 seconds and 5 git commands to generate.