From patchwork Fri Nov 5 20:04:14 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 70289 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 64D73B70FD for ; Sat, 6 Nov 2010 07:04:28 +1100 (EST) Received: (qmail 2394 invoked by alias); 5 Nov 2010 20:04:25 -0000 Received: (qmail 2379 invoked by uid 22791); 5 Nov 2010 20:04:24 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 05 Nov 2010 20:04:18 +0000 Received: (qmail 27962 invoked from network); 5 Nov 2010 20:04:16 -0000 Received: from unknown (HELO codesourcery.com) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 5 Nov 2010 20:04:16 -0000 Date: Fri, 5 Nov 2010 16:04:14 -0400 From: Nathan Froyd To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH, c++] fix PR 45332, missing semicolon after member declaration Message-ID: <20101105200412.GA26083@nightcrawler> References: <20101105161332.GY26083@nightcrawler> <4CD45D7A.1000908@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <4CD45D7A.1000908@redhat.com> User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes 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 On Fri, Nov 05, 2010 at 03:39:38PM -0400, Jason Merrill wrote: > On 11/05/2010 12:13 PM, Nathan Froyd wrote: > >+ error_at (token->location, > >+ "expected %<;%> at end of member declaration"); > > Did you mean for this to use cp_parser_error_at_token? Er. I did at one point, then realized c_parse_error is always going to say "ERROR before TOKEN", which is part of what people were grumbling about. So I changed it to use error_at and forgot about deleting cp_parser_error_at_token. Sorry about that. How's this modified patch? Updated message in new testcase, too. -Nathan gcc/cp/ PR c++/45332 * parser.c (cp_lexer_previous_token): New function. (cp_parser_member_declaration): Use previous token for error messages. Assume semicolon presence rather than grovelling for the next one. gcc/testsuite/ PR c++/45332 * g++.dg/parse/semicolon2.C: New testcase. * g++.dg/ext/asmspec1.C: Adjust. * g++.dg/init/new13.C: Adjust. * g++.dg/parse/ctor5.C: Adjust. Modified gcc/cp/parser.c diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6302864..6a9e4d7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -502,6 +502,19 @@ cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos) return pos; } +static inline cp_token * +cp_lexer_previous_token (cp_lexer *lexer) +{ + cp_token_position tp; + + if (lexer->next_token == &eof_token) + tp = lexer->last_token - 1; f+ else + tp = cp_lexer_token_position (lexer, true); + + return cp_lexer_token_at (lexer, tp); +} + /* nonzero if we are presently saving tokens. */ static inline int @@ -17627,6 +17640,8 @@ cp_parser_member_declaration (cp_parser* parser) } else { + bool assume_semicolon = false; + /* See if these declarations will be friends. */ friend_p = cp_parser_friend_p (&decl_specifiers); @@ -17820,11 +17835,18 @@ cp_parser_member_declaration (cp_parser* parser) else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { - cp_parser_error (parser, "expected %<;%>"); - /* Skip tokens until we find a `;'. */ - cp_parser_skip_to_end_of_statement (parser); + /* The next token might be a ways away from where the + actual semicolon is missing. Find the previous token + and use that for our error position. */ + cp_token *token = cp_lexer_previous_token (parser->lexer); + error_at (token->location, + "expected %<;%> at end of member declaration"); - break; + /* Assume that the user meant to provide a semicolon. If + we were to cp_parser_skip_to_end_of_statement, we might + skip to a semicolon inside a member function definition + and issue nonsensical error messages. */ + assume_semicolon = true; } if (decl) @@ -17836,6 +17858,9 @@ cp_parser_member_declaration (cp_parser* parser) if (TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); } + + if (assume_semicolon) + return; } } Modified gcc/testsuite/g++.dg/ext/asmspec1.C diff --git a/gcc/testsuite/g++.dg/ext/asmspec1.C b/gcc/testsuite/g++.dg/ext/asmspec1.C index 3df2483..0661136 100644 --- a/gcc/testsuite/g++.dg/ext/asmspec1.C +++ b/gcc/testsuite/g++.dg/ext/asmspec1.C @@ -3,6 +3,6 @@ struct A { - int i __asm__(int); // { dg-error "before" } - static int j __asm__(int); // { dg-error "before" } + int i __asm__(int); // { dg-error "expected" } + static int j __asm__(int); // { dg-error "expected" } }; Modified gcc/testsuite/g++.dg/init/new13.C diff --git a/gcc/testsuite/g++.dg/init/new13.C b/gcc/testsuite/g++.dg/init/new13.C index 3563c48..2ced6e3 100644 --- a/gcc/testsuite/g++.dg/init/new13.C +++ b/gcc/testsuite/g++.dg/init/new13.C @@ -5,7 +5,7 @@ struct A { - void* operator new(__SIZE_TYPE__) throw(X); // { dg-error "" } + void* operator new(__SIZE_TYPE__) throw(X); // { dg-error "expected|type" } }; -A* p = new A; // { dg-error "no suitable" } +A* p = new A; Modified gcc/testsuite/g++.dg/parse/ctor5.C diff --git a/gcc/testsuite/g++.dg/parse/ctor5.C b/gcc/testsuite/g++.dg/parse/ctor5.C index 8194585..3ea2354 100644 --- a/gcc/testsuite/g++.dg/parse/ctor5.C +++ b/gcc/testsuite/g++.dg/parse/ctor5.C @@ -2,9 +2,9 @@ struct A { - int i; - A() i() {} // { dg-error "expected" } -}; // { dg-error "expected" } + int i; // { dg-error "conflicts" } + A() i() {} // { dg-error "declaration" } +}; struct B { New gcc/testsuite/g++.dg/parse/semicolon2.C diff --git a/gcc/testsuite/g++.dg/parse/semicolon2.C b/gcc/testsuite/g++.dg/parse/semicolon2.C new file mode 100644 index 0000000..50c3ce1 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/semicolon2.C @@ -0,0 +1,9 @@ +// PR c++/45332 +// { dg-do compile } + +class C +{ + int x // { dg-error "at end of member declaration" } + + const int foo() { return x; } +};