diff mbox series

[C++] parser simplification

Message ID 2777ff2d-eb2e-ea09-0f82-6dfa37a8c4d3@acm.org
State New
Headers show
Series [C++] parser simplification | expand

Commit Message

Nathan Sidwell Oct. 11, 2018, 6:57 p.m. UTC
In working out how to orchestrate the preprocessor/parser dance that 
modules require, I came across the confused logic of 
cp_parser_translation_unit.  It is only called once, but looks as if it 
used to be called multiple times, and retains the scar tissue from that.

It also bails out on the first extra } brace, ignoring anything after 
that.  A couple of testcases had that hiding later (uninteresting) 
diagnostics.

I moved finish_translation_unit to c_parse_file, as it seems more 
related there than the parsing.

Booted & tested on x86_64-linux, applying to trunk.

nathan
diff mbox series

Patch

2018-10-11  Nathan Sidwell  <nathan@acm.org>

	cp/
	* parser.c (cp_parser_translation_unit): Return void.  Don't fail
	at first extra }, simplify logic.
	(c_parse_file): Call finish_translation_unit here.

	testsuite/
	* g++.dg/parse/close-brace.C: New.
	* g++.dg/cpp0x/noexcept16.C: Avoid warning.
	* g++.old-deja/g++.other/crash32.C: Add another error

Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 265035)
+++ cp/parser.c	(working copy)
@@ -2015,8 +2015,7 @@  static cp_expr cp_parser_userdef_numeric
 
 /* Basic concepts [gram.basic]  */
 
-static bool cp_parser_translation_unit
-  (cp_parser *);
+static void cp_parser_translation_unit (cp_parser *);
 
 /* Expressions [gram.expr]  */
 
@@ -4585,66 +4584,52 @@  cp_parser_userdef_string_literal (tree l
 /* Parse a translation-unit.
 
    translation-unit:
-     declaration-seq [opt]
-
-   Returns TRUE if all went well.  */
+     declaration-seq [opt]  */
 
-static bool
+static void
 cp_parser_translation_unit (cp_parser* parser)
 {
-  /* The address of the first non-permanent object on the declarator
-     obstack.  */
-  static void *declarator_obstack_base;
-
-  bool success;
-
-  /* Create the declarator obstack, if necessary.  */
-  if (!cp_error_declarator)
-    {
-      gcc_obstack_init (&declarator_obstack);
-      /* Create the error declarator.  */
-      cp_error_declarator = make_declarator (cdk_error);
-      /* Create the empty parameter list.  */
-      no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE,
-						 UNKNOWN_LOCATION);
-      /* Remember where the base of the declarator obstack lies.  */
-      declarator_obstack_base = obstack_next_free (&declarator_obstack);
-    }
-
-  cp_parser_declaration_seq_opt (parser);
+  gcc_checking_assert (!cp_error_declarator);
+  
+  /* Create the declarator obstack.  */
+  gcc_obstack_init (&declarator_obstack);
+  /* Create the error declarator.  */
+  cp_error_declarator = make_declarator (cdk_error);
+  /* Create the empty parameter list.  */
+  no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE,
+					     UNKNOWN_LOCATION);
+  /* Remember where the base of the declarator obstack lies.  */
+  void *declarator_obstack_base = obstack_next_free (&declarator_obstack);
 
-  /* If there are no tokens left then all went well.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+  for (;;)
     {
-      /* Get rid of the token array; we don't need it any more.  */
-      cp_lexer_destroy (parser->lexer);
-      parser->lexer = NULL;
-
-      /* This file might have been a context that's implicitly extern
-	 "C".  If so, pop the lang context.  (Only relevant for PCH.) */
-      if (parser->implicit_extern_c)
-	{
-	  pop_lang_context ();
-	  parser->implicit_extern_c = false;
-	}
-
-      /* Finish up.  */
-      finish_translation_unit ();
-
-      success = true;
+      cp_parser_declaration_seq_opt (parser);
+      gcc_assert (!cp_parser_parsing_tentatively (parser));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+	break;
+      /* Must have been an extra close-brace.  */
+      cp_parser_error (parser, "expected declaration");
+      cp_lexer_consume_token (parser->lexer);
+      /* If the next token is now a `;', consume it.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+	cp_lexer_consume_token (parser->lexer);
     }
-  else
+
+  /* Get rid of the token array; we don't need it any more.  */
+  cp_lexer_destroy (parser->lexer);
+  parser->lexer = NULL;
+  
+  /* This file might have been a context that's implicitly extern
+     "C".  If so, pop the lang context.  (Only relevant for PCH.) */
+  if (parser->implicit_extern_c)
     {
-      cp_parser_error (parser, "expected declaration");
-      success = false;
+      pop_lang_context ();
+      parser->implicit_extern_c = false;
     }
 
   /* Make sure the declarator obstack was fully cleaned up.  */
   gcc_assert (obstack_next_free (&declarator_obstack)
 	      == declarator_obstack_base);
-
-  /* All went well.  */
-  return success;
 }
 
 /* Return the appropriate tsubst flags for parsing, possibly in N3276
@@ -39130,6 +39115,8 @@  c_parse_file (void)
 				? dk_no_deferred : dk_no_check);
   cp_parser_translation_unit (the_parser);
   the_parser = NULL;
+
+  finish_translation_unit ();
 }
 
 /* Create an identifier for a generic parameter type (a synthesized
Index: testsuite/g++.dg/cpp0x/noexcept16.C
===================================================================
--- testsuite/g++.dg/cpp0x/noexcept16.C	(revision 265035)
+++ testsuite/g++.dg/cpp0x/noexcept16.C	(working copy)
@@ -124,7 +124,7 @@  swap(_Tp&, _Tp&)
   ;
 typedef lexertl::basic_state_machine<char32_t> lexstate;
 lexstate m_state_machine;
-GenerateLexer()
+void GenerateLexer()
 {
   m_state_machine.minimise();
 }
Index: testsuite/g++.dg/parse/close-brace.C
===================================================================
--- testsuite/g++.dg/parse/close-brace.C	(revision 0)
+++ testsuite/g++.dg/parse/close-brace.C	(working copy)
@@ -0,0 +1,5 @@ 
+// We used to stop parsing at the first top-level '}' !
+
+} // { dg-error "expected declaration" }
+
+float int c; // { dg-error "two or more data types" }
Index: testsuite/g++.old-deja/g++.other/crash32.C
===================================================================
--- testsuite/g++.old-deja/g++.other/crash32.C	(revision 265035)
+++ testsuite/g++.old-deja/g++.other/crash32.C	(working copy)
@@ -5,7 +5,9 @@  struct foo
 {
   enum e
   {
-    not				// { dg-error "" } 
+    not				// { dg-error "" }
+    // We think the next close-brace closes the definition of struct
+    // foo, not enum e.  Things go downhill from there
   }; // { dg-bogus "" } 
   ~foo(); // { dg-bogus "" "" { xfail *-*-* } } 
   void x (foo *&a, bool b = (unsigned char)0);
@@ -24,6 +26,6 @@  namespace N
   typedef baz<bar> c;
 }
 
-{
+{ // { dg-error "expected" }
   int a;
 };