aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2021-01-28 22:18:32 -0500
committerMarek Polacek <polacek@redhat.com>2021-01-28 23:29:35 -0500
commitf8f5388c9e94d4324c31d82b335fa138518e3171 (patch)
tree747ad1787e1b30432c63d55b245abb2cac5e06aa /gcc
parent85d04a2ecb75fb67f2d72f0ff2a34cee92acd7b8 (diff)
downloadgcc-f8f5388c9e94d4324c31d82b335fa138518e3171.zip
gcc-f8f5388c9e94d4324c31d82b335fa138518e3171.tar.gz
gcc-f8f5388c9e94d4324c31d82b335fa138518e3171.tar.bz2
c++: Fix infinite looping with invalid operator [PR96137]
My r11-86 adjusted cp_parser_class_name to do - scope = parser->scope; + scope = parser->scope ? parser->scope : parser->context->object_type; if (scope == error_mark_node) return error_mark_node; but that caused endless looping in cp_parser_type_specifier_seq (the while (true) loop) in this invalid test, because we never set a parser error, therefore cp_parser_type_specifier returned error_mark_node instead of NULL_TREE, and we never issued the "expected type-specifier" error. At first I thought I'd just add cp_parser_simulate_error right before the return, but that regresses crash81.C -- we'd emit multiple errors for "T::X". So the next best thing seemed to revert to pre-r11-86 behavior: return early when parser->scope is bad, otherwise proceed to get the parser error. gcc/cp/ChangeLog: PR c++/96137 * parser.c (cp_parser_class_name): If parser->scope is error_mark_node, return it, otherwise continue. gcc/testsuite/ChangeLog: PR c++/96137 * g++.dg/parse/error63.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/parser.c4
-rw-r--r--gcc/testsuite/g++.dg/parse/error63.C8
2 files changed, 11 insertions, 1 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e196db1..5c1d880 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -24559,7 +24559,9 @@ cp_parser_class_name (cp_parser *parser,
where we first want to look up A<T>::a in the class of the object
expression, as per [basic.lookup.classref]. */
tree scope = parser->scope ? parser->scope : parser->context->object_type;
- if (scope == error_mark_node)
+ /* This only checks parser->scope to avoid duplicate errors; if
+ ->object_type is erroneous, go on to give a parse error. */
+ if (parser->scope == error_mark_node)
return error_mark_node;
/* Any name names a type if we're following the `typename' keyword
diff --git a/gcc/testsuite/g++.dg/parse/error63.C b/gcc/testsuite/g++.dg/parse/error63.C
new file mode 100644
index 0000000..5472ef0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error63.C
@@ -0,0 +1,8 @@
+// PR c++/96137
+// { dg-do compile }
+
+void
+fn ()
+{
+ X.operator T(); // { dg-error ".X. was not declared in this scope|expected" }
+}