From patchwork Thu Oct 11 18:57:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 982652 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-487387-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="X1USptjB"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42WKw14Gbzz9s7T for ; Fri, 12 Oct 2018 05:57:19 +1100 (AEDT) Received: (qmail 28365 invoked by alias); 11 Oct 2018 18:57:13 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 28356 invoked by uid 89); 11 Oct 2018 18:57:12 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=PCH, pch, tissue, sk:make_pa X-HELO: mail-yw1-f43.google.com Received: from mail-yw1-f43.google.com (HELO mail-yw1-f43.google.com) (209.85.161.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 11 Oct 2018 18:57:10 +0000 Received: by mail-yw1-f43.google.com with SMTP id a197-v6so4003683ywh.9 for ; Thu, 11 Oct 2018 11:57:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=DT5D0Vkbj4yzsw2GKjUESxLhCVjzwap4Ub9JOBHZN4w=; b=X1USptjBHCBAZkJhwE6H6ObsdCJtvuMNT8KZgOo55M4U6lM94JPl87ruS+VIPZgYSK YWXXxmTs08TY9vDXzPcgO68eualUbXkwwib5+R8C7XrSnWK7JTpWkAlGxFZXrPeBCajQ leYJlkIOfbebhrBFdG4UJ5OzxqgkzsWkLDhd1kNwwQ5rTtr/YrjfuOnhhzU4mHLhvgJm 1RrGYz3o4/zVsqEQjByF9rs2P8wpIW8aT8xgnQx254KZBGNKwQTkEKPsbQKs4jFSrfVy AV5NaTVrrjndxDk5TpjDr5r/Q5aZs04Cq1/TvhhG5ZWu80fll8q37+DvxVueg3hkuQCF ApWA== Received: from ?IPv6:2620:10d:c0a3:20fb::822? ([2620:10d:c091:200::5:24da]) by smtp.googlemail.com with ESMTPSA id t81-v6sm18219558ywb.90.2018.10.11.11.57.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Oct 2018 11:57:08 -0700 (PDT) Sender: Nathan Sidwell To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] parser simplification Message-ID: <2777ff2d-eb2e-ea09-0f82-6dfa37a8c4d3@acm.org> Date: Thu, 11 Oct 2018 14:57:07 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 MIME-Version: 1.0 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 2018-10-11 Nathan Sidwell 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 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 c; } -{ +{ // { dg-error "expected" } int a; };