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
--
Nathan Sidwell
2018-10-11 Nathan Sidwell <nat...@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;
};