Patchwork ObjC/ObjC++ - finish implementation of Objective-C 2.0 @protocol attributes

login
register
mail settings
Submitter Nicola Pero
Date Nov. 18, 2010, 10:27 p.m.
Message ID <1290119234.487119290@192.168.4.58>
Download mbox | patch
Permalink /patch/72160/
State New
Headers show

Comments

Nicola Pero - Nov. 18, 2010, 10:27 p.m.
A revised patch that fixes a small ingenuity in the original patch.

Ok to commit ?

Thanks

-----Original Message-----
From: "Nicola Pero" <nicola.pero@meta-innovation.com>
Sent: Thursday, 18 November, 2010 20:51
To: "gcc-patches@gnu.org" <gcc-patches@gnu.org>
Subject: ObjC/ObjC++ - finish implementation of Objective-C 2.0 @protocol attributes

This patch completes the implementation of @protocol attributes so that 
the compiler not only parses them, but actually implements them (the only one 
that is actually implemented is the 'deprecated' attribute, which is the only 
one actually available with @protocol).

In particular this patch:

 * makes sure we do not throw away the attributes parsed with a @protocol forward 
declaration (as in  "__attribute__ ((deprecated)) @protocol MyProtocol;") but we 
pass them to the ObjC compiler (this bit was missing);

 * attaches the attributes to the protocol and marks it with TREE_DEPRECATED if 
appropriate (both for normal and forward declarations of protocols)

 * modifies lookup_protocol() to emit a deprecation warning if requested;

 * changes all callers of lookup_protocol() to request (or not, as appropriate to 
the case) a deprecation warning if the protocol being looked up turns out to be 
deprecated;

 * and, finally, removes the warnings that protocol attributes are not 
implemented in this version of the compiler, since they now are implemented. :-)

I updated the existing 2 testcases, and added another 4 testcases for Objective-C 
and Objective-C++, covering all the cases I could think of.  It all seems to work. :-)

Ok to commit to trunk ?

Thanks

n gcc/:
2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * c-parser.c (c_parser_objc_protocol_definition): Pass attributes
        to objc_declare_protocols.

In gcc/c-family/:
2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * c-common.h (objc_declare_protocols): Added additional argument.
        * stub-objc.c (objc_declare_protocol): Same change.

In gcc/cp/:
2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * parser.c (cp_parser_objc_protocol_declaration): Pass attributes
        to objc_declare_protocols.

In gcc/objc/:
2010-11-18  Nicola Pero  <nicola@nicola.brainstorm.co.uk>

        * objc-act.c (lookup_protocol): Added 'warn_if_deprecated'
        argument.  If it is 'true' and the protocol is deprecated, emit a
        deprecation warning.
        (objc_start_protocol): Do not warn that protocol attributes are
        unimplemented.  Pass the attributes to start_protocol.
	(start_protocol): Added attributes argument.  Recognize the
	'deprecated' attribute and mark the protocols with TREE_DEPRECATED
	if present.  Store attributes in the protocol.
	(objc_declare_protocols): Added 'attributes' argument.  Recognize
	the 'deprecated' attribute and mark the protocols with
	TREE_DEPRECATED if present.  Store attributes in the protocol.
	Updated call to lookup_protocol.
	(objc_build_protocol_expr): Updated call to lookup_protocol.
	(check_protocol_recursively): Same change.
	(lookup_and_install_protocols): Same change.
        * objc-act.h: Updated comments.

In gcc/testsuite/:
2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc.dg/attributes/proto-attribute-1.m: Updated.
        * objc.dg/attributes/proto-attribute-2.m: New.
        * objc.dg/attributes/proto-attribute-3.m: New.
        * obj-c++.dg/attributes/proto-attribute-1.mm: Updated.
	* obj-c++.dg/attributes/proto-attribute-2.mm: New.
        * obj-c++.dg/attributes/proto-attribute-3.mm: New.
Mike Stump - Nov. 19, 2010, 12:55 a.m.
On Nov 18, 2010, at 2:27 PM, Nicola Pero wrote:
> A revised patch that fixes a small ingenuity in the original patch.
> 
> Ok to commit ?

Ok.  Patch to update the release notes pre-approved.

