Re: [PATCH] c++: constraints are unevaluated operands [PR99961]

2021-04-12 Thread Jason Merrill via Gcc-patches

On 4/11/21 11:37 AM, Patrick Palka wrote:

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.

(I guess we should set cp_unevaluated during normalization too, but I
wasn't able to construct a testcase for which it makes a difference.)

Bootstrapped and regtested on x86_64-pc-linux-gnu, and also tested on
cmcstl2 and range-v3, does this look OK for trunk?

gcc/cp/ChangeLog:

PR c++/99961
* 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
* g++.dg/cpp2a/concepts-uneval1.C: New test.
---
  gcc/cp/constraint.cc  |  3 +++
  gcc/cp/parser.c   |  6 ++
  gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C | 10 ++
  3 files changed, 19 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 0ddb2990dd9..6c8e29d809f 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -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 an unevaluated operands.  */


OK fixing the grammar of this sentence.


+  cp_unevaluated u;
+
return satisfy_constraint_r (t, args, info);
  }
  
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c

index b6f94bdda23..8b7801b2be7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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
index 000..4c5f1b5c019
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C
@@ -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  concept C = V || A::y;
+static_assert(C);





[PATCH] c++: constraints are unevaluated operands [PR99961]

2021-04-11 Thread Patrick Palka via Gcc-patches
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.

(I guess we should set cp_unevaluated during normalization too, but I
wasn't able to construct a testcase for which it makes a difference.)

Bootstrapped and regtested on x86_64-pc-linux-gnu, and also tested on
cmcstl2 and range-v3, does this look OK for trunk?

gcc/cp/ChangeLog:

PR c++/99961
* 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
* g++.dg/cpp2a/concepts-uneval1.C: New test.
---
 gcc/cp/constraint.cc  |  3 +++
 gcc/cp/parser.c   |  6 ++
 gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C | 10 ++
 3 files changed, 19 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 0ddb2990dd9..6c8e29d809f 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -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 an unevaluated operands.  */
+  cp_unevaluated u;
+
   return satisfy_constraint_r (t, args, info);
 }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b6f94bdda23..8b7801b2be7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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
index 000..4c5f1b5c019
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C
@@ -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  concept C = V || A::y;
+static_assert(C);
-- 
2.31.1.272.g89b43f80a5