From patchwork Tue Sep 28 17:07:06 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 66004 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 73923B7116 for ; Wed, 29 Sep 2010 03:07:53 +1000 (EST) Received: (qmail 10254 invoked by alias); 28 Sep 2010 17:07:51 -0000 Received: (qmail 10207 invoked by uid 22791); 28 Sep 2010 17:07:46 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL, BAYES_05, RCVD_IN_DNSWL_NONE, TW_BJ, TW_KW X-Spam-Check-By: sourceware.org Received: from c2beaomr09.btconnect.com (HELO mail.btconnect.com) (213.123.26.187) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 28 Sep 2010 17:07:36 +0000 Received: from host81-138-1-83.in-addr.btopenworld.com (EHLO thor.office) ([81.138.1.83]) by c2beaomr09.btconnect.com with ESMTP id ACU74702; Tue, 28 Sep 2010 18:07:29 +0100 (BST) Cc: GCC Patches , "Joseph S. Myers" , Jason Merrill , Nicola Pero Message-Id: From: IainS To: Mike Stump In-Reply-To: Mime-Version: 1.0 (Apple Message framework v936) Subject: Re: [Patch, ObjC/C++ V2, Part1] Recognize attributes on class, category and protocol declarations. Date: Tue, 28 Sep 2010 18:07:06 +0100 References: X-Mirapoint-IP-Reputation: reputation=Fair-1, source=Queried, refid=tid=0001.0A0B0302.4CA220BB.003D, actions=tag X-Junkmail-Signature-Raw: score=unknown, refid=str=0001.0A0B0201.4CA220D5.025C, ss=1, fgs=0, ip=0.0.0.0, so=2010-07-22 22:03:31, dmn=2009-09-10 00:05:08, mode=single engine 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 Mike, I will note that, whilst the patch touches gcc/ gcc/c-family gcc/cp and gcc/objc, it *only* touches objc-specific routines or code paths. Ergo, as per Nicola's relayed email from Joseph, it is eligible for your review, if you would have time. (of course, I would welcome comments from any reviewer). This is a re-issue of this patch that takes into account: (a) Nicola's comment on the diagnostics strings (b) makes some small stylistic changes (naming routines more consistently) (c) factors a test out that is needed in several places (and by method attribs in part 2) (d) Splits the patch into code & test-suite sections. tested on i686-darwin9, x86_64-linux and a cross to cris-elf OK for trunk? Iain On 26 Sep 2010, at 15:04, IainS wrote: > > gcc/c-family: > > * c-common.h (objc_start_class_interface): Adjust prototype. > (objc_start_category_interface): Likewise. > (objc_start_protocol): Likewise. > * stub-objc.c (objc_start_protocol): Adjust for extra argument. > (objc_start_class_interface): Likewise. > (objc_start_category_interface): Likewise. > > gcc/objc: > > * objc-act.c (objc_start_class_interface): Handle and ignore > attributes. > (objc_start_category_interface): Likewise. > (objc_start_protocol): Likewise. > > gcc/cp: > * parser.c (cp_parser_objc_valid_prefix_attributes): New. > (cp_parser_declaration): Parse prefix attributes for ObjC++. > (cp_parser_objc_protocol_declaration): Handle attributes. > (cp_parser_objc_class_interface): Likewise. > (cp_parser_objc_declaration): Likewise. > > gcc: > > * c-parser.c (c_parser_objc_class_definition): Adjust prototype. > (c_parser_objc_protocol_definition): Likewise. > (c_parser_external_declaration): Provide dummy attribute arguments. > (c_parser_declaration_or_fndef): Parse prefix attributes for ObjC. > (c_parser_objc_class_definition): Handle attributes. > (c_parser_objc_protocol_definition): Likewise. > should be considered, statements. ALLOW_STMT is true if we're within > gcc/testsuite: > > * objc.dg/attributes: New. > * objc.dg/attributes/attributes.exp: New. > * objc.dg/attributes/class-attribute-1.m: New. > * objc.dg/attributes/class-attribute-2.m: New > * objc.dg/attributes/categ-attribute-1.m: New > * objc.dg/attributes/categ-attribute-2.m: New > * objc.dg/attributes/proto-attribute-1.m: New > > * obj-c++.dg/attributes: New. > * obj-c++.dg/attributes/attributes.exp: New > * obj-c++.dg/attributes/class-attribute-1.mm: New > * obj-c++.dg/attributes/class-attribute-2.mm: New > * obj-c++.dg/attributes/categ-attribute-1.mm: New > * obj-c++.dg/attributes/categ-attribute-2.mm: New > * obj-c++.dg/attributes/proto-attribute-1.mm: New Index: gcc/testsuite/objc.dg/attributes/class-attribute-1.m =================================================================== --- gcc/testsuite/objc.dg/attributes/class-attribute-1.m (revision 0) +++ gcc/testsuite/objc.dg/attributes/class-attribute-1.m (revision 0) @@ -0,0 +1,36 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +/* Normal deprecated func. */ +__attribute ((deprecated)) void f1(); +__attribute__ ((deprecated("use some new func"))) void f2(); + +__attribute__ ((deprecated)) +@interface DEPRECATED : Object + { @public int ivar; } /* { dg-warning "class attributes are not available in this version" } */ + - (int) instancemethod; +@end + +@implementation DEPRECATED +-(int) instancemethod { return ivar; } +@end + +@interface DEPRECATED (Category) +@end /* dg - warning "deprecated" */ + +@interface NS : DEPRECATED +@end /* dg - warning "deprecated" */ + +DEPRECATED * deprecated_obj; /* dg - warning "deprecated" */ + +int foo (DEPRECATED *unavailable_obj) /* dg - warning "deprecated" */ +{ + DEPRECATED *p = [DEPRECATED new]; /* dg - warning "deprecated" */ + + f1(); /* { dg-warning "'f1' is deprecated" } */ + f2(); /* { dg-warning "'f2' is deprecated .declared at \[^\\)\]*.: use some new func" } */ + int q = p->ivar; + return [p instancemethod]; +} Index: gcc/testsuite/objc.dg/attributes/class-attribute-2.m =================================================================== --- gcc/testsuite/objc.dg/attributes/class-attribute-2.m (revision 0) +++ gcc/testsuite/objc.dg/attributes/class-attribute-2.m (revision 0) @@ -0,0 +1,25 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +__attribute ((deprecated)) +@interface depobj : Object { /* { dg-warning "class attributes are not available in this version" } */ +@public + int ivar; +} +- (int) mth; +@end + +__attribute ((deprecated)) +@implementation depobj /* { dg-warning "prefix attributes are ignored for implementations" } */ +-(int) mth { return ivar; } +@end + +int foo (void) +{ + depobj *p = [depobj new]; /* dg - warning "deprecated" */ + + int q = p->ivar; + return [p mth]; +} Index: gcc/testsuite/objc.dg/attributes/attributes.exp =================================================================== --- gcc/testsuite/objc.dg/attributes/attributes.exp (revision 0) +++ gcc/testsuite/objc.dg/attributes/attributes.exp (revision 0) @@ -0,0 +1,44 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Load support procs. + +load_lib objc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS "" +} + +# Initialize `dg'. +dg-init + +# Gather a list of all tests. +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.m]] + +# Main loop. +dg-runtest $tests "-fgnu-runtime" $DEFAULT_CFLAGS + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { + dg-runtest $tests "-fnext-runtime" $DEFAULT_CFLAGS +} + +# All done. +dg-finish Index: gcc/testsuite/objc.dg/attributes/categ-attribute-1.m =================================================================== --- gcc/testsuite/objc.dg/attributes/categ-attribute-1.m (revision 0) +++ gcc/testsuite/objc.dg/attributes/categ-attribute-1.m (revision 0) @@ -0,0 +1,31 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) mth; +@end + +@implementation obj +- (int) mth { return var; } +@end + +__attribute ((deprecated)) +@interface obj (dep_categ) +- (int) depmth;/* { dg-warning "category attributes are not available in this version" } */ +@end + +@implementation obj (dep_categ) +- (int) depmth { return var + 1; } +@end + +int foo (void) +{ + obj *p = [obj new]; + int q = [p depmth]; + return [p mth]; +} Index: gcc/testsuite/objc.dg/attributes/proto-attribute-1.m =================================================================== --- gcc/testsuite/objc.dg/attributes/proto-attribute-1.m (revision 0) +++ gcc/testsuite/objc.dg/attributes/proto-attribute-1.m (revision 0) @@ -0,0 +1,29 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +__attribute ((deprecated)) +@protocol dep_proto +- (int) depprotomth; /* { dg-warning "protocol attributes are not available in this version" } */ +@end + +@interface obj : Object +{ +@public + int var; +} +- (int) mth; +@end + +@implementation obj +- (int) mth { return var; } +- (int) depprotomth { return var + 1; } +@end + +int foo (void) +{ + obj *p = [obj new]; + int q = [p depprotomth]; + return [p mth]; +} Index: gcc/testsuite/objc.dg/attributes/categ-attribute-2.m =================================================================== --- gcc/testsuite/objc.dg/attributes/categ-attribute-2.m (revision 0) +++ gcc/testsuite/objc.dg/attributes/categ-attribute-2.m (revision 0) @@ -0,0 +1,32 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) mth; +@end + +@implementation obj +- (int) mth { return var; } +@end + +__attribute__ ((deprecated("no dep_categ"))) +@interface obj (dep_categ) +- (int) depmth;/* { dg-warning "category attributes are not available in this version" } */ +@end + +__attribute__ ((deprecated)) +@implementation obj (dep_categ) /* { dg-warning "prefix attributes are ignored for implementations" } */ +- (int) depmth { return var + 1; } +@end + +int foo (void) +{ + obj *p = [obj new]; + int q = [p depmth]; + return [p mth]; +} Index: gcc/testsuite/obj-c++.dg/attributes/attributes.exp =================================================================== --- gcc/testsuite/obj-c++.dg/attributes/attributes.exp (revision 0) +++ gcc/testsuite/obj-c++.dg/attributes/attributes.exp (revision 0) @@ -0,0 +1,43 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Load support procs. +load_lib obj-c++-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_OBJCXXFLAGS +if ![info exists DEFAULT_OBJCXXFLAGS] then { + set DEFAULT_OBJCXXFLAGS " -ansi -pedantic-errors -Wno-long-long" +} + +# Initialize `dg'. +dg-init + +# Gather a list of all tests. +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]] + +# Main loop. +dg-runtest $tests "-fgnu-runtime" $DEFAULT_OBJCXXFLAGS + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { + dg-runtest $tests "-fnext-runtime" $DEFAULT_OBJCXXFLAGS +} + +# All done. +dg-finish Index: gcc/testsuite/obj-c++.dg/attributes/categ-attribute-1.mm =================================================================== --- gcc/testsuite/obj-c++.dg/attributes/categ-attribute-1.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/attributes/categ-attribute-1.mm (revision 0) @@ -0,0 +1,31 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) mth; +@end + +@implementation obj +- (int) mth { return var; } +@end + +__attribute ((deprecated)) +@interface obj (dep_categ) /* { dg-warning "category attributes are not available in this version" } */ +- (int) depmth; +@end + +@implementation obj (dep_categ) +- (int) depmth { return var + 1; } +@end + +int foo (void) +{ + obj *p = [obj new]; + int q = [p depmth]; + return [p mth]; +} Index: gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm =================================================================== --- gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/attributes/proto-attribute-1.mm (revision 0) @@ -0,0 +1,29 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +__attribute ((deprecated)) +@protocol dep_proto /* { dg-warning "protocol attributes are not available in this version" } */ +- (int) depprotomth; +@end + +@interface obj : Object +{ +@public + int var; +} +- (int) mth; +@end + +@implementation obj +- (int) mth { return var; } +- (int) depprotomth { return var + 1; } +@end + +int foo (void) +{ + obj *p = [obj new]; + int q = [p depprotomth]; + return [p mth]; +} Index: gcc/testsuite/obj-c++.dg/attributes/categ-attribute-2.mm =================================================================== --- gcc/testsuite/obj-c++.dg/attributes/categ-attribute-2.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/attributes/categ-attribute-2.mm (revision 0) @@ -0,0 +1,32 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) mth; +@end + +@implementation obj +- (int) mth { return var; } +@end + +__attribute__ ((deprecated("no dep_categ"))) +@interface obj (dep_categ) /* { dg-warning "category attributes are not available in this version" } */ +- (int) depmth; +@end + +__attribute__ ((deprecated)) +@implementation obj (dep_categ) /* { dg-error "prefix attributes are ignored before" } */ +- (int) depmth { return var + 1; } +@end + +int foo (void) +{ + obj *p = [obj new]; + int q = [p depmth]; + return [p mth]; +} Index: gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm =================================================================== --- gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/attributes/class-attribute-1.mm (revision 0) @@ -0,0 +1,38 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +/* Normal deprecated func. */ +__attribute ((deprecated)) void f1(); +__attribute__ ((deprecated("use some new func"))) void f2(); + +__attribute__ ((deprecated)) +@interface depobj : Object { /* { dg-warning "class attributes are not available in this version" } */ +@public + int var; +} +- (int) mth; +@end + +@implementation depobj +-(int) mth { return var; } +@end + +@interface depobj (ok_categ) +@end + +@interface NS : depobj +@end + +depobj * deprecated; + +int foo (depobj *dep_obj) /* dg - warning "deprecated" */ +{ + depobj *p = [depobj new]; /* dg - warning "deprecated" */ + + f1(); /* { dg-warning "'void f1..' is deprecated .declared at" } */ + f2(); /* { dg-warning "'void f2..' is deprecated .declared at \[^\\)\]*.: use some new func" } */ + int q = p->var; + return [p mth]; +} Index: gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm =================================================================== --- gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/attributes/class-attribute-2.mm (revision 0) @@ -0,0 +1,25 @@ +/* { dg-do compile } */ + +#include +#include "../../objc-obj-c++-shared/Object1.h" + +__attribute ((deprecated)) +@interface depobj : Object { /* { dg-warning "class attributes are not available in this version" } */ +@public + int ivar; +} +- (int) mth; +@end + +__attribute ((deprecated)) +@implementation depobj /* { dg-error "prefix attributes are ignored before" } */ +-(int) mth { return ivar; } +@end + +int foo (void) +{ + depobj *p = [depobj new]; /* dg - warning "deprecated" */ + + int q = p->ivar; + return [p mth]; +} Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 164686) +++ gcc/c-family/c-common.h (working copy) @@ -965,9 +965,9 @@ extern tree objc_get_protocol_qualified_type (tree extern tree objc_get_class_reference (tree); extern tree objc_get_class_ivars (tree); extern tree objc_get_interface_ivars (tree); -extern void objc_start_class_interface (tree, tree, tree); -extern void objc_start_category_interface (tree, tree, tree); -extern void objc_start_protocol (tree, tree); +extern void objc_start_class_interface (tree, tree, tree, tree); +extern void objc_start_category_interface (tree, tree, tree, tree); +extern void objc_start_protocol (tree, tree, tree); extern void objc_continue_interface (void); extern void objc_finish_interface (void); extern void objc_start_class_implementation (tree, tree); Index: gcc/c-family/stub-objc.c =================================================================== --- gcc/c-family/stub-objc.c (revision 164686) +++ gcc/c-family/stub-objc.c (working copy) @@ -122,21 +122,24 @@ objc_declare_protocols (tree ARG_UNUSED (list)) void objc_start_protocol (tree ARG_UNUSED (proto), - tree ARG_UNUSED (protorefs)) + tree ARG_UNUSED (protorefs), + tree ARG_UNUSED (attribs)) { } void objc_start_class_interface (tree ARG_UNUSED (name), tree ARG_UNUSED (super), - tree ARG_UNUSED (protos)) + tree ARG_UNUSED (protos), + tree ARG_UNUSED (attribs)) { } void objc_start_category_interface (tree ARG_UNUSED (name), tree ARG_UNUSED (categ), - tree ARG_UNUSED (protos)) + tree ARG_UNUSED (protos), + tree ARG_UNUSED (attribs)) { } Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 164686) +++ gcc/cp/parser.c (working copy) @@ -2086,9 +2086,11 @@ static tree cp_parser_objc_selector static tree cp_parser_objc_protocol_refs_opt (cp_parser *); static void cp_parser_objc_declaration - (cp_parser *); + (cp_parser *, tree); static tree cp_parser_objc_statement (cp_parser *); +static bool cp_parser_objc_valid_prefix_attributes + (cp_parser* parser, tree *attrib); /* Utility Routines */ @@ -9285,6 +9287,7 @@ cp_parser_declaration (cp_parser* parser) cp_token token2; int saved_pedantic; void *p; + tree attributes = NULL_TREE; /* Check for the `__extension__' keyword. */ if (cp_parser_extension_opt (parser, &saved_pedantic)) @@ -9362,7 +9365,11 @@ cp_parser_declaration (cp_parser* parser) cp_parser_namespace_definition (parser); /* Objective-C++ declaration/definition. */ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword)) - cp_parser_objc_declaration (parser); + cp_parser_objc_declaration (parser, NULL_TREE); + else if (c_dialect_objc () + && token1.keyword == RID_ATTRIBUTE + && cp_parser_objc_valid_prefix_attributes (parser, &attributes)) + cp_parser_objc_declaration (parser, attributes); /* We must have either a block declaration or a function definition. */ else @@ -21739,7 +21849,7 @@ cp_parser_objc_class_ivars (cp_parser* parser) /* Parse an Objective-C protocol declaration. */ static void -cp_parser_objc_protocol_declaration (cp_parser* parser) +cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) { tree proto, protorefs; cp_token *tok; @@ -21768,7 +21878,7 @@ static void { proto = cp_parser_identifier (parser); protorefs = cp_parser_objc_protocol_refs_opt (parser); - objc_start_protocol (proto, protorefs); + objc_start_protocol (proto, protorefs, attributes); cp_parser_objc_method_prototype_list (parser); } } @@ -21798,7 +21908,7 @@ cp_parser_objc_superclass_or_category (cp_parser * /* Parse an Objective-C class interface. */ static void -cp_parser_objc_class_interface (cp_parser* parser) +cp_parser_objc_class_interface (cp_parser* parser, tree attributes) { tree name, super, categ, protos; @@ -21809,10 +21919,10 @@ static void /* We have either a class or a category on our hands. */ if (categ) - objc_start_category_interface (name, categ, protos); + objc_start_category_interface (name, categ, protos, attributes); else { - objc_start_class_interface (name, super, protos); + objc_start_class_interface (name, super, protos, attributes); /* Handle instance variable declarations, if any. */ cp_parser_objc_class_ivars (parser); objc_continue_interface (); @@ -21858,11 +21968,31 @@ cp_parser_objc_end_implementation (cp_parser* pars /* Parse an Objective-C declaration. */ static void -cp_parser_objc_declaration (cp_parser* parser) +cp_parser_objc_declaration (cp_parser* parser, tree attributes) { /* Try to figure out what kind of declaration is present. */ cp_token *kwd = cp_lexer_peek_token (parser->lexer); + if (attributes) + switch (kwd->keyword) + { + case RID_AT_ALIAS: + case RID_AT_CLASS: + case RID_AT_END: + error_at (kwd->location, "attributes may not be specified before" + " the %<@%D%> Objective-C++ keyword", + kwd->u.value); + attributes = NULL; + break; + case RID_AT_IMPLEMENTATION: + warning_at (kwd->location, OPT_Wattributes, + "prefix attributes are ignored before %<@%D%>", + kwd->u.value); + attributes = NULL; + default: + break; + } + switch (kwd->keyword) { case RID_AT_ALIAS: @@ -21872,10 +22002,10 @@ static void cp_parser_objc_class_declaration (parser); break; case RID_AT_PROTOCOL: - cp_parser_objc_protocol_declaration (parser); + cp_parser_objc_protocol_declaration (parser, attributes); break; case RID_AT_INTERFACE: - cp_parser_objc_class_interface (parser); + cp_parser_objc_class_interface (parser, attributes); break; case RID_AT_IMPLEMENTATION: cp_parser_objc_class_implementation (parser); @@ -22024,6 +22154,26 @@ cp_parser_objc_statement (cp_parser * parser) { return error_mark_node; } + +/* If we are compiling ObjC++ and we see an __attribute__ we neeed to + look ahead to see if an objc keyword follows the attributes. This + is to detect the use of prefix attributes on ObjC @interface and + @protocol. */ + +static bool +cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib) +{ + cp_lexer_save_tokens (parser->lexer); + *attrib = cp_parser_attributes_opt (parser); + gcc_assert (*attrib); + if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword)) + { + cp_lexer_commit_tokens (parser->lexer); + return true; + } + cp_lexer_rollback_tokens (parser->lexer); + return false; +} /* OpenMP 2.5 parsing routines. */ Index: gcc/objc/objc-act.c =================================================================== --- gcc/objc/objc-act.c (revision 164686) +++ gcc/objc/objc-act.c (working copy) @@ -650,8 +650,13 @@ lookup_protocol_in_reflist (tree rproto_list, tree } void -objc_start_class_interface (tree klass, tree super_class, tree protos) +objc_start_class_interface (tree klass, tree super_class, + tree protos, tree attributes) { + if (attributes) + warning_at (input_location, OPT_Wattributes, + "class attributes are not available in this version" + " of the compiler, (ignored)"); objc_interface_context = objc_ivar_context = start_class (CLASS_INTERFACE_TYPE, klass, super_class, protos); @@ -659,8 +664,13 @@ void } void -objc_start_category_interface (tree klass, tree categ, tree protos) +objc_start_category_interface (tree klass, tree categ, + tree protos, tree attributes) { + if (attributes) + warning_at (input_location, OPT_Wattributes, + "category attributes are not available in this version" + " of the compiler, (ignored)"); objc_interface_context = start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos); objc_ivar_chain @@ -668,8 +678,12 @@ void } void -objc_start_protocol (tree name, tree protos) +objc_start_protocol (tree name, tree protos, tree attributes) { + if (attributes) + warning_at (input_location, OPT_Wattributes, + "protocol attributes are not available in this version" + " of the compiler, (ignored)"); objc_interface_context = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos); } Index: gcc/c-parser.c =================================================================== --- gcc/c-parser.c (revision 164686) +++ gcc/c-parser.c (working copy) @@ -977,11 +977,11 @@ static bool c_parser_pragma (c_parser *, enum prag /* These Objective-C parser functions are only ever called when compiling Objective-C. */ -static void c_parser_objc_class_definition (c_parser *); +static void c_parser_objc_class_definition (c_parser *, tree); static void c_parser_objc_class_instance_variables (c_parser *); static void c_parser_objc_class_declaration (c_parser *); static void c_parser_objc_alias_declaration (c_parser *); -static void c_parser_objc_protocol_definition (c_parser *); +static void c_parser_objc_protocol_definition (c_parser *, tree); static enum tree_code c_parser_objc_method_type (c_parser *); static void c_parser_objc_method_definition (c_parser *); static void c_parser_objc_methodprotolist (c_parser *); @@ -996,6 +996,8 @@ static tree c_parser_objc_selector_arg (c_parser * static tree c_parser_objc_receiver (c_parser *); static tree c_parser_objc_message_args (c_parser *); static tree c_parser_objc_keywordexpr (c_parser *); +static bool c_parser_objc_diagnose_bad_element_prefix + (c_parser *, struct c_declspecs *); /* Parse a translation unit (C90 6.7, C99 6.9). @@ -1079,7 +1081,7 @@ c_parser_external_declaration (c_parser *parser) case RID_AT_INTERFACE: case RID_AT_IMPLEMENTATION: gcc_assert (c_dialect_objc ()); - c_parser_objc_class_definition (parser); + c_parser_objc_class_definition (parser, NULL_TREE); break; case RID_CLASS: gcc_assert (c_dialect_objc ()); @@ -1091,7 +1093,7 @@ c_parser_external_declaration (c_parser *parser) break; case RID_AT_PROTOCOL: gcc_assert (c_dialect_objc ()); - c_parser_objc_protocol_definition (parser); + c_parser_objc_protocol_definition (parser, NULL_TREE); break; case RID_AT_END: gcc_assert (c_dialect_objc ()); @@ -1123,15 +1125,15 @@ c_parser_external_declaration (c_parser *parser) as a declaration or function definition. */ default: decl_or_fndef: - /* A declaration or a function definition. We can only tell - which after parsing the declaration specifiers, if any, and - the first declarator. */ + /* A declaration or a function definition (or, in Objective-C, + an @interface or @protocol with prefix attributes). We can + only tell which after parsing the declaration specifiers, if + any, and the first declarator. */ c_parser_declaration_or_fndef (parser, true, true, true, false, true); break; } } - /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -1173,6 +1175,11 @@ c_parser_external_declaration (c_parser *parser) declaration-specifiers declarator declaration-list[opt] compound-statement + Objective-C: + attributes objc-class-definition + attributes objc-category-definition + attributes objc-protocol-definition + The simple-asm-expr and attributes are GNU extensions. This function does not handle __extension__; that is handled in its @@ -1235,6 +1242,51 @@ c_parser_declaration_or_fndef (c_parser *parser, b c_parser_consume_token (parser); return; } + else if (c_dialect_objc ()) + { + /* This is where we parse 'attributes @interface ...', + 'attributes @implementation ...', 'attributes @protocol ...' + (where attributes could be, for example, __attribute__ + ((deprecated)). + */ + switch (c_parser_peek_token (parser)->keyword) + { + case RID_AT_INTERFACE: + { + if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) + return; + c_parser_objc_class_definition (parser, specs->attrs); + return; + } + break; + case RID_AT_IMPLEMENTATION: + { + if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) + return; + if (specs->attrs) + { + warning_at (c_parser_peek_token (parser)->location, + OPT_Wattributes, + "prefix attributes are ignored for implementations"); + specs->attrs = NULL_TREE; + } + c_parser_objc_class_definition (parser, NULL_TREE); + return; + } + break; + case RID_AT_PROTOCOL: + { + if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) + return; + c_parser_objc_protocol_definition (parser, specs->attrs); + return; + } + break; + default: + break; + } + } + pending_xref_error (); prefix_attrs = specs->attrs; all_prefix_attrs = prefix_attrs; @@ -6254,7 +6306,7 @@ c_parser_expr_list (c_parser *parser, bool convert objc-protocol-refs and objc-class-instance-variables are omitted. */ static void -c_parser_objc_class_definition (c_parser *parser) +c_parser_objc_class_definition (c_parser *parser, tree attributes) { bool iface_p; tree id1; @@ -6265,6 +6317,7 @@ static void iface_p = false; else gcc_unreachable (); + c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { @@ -6294,7 +6347,7 @@ static void } if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_start_category_interface (id1, id2, proto); + objc_start_category_interface (id1, id2, proto, attributes); c_parser_objc_methodprotolist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_finish_interface (); @@ -6318,7 +6371,7 @@ static void tree proto = NULL_TREE; if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_start_class_interface (id1, superclass, proto); + objc_start_class_interface (id1, superclass, proto, attributes); } else objc_start_class_implementation (id1, superclass); @@ -6498,9 +6551,10 @@ c_parser_objc_alias_declaration (c_parser *parser) omitted. */ static void -c_parser_objc_protocol_definition (c_parser *parser) +c_parser_objc_protocol_definition (c_parser *parser, tree attributes) { gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL)); + c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { @@ -6540,7 +6594,7 @@ static void if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); parser->objc_pq_context = true; - objc_start_protocol (id, proto); + objc_start_protocol (id, proto, attributes); c_parser_objc_methodprotolist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); parser->objc_pq_context = false; @@ -7129,6 +7183,21 @@ c_parser_objc_keywordexpr (c_parser *parser) return ret; } +/* A check, needed in several places, that ObjC interface, implementation or + method definitions are not prefixed by incorrect items. */ +static bool +c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, + struct c_declspecs *specs) +{ + if (!specs->declspecs_seen_p || specs->type_seen_p || specs->non_sc_seen_p) + { + c_parser_error (parser, + "no type or storage class may be specified here,"); + c_parser_skip_to_end_of_block_or_statement (parser); + return true; + } + return false; +} /* Handle pragmas. Some OpenMP pragmas are associated with, and therefore