Patch

Index: c-family/ChangeLog
===================================================================
--- c-family/ChangeLog	(revision 166902)
+++ c-family/ChangeLog	(working copy)
@@ -1,3 +1,8 @@ 
+2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* c-common.h (objc_declare_protocols): Added additional argument.
+	* stub-objc.c (objc_declare_protocol): Same change.
+	
 2010-11-17  Joseph Myers  <joseph@codesourcery.com>
 
 	* c-opts.c (c_common_parse_file): Take no arguments.
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h	(revision 166902)
+++ c-family/c-common.h	(working copy)
@@ -995,7 +995,7 @@  extern int objc_is_public (tree, tree);
 extern tree objc_is_id (tree);
 extern void objc_declare_alias (tree, tree);
 extern void objc_declare_class (tree);
-extern void objc_declare_protocols (tree);
+extern void objc_declare_protocols (tree, tree);
 extern tree objc_build_message_expr (tree);
 extern tree objc_finish_message_expr (tree, tree, tree);
 extern tree objc_build_selector_expr (location_t, tree);
Index: c-family/stub-objc.c
===================================================================
--- c-family/stub-objc.c	(revision 166902)
+++ c-family/stub-objc.c	(working copy)
@@ -126,7 +126,7 @@  objc_declare_class (tree ARG_UNUSED (lis
 }
 
 void
-objc_declare_protocols (tree ARG_UNUSED (list))
+objc_declare_protocols (tree ARG_UNUSED (list), tree ARG_UNUSED (attributes))
 {
 }
 
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 166908)
+++ objc/objc-act.c	(working copy)
@@ -153,7 +153,7 @@  static void objc_start_function (tree, t
 #else
 static void objc_start_function (tree, tree, tree, struct c_arg_info *);
 #endif
-static tree start_protocol (enum tree_code, tree, tree);
+static tree start_protocol (enum tree_code, tree, tree, tree);
 static tree build_method_decl (enum tree_code, tree, tree, tree, bool);
 static tree objc_add_method (tree, tree, int, bool);
 static tree add_instance_variable (tree, objc_ivar_visibility_kind, tree);
@@ -234,9 +234,9 @@  enum string_section
 static tree add_objc_string (tree, enum string_section);
 static void build_selector_table_decl (void);
 
-/* Protocol additions.  */
+/* Protocols.  */
 
-static tree lookup_protocol (tree);
+static tree lookup_protocol (tree, bool);
 static tree lookup_and_install_protocols (tree);
 
 /* Type encoding.  */
@@ -767,17 +767,11 @@  objc_start_category_interface (tree klas
 void
 objc_start_protocol (tree name, tree protos, tree attributes)
 {
-  if (attributes)
-    {
-      if (flag_objc1_only)
-	error_at (input_location, "protocol attributes are not available in Objective-C 1.0");	
-      else
-	warning_at (input_location, OPT_Wattributes, 
-		    "protocol attributes are not available in this version"
-		    " of the compiler, (ignored)");
-    }
+  if (flag_objc1_only && attributes)
+    error_at (input_location, "protocol attributes are not available in Objective-C 1.0");	
+
   objc_interface_context
-    = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos);
+    = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos, attributes);
   objc_method_optional_flag = false;
 }
 
