On 8/16/25 2:02 PM, Ben Wu wrote:
This testcase caused an ICE when mangling the invalid type-constraint in
write_requirement since write_type_constraint expects a TEMPLATE_TYPE_PARM.
Setting the trailing return type to NULL_TREE when a
return-type-requirement is found in place of a type-constraint prevents the
failed assertion in write_requirement. It also allows the invalid
constraint to be satisfied in some contexts to prevent redundant errors,
e.g. in concepts-requires5.C.
Bootstrapped and tested on x86_64-linux-gnu. For some reason, compare_tests
indicates that 19 libitm tests have disappeared and 19 new libitm tests,
though the tests are identical and behave the same.
compare_tests also indicates that gcc.dg/macro-fusion-1.c and
gcc.dg/macro-fusion-2.c now pass, though I do not know why this would be
the case.
Could someone help review and commit?
Thanks.
PR c++/120618
gcc/cp/ChangeLog:
* parser.cc (cp_parser_compound_requirement): Set type to
NULL_TREE for invalid type-constraint.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-requires5.C: Avoid redundant error
in static assertion.
* g++.dg/concepts/pr120618.C: New test.
Suggested-by: Jason Merrill <ja...@redhat.com>
---
gcc/cp/parser.cc | 9 ++++++---
gcc/testsuite/g++.dg/concepts/pr120618.C | 13 +++++++++++++
gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C | 2 +-
3 files changed, 20 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/concepts/pr120618.C
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d66b658b748..40223bedcc1 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -33403,9 +33403,12 @@ cp_parser_compound_requirement (cp_parser *parser)
}
}
else
- /* P1452R2 removed the trailing-return-type option. */
- error_at (type_loc,
- "return-type-requirement is not a type-constraint");
+ {
+ /* P1452R2 removed the trailing-return-type option. */
+ error_at (type_loc,
+ "return-type-requirement is not a type-constraint");
+ type = NULL_TREE;
+ }
Wrong indentation.
}
location_t loc = make_location (expr_token->location,
diff --git a/gcc/testsuite/g++.dg/concepts/pr120618.C
b/gcc/testsuite/g++.dg/concepts/pr120618.C
Broken word wrap.
new file mode 100644
index 00000000000..cff79b4ba49
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr120618.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+class B{};
+
+template <typename T>
+requires (!requires(T t) { { t } -> bool; }) // { dg-error
"return-type-requirement is not a type-constraint" }
Broken word wrap.
+void foo(T t) {}
+
+int main() {
+ B b;
+ foo(b); // { dg-error "no matching function" }
For a diagnostic like this that we want to allow but not require I
prefer to use dg-prune-output rather than dg-error, so the test will
pass with or without it.
Or just add an "error-recovery" comment.
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
Broken word wrap.
index 524eadbf5dd..1c68cca52ac 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
@@ -41,5 +41,5 @@ class D : /*private*/ B { };
void driver_2()
{
static_assert(ConvertibleTo<D, B>()); // { dg-error "cannot call" }
- static_assert(ConvertibleTo<D, B>); // { dg-error "static assertion failed" }
+ static_assert(ConvertibleTo<D, B>);
Similarly here: we would get the static_assert failure if we turned the
plain U& into std::convertible_to<U&>, so it makes sense to allow it.
Jason