diff mbox

[ObjC/C++,V2,Part1] Recognize attributes on class, category and protocol declarations.

Message ID D3505534-4D0D-4485-B0A3-E737163E3FEB@sandoe-acoustics.co.uk
State New
Headers show

Commit Message

Iain Sandoe Sept. 28, 2010, 5:07 p.m. UTC
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 <objc/objc.h>
+#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 <objc/objc.h>
+#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
+# <http://www.gnu.org/licenses/>.
+
+# 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 <objc/objc.h>
+#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 <objc/objc.h>
+#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 <dep_proto>
+{ 
+@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 <objc/objc.h>
+#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
+# <http://www.gnu.org/licenses/>.
+
+# 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 <objc/objc.h>
+#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 <objc/objc.h>
+#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 <dep_proto>
+{ 
+@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 <objc/objc.h>
+#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 <objc/objc.h>
+#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 <objc/objc.h>
+#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];    
+}

Comments

Mike Stump Sept. 28, 2010, 5:23 p.m. UTC | #1
On Sep 28, 2010, at 10:07 AM, IainS wrote:
> OK for trunk?

Ok.
Nicola Pero Sept. 28, 2010, 6:18 p.m. UTC | #2
Great patch. :-)

So, you did add attributes to categories in the end, as we discussed ;-)

I think it will be a really useful extension to be able to mark an entire category
as deprecated, and have that automatically deprecate all methods in the category. :-)

The Apple compiler does not support that, but I think we should - it's an obvious extension.

Thanks

-----Original Message-----
From: "IainS" <developer@sandoe-acoustics.co.uk>
Sent: Tuesday, 28 September, 2010 19:07
To: "Mike Stump" <mrs@gcc.gnu.org>
Cc: "GCC Patches" <gcc-patches@gcc.gnu.org>, "Joseph S. Myers" <joseph@codesourcery.com>, "Jason Merrill" <jason@redhat.com>, "Nicola Pero" <nicola.pero@meta-innovation.com>
Subject: Re: [Patch, ObjC/C++ V2, Part1] Recognize attributes on class, category and protocol declarations.

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.
>



> 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
Iain Sandoe Sept. 28, 2010, 6:40 p.m. UTC | #3
On 28 Sep 2010, at 19:18, Nicola Pero wrote:
>
> So, you did add attributes to categories in the end, as we  
> discussed ;-)

detecting them to flag an error is no harder than adding them -- of  
course making use of that within obc-act.c is a bigger job.

> I think it will be a really useful extension to be able to mark an  
> entire category
> as deprecated, and have that automatically deprecate all methods in  
> the category. :-)

welll.... we've got all that to do - since there's no class/categ/ 
proto implementation in the apple-branch - so we might as well make  
the extension at the same time

====

As observed before, we need fairly soon to identify the tags by which  
various capabilities are to be discriminated.

I am conscious that the current patch does not exactly mirror what  
apple-4.2 gives as messages
- but I would like to re-visit this once we get:

(a) basic functionality with NeXT on Darwin>=9.
(b) an agreed set of   -objc-std= apple_xxxx ,  gnu_yyyy defined.

(maybe it should be -objc-lang= since it's not a 'standard' as such)

===

I want to sort out a couple more key merges/additions in a bid to make  
4.6 compile NeXT m32 on darwin 9 & 10.

Hopefully, we can iron out message wording (or even commuting warnings  
-> errors for different -objc-lang= ) in slower time.

It shouldn't be too hard to make a list of the apple_xxxx - since  
there are release notes for each XCode rev.
I'm less clear about how one would identify the gnu equivalent  -  
perhaps also by gcc releases?

I'll try and get it applied later/tomorrow morning.

Iain
diff mbox

Patch

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