From patchwork Mon Jan 24 17:49:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 80222 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 CB4B0B7128 for ; Tue, 25 Jan 2011 04:49:52 +1100 (EST) Received: (qmail 9516 invoked by alias); 24 Jan 2011 17:49:51 -0000 Received: (qmail 9508 invoked by uid 22791); 24 Jan 2011 17:49:50 -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; Mon, 24 Jan 2011 17:49:43 +0000 Received: (qmail 15199 invoked from network); 24 Jan 2011 17:49:41 -0000 Received: from unknown (HELO localhost) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 24 Jan 2011 17:49:41 -0000 Date: Mon, 24 Jan 2011 09:49:41 -0800 From: Nathan Froyd To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH,c++] fix PR 46890, parsing regression Message-ID: <20110124174940.GJ6247@codesourcery.com> References: <20101217172046.GK25059@nightcrawler> <4D24C90E.30601@redhat.com> <20110121140729.GS6247@codesourcery.com> <4D39B26F.9000406@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <4D39B26F.9000406@redhat.com> User-Agent: Mutt/1.5.17+20080114 (2008-01-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, Jan 21, 2011 at 11:21:03AM -0500, Jason Merrill wrote: > On 01/21/2011 09:07 AM, Nathan Froyd wrote: >> On Wed, Jan 05, 2011 at 02:39:58PM -0500, Jason Merrill wrote: >>> How about keyword_is_decl_specifier? >> >> That's a bit cryptic. Do you mean adding keyword_is_decl_specifier to >> c-family? > > Yes, that's what I had in mind. Let's have a predicate that does the > test we want with a name that accurately describes it. OK, how about this patch? It includes Jakub's proposed testcase from the PR. Tested bootstrap, g++ and libstdc++. -Nathan gcc/c-family/ PR c++/46890 * c-common.h (keyword_is_decl_specifier): Declare. * c-common.c (keyword_is_decl_specifier): Define. (keyword_is_function_specifier): New function. gcc/cp/ PR c++/46890 * parser.c (cp_parser_class_specifier): Fix setting of want_semicolon. gcc/testsuite/ PR c++/46890 * g++.dg/parser/semicolon3.C: Adjust. * g++.dg/parser/semicolon4.C: New testcase. * g++.dg/pr46890.C: New testcase. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 2156fa8..3e46019 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -9653,4 +9653,42 @@ keyword_is_storage_class_specifier (enum rid keyword) } } +/* Return true if KEYWORD names a function-specifier [dcl.fct.spec]. */ + +static bool +keyword_is_function_specifier (enum rid keyword) +{ + switch (keyword) + { + case RID_INLINE: + case RID_VIRTUAL: + case RID_EXPLICIT: + return true; + default: + return false; + } +} + +/* Return true if KEYWORD names a decl-specifier [dcl.spec] or a + declaration-specifier (C99 6.7). */ + +bool +keyword_is_decl_specifier (enum rid keyword) +{ + if (keyword_is_storage_class_specifier (keyword) + || keyword_is_type_qualifier (keyword) + || keyword_is_function_specifier (keyword)) + return true; + + switch (keyword) + { + case RID_TYPEDEF: + case RID_FRIEND: + case RID_CONSTEXPR: + return true; + default: + return false; + } +} + #include "gt-c-family-c-common.h" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 05456d3..406def9 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -741,6 +741,7 @@ extern bool float_const_decimal64_p (void); extern bool keyword_begins_type_specifier (enum rid); extern bool keyword_is_storage_class_specifier (enum rid); extern bool keyword_is_type_qualifier (enum rid); +extern bool keyword_is_decl_specifier (enum rid); #define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, 1) #define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, 1) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 41f82ac..4a6a8d0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16998,18 +16998,15 @@ cp_parser_class_specifier (cp_parser* parser) class Z { } static const var = ...; */ case CPP_KEYWORD: - if (keyword_is_storage_class_specifier (token->keyword) - || keyword_is_type_qualifier (token->keyword)) + if (keyword_is_decl_specifier (token->keyword)) { cp_token *lookahead = cp_lexer_peek_nth_token (parser->lexer, 2); - if (lookahead->type == CPP_KEYWORD - && !keyword_begins_type_specifier (lookahead->keyword)) - want_semicolon = false; - else if (lookahead->type == CPP_NAME) - /* Handling user-defined types here would be nice, but - very tricky. */ - want_semicolon = false; + /* Handling user-defined types here would be nice, but very + tricky. */ + want_semicolon + = (lookahead->type == CPP_KEYWORD + && keyword_begins_type_specifier (lookahead->keyword)); } break; default: diff --git a/gcc/testsuite/g++.dg/parse/semicolon3.C b/gcc/testsuite/g++.dg/parse/semicolon3.C index a119ef4..bc43b48 100644 --- a/gcc/testsuite/g++.dg/parse/semicolon3.C +++ b/gcc/testsuite/g++.dg/parse/semicolon3.C @@ -62,6 +62,48 @@ autotest (void) return ok10.a; } +struct OK11 +{ + int a; +} // no complaints + const *ok11_var; + +struct OK12 +{ + int a; +} // no complaints + const &ok12_var = *(new OK12()); + +struct OK13 +{ + int a; +} // no complaints + static *ok13_var; + +class OK14 +{ + struct OK14sub + { + int a; + } // no complaints + static &ok14_var; +}; + +class OK15 +{ + int a; +} typedef tOK15; + +class OK16 +{ + int a; +} typedef *pOK16; + +class OK17 +{ + int a; +} typedef &rOK16; + struct E1 { int a; @@ -196,6 +238,13 @@ class E17 mutable int i; } // { dg-error "after class definition" } +class E18 +{ + int a; +} // { dg-error "after class definition" } + +typedef int E18int; + /* This was the original test from the PR. */ class C0 diff --git a/gcc/testsuite/g++.dg/parse/semicolon4.C b/gcc/testsuite/g++.dg/parse/semicolon4.C new file mode 100644 index 0000000..adba7a8 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/semicolon4.C @@ -0,0 +1,37 @@ +// PR c++/46890 +// { dg-do compile } + +struct OK1 +{ + int i; +} const *ok1_var; // No complains + +struct OK2; +extern OK2 ok2a_var; + +struct OK2 +{ + int i; +} const &ok2_var = ok2a_var; // No complains + +struct OK3 +{ + int i; +} volatile (ok3_var); // No complains + +struct E1 +{ + int i; +} const; // { dg-error "qualifiers can only be specified for objects and functions" } + +void foo ( +struct E2 +{ // { dg-error "types may not be defined in parameter types" } + int i; +} volatile); + +void bar ( +struct E3 +{ // { dg-error "types may not be defined in parameter types" } + int i; +} const, int); diff --git a/gcc/testsuite/g++.dg/pr46890.C b/gcc/testsuite/g++.dg/pr46890.C new file mode 100644 index 0000000..3ecef5a --- /dev/null +++ b/gcc/testsuite/g++.dg/pr46890.C @@ -0,0 +1,6 @@ +// PR c++/46890 +// { dg-do compile } + +struct MdatResource { +const char *mdatAlloc; +} const *_resource;