c++: Fix infinite looping with invalid operator [PR96137]
authorMarek Polacek <polacek@redhat.com>
Fri, 29 Jan 2021 03:18:32 +0000 (22:18 -0500)
committerMarek Polacek <polacek@redhat.com>
Fri, 29 Jan 2021 04:29:35 +0000 (23:29 -0500)
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.

gcc/cp/parser.c
gcc/testsuite/g++.dg/parse/error63.C [new file with mode: 0644]

index e196db1..5c1d880 100644 (file)
@@ -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 (file)
index 0000000..5472ef0
--- /dev/null
@@ -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" }
+}