aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-04-12 22:54:55 -0400
committerPatrick Palka <ppalka@redhat.com>2021-04-12 22:54:55 -0400
commit59d9aa6d2efe7c52b6a986eb3e1977c1fb3c5753 (patch)
tree1d4c31e21078391baa8efb51ede1013c6034918c /gcc
parent07b27384de56ce2f6a93007d018743ef9d5c8cc4 (diff)
downloadgcc-59d9aa6d2efe7c52b6a986eb3e1977c1fb3c5753.zip
gcc-59d9aa6d2efe7c52b6a986eb3e1977c1fb3c5753.tar.gz
gcc-59d9aa6d2efe7c52b6a986eb3e1977c1fb3c5753.tar.bz2
c++: constraints are unevaluated operands [PR99961]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constraint.cc3
-rw-r--r--gcc/cp/parser.c6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-uneval1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-uneval2.C8
4 files changed, 27 insertions, 0 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 0ddb299..0709695 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 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 b6f94bd..8b7801b 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 0000000..4c5f1b5
--- /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 <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
index 0000000..4793bd6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval2.C
@@ -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);
+}