objc++: Always pop scope with method definitions [PR97015]
authorNathan Sidwell <nathan@acm.org>
Fri, 11 Sep 2020 15:23:32 +0000 (08:23 -0700)
committerNathan Sidwell <nathan@acm.org>
Fri, 11 Sep 2020 15:27:40 +0000 (08:27 -0700)
Syntax errors in method definition lists could leave us in a function
scope.  My recent change for block scope externs didn't like that.
This reimplements the parsing loop to finish the method definition we
started.  AFAICT the original code was attempting to provide some
error recovery.  Also while there, simply do the token peeking at the
top of the loop, rather than at the two(!) ends.

gcc/cp/
* parser.c (cp_parser_objc_method_definition_list): Reimplement
loop, make sure we pop scope.
gcc/testsuite/
* obj-c++.dg/syntax-error-9.mm: Adjust expected errors.

gcc/cp/parser.c
gcc/testsuite/obj-c++.dg/syntax-error-9.mm

index fed16895b424169c2312aee270d0cb3a8eb3450d..fba3fcc0c4c44bfd7b75a3f995f35a48358ecffe 100644 (file)
@@ -32980,44 +32980,42 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
 static void
 cp_parser_objc_method_definition_list (cp_parser* parser)
 {
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
+  for (;;)
     {
-      tree meth;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+      if (token->keyword == RID_AT_END)
        {
-         cp_token *ptk;
-         tree sig, attribute;
-         bool is_class_method;
-         if (token->type == CPP_PLUS)
-           is_class_method = true;
-         else
-           is_class_method = false;
+         cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+         break;
+       }
+      else if (token->type == CPP_EOF)
+       {
+         cp_parser_error (parser, "expected %<@end%>");
+         break;
+       }
+      else if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+       {
+         bool is_class_method = token->type == CPP_PLUS;
+
          push_deferring_access_checks (dk_deferred);
-         sig = cp_parser_objc_method_signature (parser, &attribute);
+         tree attribute;
+         tree sig = cp_parser_objc_method_signature (parser, &attribute);
          if (sig == error_mark_node)
+           cp_parser_skip_to_end_of_block_or_statement (parser);
+         else
            {
-             cp_parser_skip_to_end_of_block_or_statement (parser);
-             token = cp_lexer_peek_token (parser->lexer);
-             continue;
-           }
-         objc_start_method_definition (is_class_method, sig, attribute,
-                                       NULL_TREE);
+             objc_start_method_definition (is_class_method, sig,
+                                           attribute, NULL_TREE);
 
-         /* For historical reasons, we accept an optional semicolon.  */
-         if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-           cp_lexer_consume_token (parser->lexer);
+             /* For historical reasons, we accept an optional semicolon.  */
+             if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+               cp_lexer_consume_token (parser->lexer);
 
-         ptk = cp_lexer_peek_token (parser->lexer);
-         if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
-               || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
-           {
              perform_deferred_access_checks (tf_warning_or_error);
              stop_deferring_access_checks ();
-             meth = cp_parser_function_definition_after_declarator (parser,
-                                                                    false);
+             tree meth
+               = cp_parser_function_definition_after_declarator (parser, false);
              pop_deferring_access_checks ();
              objc_finish_method_definition (meth);
            }
@@ -33037,15 +33035,8 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
       else
        /* Allow for interspersed non-ObjC++ code.  */
        cp_parser_objc_interstitial_code (parser);
-
-      token = cp_lexer_peek_token (parser->lexer);
     }
 
-  if (token->type != CPP_EOF)
-    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
-  else
-    cp_parser_error (parser, "expected %<@end%>");
-
   objc_finish_implementation ();
 }
 
index ae104e5c140e0aed58200e89c275211f8b1025a1..1876c32dd20d6a3c520323600b205712d5485463 100644 (file)
@@ -1,3 +1,3 @@
 @implementation SaturnDoc /* { dg-warning "cannot find interface declaration" } */
 - read: (void*)aStream ggg /* { dg-error "expected .:. at end of input" } */
-/* { dg-error "-:expected ..end. at end of input" "" { target *-*-* } .+1 } */
+/* { dg-error "-:expected ..*. at end of input" "" { target *-*-* } .+1 } */