Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
Just an ICE-on-invalid, but while writing tests for 123237 my
typos would result in this crash often enough to prompt me to
go ahead and fix it.
We crash here because we are asserting that we've emitted hard
errors when cp_parser_splice_specifier returns error_mark_node
even when parsing tentatively. In the crash20.C case we have
[:R<T>:] where we interpret the < as a "less than" operator and
expect that T will produce a primary expression, which it does
not. But cp_parser_error won't emit any errors yet.
PR c++/124496
gcc/cp/ChangeLog:
* parser.cc (cp_parser_splice_specifier): Use NULL_TREE instead of
NULL.
(cp_parser_splice_expression): Don't assert seen_error() when not
committed to tentative parse.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/crash20.C: New test.
* g++.dg/reflect/crash21.C: New test.
---
gcc/cp/parser.cc | 5 +++--
gcc/testsuite/g++.dg/reflect/crash20.C | 18 ++++++++++++++++++
gcc/testsuite/g++.dg/reflect/crash21.C | 20 ++++++++++++++++++++
3 files changed, 41 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/reflect/crash20.C
create mode 100644 gcc/testsuite/g++.dg/reflect/crash21.C
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index ffb22aa776f..7c36c564c57 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6158,7 +6158,7 @@ cp_parser_splice_specifier (cp_parser *parser, bool
template_p = false,
int q = A ().[: ^^x :];
should be an error -- x is not a member-qualified name and isn't
in scope. */
- parser->context->object_type = NULL;
+ parser->context->object_type = NULL_TREE;
tree expr = cp_parser_constant_expression (parser,
/*allow_non_constant_p=*/false,
/*non_constant_p=*/nullptr,
@@ -6318,7 +6318,8 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
if (error_operand_p (t))
{
- gcc_assert (seen_error ());
+ if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+ gcc_assert (seen_error ());
return error_mark_node;
}
diff --git a/gcc/testsuite/g++.dg/reflect/crash20.C
b/gcc/testsuite/g++.dg/reflect/crash20.C
new file mode 100644
index 00000000000..322aac6fa2a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/crash20.C
@@ -0,0 +1,18 @@
+// PR c++/124496
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template<unsigned>
+struct A {};
+
+template<int N>
+static constexpr int var = N;
+
+template<decltype(^^void) R, typename T>
+constexpr auto f () // { dg-error "deduced class type .A. in function return
type" }
+ -> A<([:R<T>:])> // { dg-error "invalid|expected" }
+{
+ return {};
+}
+
+constexpr auto a = f<^^var, int>(); // { dg-error "declared" }
diff --git a/gcc/testsuite/g++.dg/reflect/crash21.C
b/gcc/testsuite/g++.dg/reflect/crash21.C
new file mode 100644
index 00000000000..f32df8a94fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/crash21.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+template <typename T>
+using A = decltype (T.[:std::meta::nonstatic_data_members_of (^^T,
std::meta::access_context::unchecked ())[0]:]); // { dg-error "expected" }
+
+struct C
+{
+ int c;
+ long d;
+};
+
+int
+main ()
+{
+ [] <typename T = C> requires (requires { A<T> {}; }) // { dg-error
"expected|not declared" }
+ {} (); // { dg-error "no match" }
+}
base-commit: 172f92a464f64b3d6e0a6835882c6cbab36ffc3e
--
2.53.0