@@ -2866,7 +2860,7 @@  check_protocol_recursively (tree proto, 
       tree pp = TREE_VALUE (p);
 
       if (TREE_CODE (pp) == IDENTIFIER_NODE)
-	pp = lookup_protocol (pp);
+	pp = lookup_protocol (pp, /* warn if deprecated */ false);
 
       if (pp == proto)
 	fatal_error ("protocol %qE has circular dependency",
@@ -2876,8 +2870,9 @@  check_protocol_recursively (tree proto, 
     }
 }
 
-/* Look up PROTOCOLS, and return a list of those that are found.
-   If none are found, return NULL.  */
+/* Look up PROTOCOLS, and return a list of those that are found.  If
+   none are found, return NULL.  Note that this function will emit a
+   warning if a protocol is found and is deprecated.  */
 
 static tree
 lookup_and_install_protocols (tree protocols)
@@ -2891,7 +2886,7 @@  lookup_and_install_protocols (tree proto
   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
     {
       tree ident = TREE_VALUE (proto);
-      tree p = lookup_protocol (ident);
+      tree p = lookup_protocol (ident, /* warn_if_deprecated */ true);
 
       if (p)
 	return_value = chainon (return_value,
@@ -8237,7 +8232,7 @@  tree
 objc_build_protocol_expr (tree protoname)
 {
   tree expr;
-  tree p = lookup_protocol (protoname);
+  tree p = lookup_protocol (protoname, /* warn if deprecated */ true);
 
   if (!p)
     {
@@ -10544,14 +10539,28 @@  add_protocol (tree protocol)
   return protocol_chain;
 }
 
+/* Looks up a protocol.  If 'warn_if_deprecated' is true, a warning is
+   emitted if the protocol is deprecated.  */
+
 static tree
-lookup_protocol (tree ident)
+lookup_protocol (tree ident, bool warn_if_deprecated)
 {
   tree chain;
 
   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
     if (ident == PROTOCOL_NAME (chain))
-      return chain;
+      {
+	if (warn_if_deprecated && TREE_DEPRECATED (chain))
+	  {
+	    /* It would be nice to use warn_deprecated_use() here, but
+	       we are using TREE_CHAIN (which is supposed to be the
+	       TYPE_STUB_DECL for a TYPE) for something different.  */
+	    warning (OPT_Wdeprecated_declarations, "protocol %qE is deprecated", 
+		     PROTOCOL_NAME (chain));
+	  }
+
+	return chain;
+      }
 
   return NULL_TREE;
 }
@@ -10560,9 +10569,10 @@  lookup_protocol (tree ident)
    they are already declared or defined, the function has no effect.  */
 
 void
-objc_declare_protocols (tree names)
+objc_declare_protocols (tree names, tree attributes)
 {
   tree list;
+  bool deprecated = false;
 
 #ifdef OBJCPLUS
   if (current_namespace != global_namespace) {
@@ -10570,11 +10580,25 @@  objc_declare_protocols (tree names)
   }
 #endif /* OBJCPLUS */
 
+  /* Determine if 'deprecated', the only attribute we recognize for
+     protocols, was used.  Ignore all other attributes.  */
+  if (attributes)
+    {
+      tree attribute;
+      for (attribute = attributes; attribute; attribute = TREE_CHAIN (attribute))
+	{
+	  tree name = TREE_PURPOSE (attribute);
+	  
+	  if (is_attribute_p  ("deprecated", name))
+	    deprecated = true;
+	}
+    }
+
   for (list = names; list; list = TREE_CHAIN (list))
     {
       tree name = TREE_VALUE (list);
 
-      if (lookup_protocol (name) == NULL_TREE)
+      if (lookup_protocol (name, /* warn if deprecated */ false) == NULL_TREE)
 	{
 	  tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
 
@@ -10585,14 +10609,22 @@  objc_declare_protocols (tree names)
 	  add_protocol (protocol);
 	  PROTOCOL_DEFINED (protocol) = 0;
 	  PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+	  
+	  if (attributes)
+	    {
+	      TYPE_ATTRIBUTES (protocol) = attributes;
+	      if (deprecated)
+		TREE_DEPRECATED (protocol) = 1;
+	    }
 	}
     }
 }
 
 static tree
-start_protocol (enum tree_code code, tree name, tree list)
+start_protocol (enum tree_code code, tree name, tree list, tree attributes)
 {
   tree protocol;
+  bool deprecated = false;
 
 #ifdef OBJCPLUS
   if (current_namespace != global_namespace) {
@@ -10600,7 +10632,21 @@  start_protocol (enum tree_code code, tre
   }
 #endif /* OBJCPLUS */
 
-  protocol = lookup_protocol (name);
+  /* Determine if 'deprecated', the only attribute we recognize for
+     protocols, was used.  Ignore all other attributes.  */
+  if (attributes)
+    {
+      tree attribute;
+      for (attribute = attributes; attribute; attribute = TREE_CHAIN (attribute))
+	{
+	  tree name = TREE_PURPOSE (attribute);
+	  
+	  if (is_attribute_p  ("deprecated", name))
+	    deprecated = true;
+	}
+    }
+
+  protocol = lookup_protocol (name, /* warn_if_deprecated */ false);
 
   if (!protocol)
     {
@@ -10627,6 +10673,14 @@  start_protocol (enum tree_code code, tre
       warning (0, "duplicate declaration for protocol %qE",
 	       name);
     }
+
+  if (attributes)
+    {
+      TYPE_ATTRIBUTES (protocol) = attributes;
+      if (deprecated)
+	TREE_DEPRECATED (protocol) = 1;
+    }
+
   return protocol;
 }
 
Index: objc/ChangeLog
===================================================================
--- objc/ChangeLog	(revision 166908)
+++ objc/ChangeLog	(working copy)
@@ -1,3 +1,22 @@ 
+2010-11-18  Nicola Pero  <nicola@nicola.brainstorm.co.uk>
+
+	* objc-act.c (lookup_protocol): Added 'warn_if_deprecated'
+	argument.  If it is 'true' and the protocol is deprecated, emit a
+	deprecation warning.
+	(objc_start_protocol): Do not warn that protocol attributes are
+	unimplemented.  Pass the attributes to start_protocol.
+	(start_protocol): Added attributes argument.  Recognize the
+	'deprecated' attribute and mark the protocols with TREE_DEPRECATED
+	if present.  Store attributes in the protocol.
+	(objc_declare_protocols): Added 'attributes' argument.  Recognize
+	the 'deprecated' attribute and mark the protocols with
+	TREE_DEPRECATED if present.  Store attributes in the protocol.
+	Updated call to lookup_protocol.
+	(objc_build_protocol_expr): Updated call to lookup_protocol.
+	(check_protocol_recursively): Same change.
+	(lookup_and_install_protocols): Same change.
+	* objc-act.h: Updated comments.
+	
 2010-11-17  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc-act.c (lookup_method_in_protocol_list): Search methods in
Index: objc/objc-act.h
===================================================================
--- objc/objc-act.h	(revision 166908)
+++ objc/objc-act.h	(working copy)
@@ -166,11 +166,16 @@  typedef enum objc_property_assign_semant
 #define PROTOCOL_OPTIONAL_CLS_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2)
 #define PROTOCOL_OPTIONAL_NST_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 3)
 
+
 /* For CATEGORY_INTERFACE_TYPE, CLASS_INTERFACE_TYPE or PROTOCOL_INTERFACE_TYPE */
 #define CLASS_PROPERTY_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 6)
 /* For CLASS_IMPLEMENTATION_TYPE or CATEGORY_IMPLEMENTATION_TYPE. */
 #define IMPL_PROPERTY_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 6)
 
+/* TREE_DEPRECATED is used for a CLASS_INTERFACE_TYPE or PROTOCOL_INTERFACE_TYPE.  */
+
+/* TYPE_ATTRIBUTES is used for a CLASS_INTERFACE_TYPE or PROTOCOL_INTERFACE_TYPE.  */
+
 /* ObjC-specific information pertaining to RECORD_TYPEs are stored in
    the LANG_SPECIFIC structures, which may itself need allocating first.  */
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 166902)
+++ ChangeLog	(working copy)
@@ -1,3 +1,8 @@ 
+2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* c-parser.c (c_parser_objc_protocol_definition): Pass attributes
+	to objc_declare_protocols.
+
 2010-11-18  Richard Guenther  <rguenther@suse.de>
 
 	PR lto/46525
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 166902)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,12 @@ 
+2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc.dg/attributes/proto-attribute-1.m: Updated.
+	* objc.dg/attributes/proto-attribute-2.m: New.
+	* objc.dg/attributes/proto-attribute-3.m: New.
+	* obj-c++.dg/attributes/proto-attribute-1.mm: Updated.
+	* obj-c++.dg/attributes/proto-attribute-2.mm: New.
+	* obj-c++.dg/attributes/proto-attribute-3.mm: New.	
+	
 2010-11-17  Steve Ellcey  <sje@cup.hp.com>
 
 	PR middle-end/31490
Index: testsuite/objc.dg/attributes/proto-attribute-1.m
===================================================================
--- testsuite/objc.dg/attributes/proto-attribute-1.m	(revision 166902)
+++ testsuite/objc.dg/attributes/proto-attribute-1.m	(working copy)
@@ -1,14 +1,13 @@ 
 /* { 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" } */
+- (int) depprotomth;
 @end
 
-@interface obj : Object <dep_proto>
+@interface obj <dep_proto> /* { dg-warning "is deprecated" } */
 { 
 @public 
   int var; 
@@ -20,10 +19,3 @@  __attribute ((deprecated)) 
 - (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: testsuite/objc.dg/attributes/proto-attribute-2.m
===================================================================
--- testsuite/objc.dg/attributes/proto-attribute-2.m	(revision 0)
+++ testsuite/objc.dg/attributes/proto-attribute-2.m	(revision 0)
@@ -0,0 +1,45 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test deprecate attribute with a forward declarations of
+   @protocol.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+__attribute__ ((deprecated))
+@protocol DeprecatedProtocol1;
+
+@protocol NonDeprecatedProtocol1;
+
+
+@interface Class1 <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 <NonDeprecatedProtocol1>
+@end
+
+@interface Class3 <NonDeprecatedProtocol1, DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 (Category1) <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+void function1 (id <DeprecatedProtocol1> object); /* { dg-warning "is deprecated" } */
+void function2 (id <NonDeprecatedProtocol1> object);
+
+@class Class4;
+
+void function3 (Class4 <DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+void function4 (Class4 <NonDeprecatedProtocol1> *object);
+void function5 (Class4 <NonDeprecatedProtocol1, DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+
+int function6 (void)
+{
+  Protocol *p1 = @protocol (DeprecatedProtocol1); /* { dg-warning "is deprecated" } */
+  Protocol *p2 = @protocol (NonDeprecatedProtocol1);
+
+  return (p1 == p2);
+}
+
Index: testsuite/objc.dg/attributes/proto-attribute-3.m
===================================================================
--- testsuite/objc.dg/attributes/proto-attribute-3.m	(revision 0)
+++ testsuite/objc.dg/attributes/proto-attribute-3.m	(revision 0)
@@ -0,0 +1,60 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test deprecate attribute with normal @protocol declarations.  */
+
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+__attribute__ ((deprecated))
+@protocol DeprecatedProtocol1
+- (void) aMethod;
+@end
+
+@protocol NonDeprecatedProtocol1
+- (void) anotherMethod;
+@end
+
+@protocol Protocol2 <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+- (void) someOtherMethod;
+@end
+
+@protocol Protocol3 <NonDeprecatedProtocol1>
+- (void) someOtherMethod2;
+@end
+
+@protocol Protocol4 <NonDeprecatedProtocol1, DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+- (void) someOtherMethod3;
+@end
+
+
+@interface Class1 <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 <NonDeprecatedProtocol1>
+@end
+
+@interface Class3 <NonDeprecatedProtocol1, DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 (Category1) <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+void function1 (id <DeprecatedProtocol1> object); /* { dg-warning "is deprecated" } */
+void function2 (id <NonDeprecatedProtocol1> object);
+
+@class Class4;
+
+void function3 (Class4 <DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+void function4 (Class4 <NonDeprecatedProtocol1> *object);
+void function5 (Class4 <NonDeprecatedProtocol1, DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+
+int function6 (void)
+{
+  Protocol *p1 = @protocol (DeprecatedProtocol1); /* { dg-warning "is deprecated" } */
+  Protocol *p2 = @protocol (NonDeprecatedProtocol1);
+
+  return (p1 == p2);
+}
Index: testsuite/obj-c++.dg/attributes/proto-attribute-1.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/proto-attribute-1.mm	(revision 166902)
+++ testsuite/obj-c++.dg/attributes/proto-attribute-1.mm	(working copy)
@@ -1,14 +1,13 @@ 
 /* { 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; 
+@protocol dep_proto 
+- (int) depprotomth;
 @end
 
-@interface obj : Object <dep_proto>
+@interface obj <dep_proto> /* { dg-warning "is deprecated" } */
 { 
 @public 
   int var; 
@@ -20,10 +19,3 @@  __attribute ((deprecated)) 
 - (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: testsuite/obj-c++.dg/attributes/proto-attribute-2.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/proto-attribute-2.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/proto-attribute-2.mm	(revision 0)
@@ -0,0 +1,45 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test deprecate attribute with a forward declarations of
+   @protocol.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+__attribute__ ((deprecated))
+@protocol DeprecatedProtocol1;
+
+@protocol NonDeprecatedProtocol1;
+
+
+@interface Class1 <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 <NonDeprecatedProtocol1>
+@end
+
+@interface Class3 <NonDeprecatedProtocol1, DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 (Category1) <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+void function1 (id <DeprecatedProtocol1> object); /* { dg-warning "is deprecated" } */
+void function2 (id <NonDeprecatedProtocol1> object);
+
+@class Class4;
+
+void function3 (Class4 <DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+void function4 (Class4 <NonDeprecatedProtocol1> *object);
+void function5 (Class4 <NonDeprecatedProtocol1, DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+
+int function6 (void)
+{
+  Protocol *p1 = @protocol (DeprecatedProtocol1); /* { dg-warning "is deprecated" } */
+  Protocol *p2 = @protocol (NonDeprecatedProtocol1);
+
+  return (p1 == p2);
+}
+
Index: testsuite/obj-c++.dg/attributes/proto-attribute-3.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/proto-attribute-3.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/proto-attribute-3.mm	(revision 0)
@@ -0,0 +1,60 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test deprecate attribute with normal @protocol declarations.  */
+
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+__attribute__ ((deprecated))
+@protocol DeprecatedProtocol1
+- (void) aMethod;
+@end
+
+@protocol NonDeprecatedProtocol1
+- (void) anotherMethod;
+@end
+
+@protocol Protocol2 <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+- (void) someOtherMethod;
+@end
+
+@protocol Protocol3 <NonDeprecatedProtocol1>
+- (void) someOtherMethod2;
+@end
+
+@protocol Protocol4 <NonDeprecatedProtocol1, DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+- (void) someOtherMethod3;
+@end
+
+
+@interface Class1 <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 <NonDeprecatedProtocol1>
+@end
+
+@interface Class3 <NonDeprecatedProtocol1, DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+@interface Class2 (Category1) <DeprecatedProtocol1> /* { dg-warning "is deprecated" } */
+@end
+
+void function1 (id <DeprecatedProtocol1> object); /* { dg-warning "is deprecated" } */
+void function2 (id <NonDeprecatedProtocol1> object);
+
+@class Class4;
+
+void function3 (Class4 <DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+void function4 (Class4 <NonDeprecatedProtocol1> *object);
+void function5 (Class4 <NonDeprecatedProtocol1, DeprecatedProtocol1> *object); /* { dg-warning "is deprecated" } */
+
+int function6 (void)
+{
+  Protocol *p1 = @protocol (DeprecatedProtocol1); /* { dg-warning "is deprecated" } */
+  Protocol *p2 = @protocol (NonDeprecatedProtocol1);
+
+  return (p1 == p2);
+}
Index: cp/ChangeLog
===================================================================
--- cp/ChangeLog	(revision 166902)
+++ cp/ChangeLog	(working copy)
@@ -1,3 +1,8 @@ 
+2010-11-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* parser.c (cp_parser_objc_protocol_declaration): Pass attributes
+	to objc_declare_protocols.
+
 2010-11-16  Jason Merrill  <jason@redhat.com>
 
 	* call.c (convert_like_real): Don't make a temp for copy-list-init.
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 166902)
+++ cp/parser.c	(working copy)
@@ -22314,7 +22314,8 @@  cp_parser_objc_protocol_declaration (cp_
   /* Try a forward declaration first.  */
   if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
     {
-      objc_declare_protocols (cp_parser_objc_identifier_list (parser));
+      objc_declare_protocols (cp_parser_objc_identifier_list (parser), 
+			      attributes);
      finish:
       cp_parser_consume_semicolon_at_end_of_statement (parser);
     }
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 166902)
+++ c-parser.c	(working copy)
@@ -7046,7 +7046,7 @@  c_parser_objc_protocol_definition (c_par
 	    break;
 	}
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-      objc_declare_protocols (list);
+      objc_declare_protocols (list, attributes);
     }
   else
     {