Patchwork ObjC / ObjC++: fix implementation of @optional in @protocol

login
register
mail settings
Submitter Nicola Pero
Date Nov. 16, 2010, 1:18 a.m.
Message ID <1289870322.206819907@192.168.2.228>
Download mbox | patch
Permalink /patch/71326/
State New
Headers show

Comments

Nicola Pero - Nov. 16, 2010, 1:18 a.m.
This patch adds a couple of testcases for the usage of @optional in @protocol
(another new syntax allowed in "Objective-C 2.0" that is now available in GCC)
and fixes/completes the implementation so that the testcases actually work :-)

Ok to commit to trunk ?

Thanks

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

        * objc-act.c (lookup_method_in_protocol_list): Search methods in
        PROTOCOL_OPTIONAL_CLS_METHODS / PROTOCOL_OPTIONAL_NST_METHODS if
        they are not found in PROTOCOL_CLS_METHODS / PROTOCOL_NST_METHODS.

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

        * objc.dg/protocol-optional-1.m: New.
        * obj-c++.dg/protocol-optional-1.mm: New.
Mike Stump - Nov. 16, 2010, 4:38 p.m.
On Nov 15, 2010, at 5:18 PM, Nicola Pero wrote:
> This patch adds a couple of testcases for the usage of @optional in @protocol
> (another new syntax allowed in "Objective-C 2.0" that is now available in GCC)
> and fixes/completes the implementation so that the testcases actually work :-)
> 
> Ok to commit to trunk ?

Ok.

Patch

Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 166779)
+++ objc/objc-act.c	(working copy)
@@ -649,30 +649,44 @@  static tree
 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
 				int is_class)
 {
-   tree rproto, p;
-   tree fnd = 0;
+  tree rproto, p, m;
 
    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
      {
-        p = TREE_VALUE (rproto);
+       p = TREE_VALUE (rproto);
+       m = NULL_TREE;
 
 	if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
 	  {
-	    if ((fnd = lookup_method (is_class
-				      ? PROTOCOL_CLS_METHODS (p)
-				      : PROTOCOL_NST_METHODS (p), sel_name)))
-	      ;
-	    else if (PROTOCOL_LIST (p))
-	      fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
-						    sel_name, is_class);
+	    /* First, search the @required protocol methods.  */
+	    if (is_class)
+	      m = lookup_method (PROTOCOL_CLS_METHODS (p),  sel_name);
+	    else
+	      m = lookup_method (PROTOCOL_NST_METHODS (p), sel_name);
+
+	    if (m)
+	      return m;
+
+	    /* If still not found, search the @optional protocol methods.  */
+	    if (is_class)
+	      m = lookup_method (PROTOCOL_OPTIONAL_CLS_METHODS (p), sel_name);
+	    else
+	      m = lookup_method (PROTOCOL_OPTIONAL_NST_METHODS (p), sel_name);
+
+	    if (m)
+	      return m;
+
+	    /* If still not found, search the attached protocols.  */
+	    if (PROTOCOL_LIST (p))
+	      m = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
+						  sel_name, is_class);
+	    if (m)
+	      return m;
 	  }
 	else
           {
 	    ; /* An identifier...if we could not find a protocol.  */
           }
-
-	if (fnd)
-	  return fnd;
      }
 
    return 0;
@@ -8642,7 +8656,10 @@  objc_add_method (tree klass, tree method, int is_c
 {
   tree mth;
 
-  /* @optional methods are added to protocol's OPTIONAL list */
+  /* @optional methods are added to protocol's OPTIONAL list.  Note
+     that this disables checking that the methods are implemented by
+     classes implementing the protocol, since these checks only use
+     the CLASS_CLS_METHODS and CLASS_NST_METHODS.  */
   if (is_optional)
     {
       gcc_assert (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE);
Index: objc/ChangeLog
===================================================================
--- objc/ChangeLog	(revision 166779)
+++ objc/ChangeLog	(working copy)
@@ -1,3 +1,9 @@ 
+2010-11-16  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc-act.c (lookup_method_in_protocol_list): Search methods in
+	PROTOCOL_OPTIONAL_CLS_METHODS / PROTOCOL_OPTIONAL_NST_METHODS if
+	they are not found in PROTOCOL_CLS_METHODS / PROTOCOL_NST_METHODS.
+
 2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc-act.c (objc_build_setter_call): New.
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 166779)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,8 @@ 
+2010-11-16  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc.dg/protocol-optional-1.m: New.
+	* obj-c++.dg/protocol-optional-1.mm: New.
+
 2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc.dg/property/dotsyntax-18.m: New.
Index: testsuite/objc.dg/protocol-optional-1.m
===================================================================
--- testsuite/objc.dg/protocol-optional-1.m	(revision 0)
+++ testsuite/objc.dg/protocol-optional-1.m	(revision 0)
@@ -0,0 +1,48 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that @optional for @protocol works.  */
+
+@protocol MyProtocol
++ (int)classMethod;
+- (int)method;
+@optional
++ (int)optionalClassMethod;
+- (int)optionalMethod;
+@end
+
+@interface MyRootClass <MyProtocol>
+@end
+
+/* The implementation implements both the @required methods, but none
+   of the @optional ones.  There should be no warnings as the
+   @optional methods are optional. ;-)  */
+@implementation MyRootClass
++ (int)classMethod
+{
+  return 20;
+}
+- (int)method
+{
+  return 11;
+}
+@end
+
+int function (id <MyProtocol> object1,
+	      MyRootClass *object2)
+{
+  /* Test that there are no warnings if you try to use an @optional
+     method with an object of the class.  */
+  int i = 0;
+
+  i += [object1 method];
+  i += [object2 method];
+  i += [MyRootClass classMethod];
+  i += [object1 optionalMethod];
+  i += [object2 optionalMethod];
+  i += [MyRootClass optionalClassMethod];
+
+  return i;
+}
Index: testsuite/obj-c++.dg/protocol-optional-1.mm
===================================================================
--- testsuite/obj-c++.dg/protocol-optional-1.mm	(revision 0)
+++ testsuite/obj-c++.dg/protocol-optional-1.mm	(revision 0)
@@ -0,0 +1,48 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that @optional for @protocol works.  */
+
+@protocol MyProtocol
++ (int)classMethod;
+- (int)method;
+@optional
++ (int)optionalClassMethod;
+- (int)optionalMethod;
+@end
+
+@interface MyRootClass <MyProtocol>
+@end
+
+/* The implementation implements both the @required methods, but none
+   of the @optional ones.  There should be no warnings as the
+   @optional methods are optional. ;-)  */
+@implementation MyRootClass
++ (int)classMethod
+{
+  return 20;
+}
+- (int)method
+{
+  return 11;
+}
+@end
+
+int function (id <MyProtocol> object1,
+	      MyRootClass *object2)
+{
+  /* Test that there are no warnings if you try to use an @optional
+     method with an object of the class.  */
+  int i = 0;
+
+  i += [object1 method];
+  i += [object2 method];
+  i += [MyRootClass classMethod];
+  i += [object1 optionalMethod];
+  i += [object2 optionalMethod];
+  i += [MyRootClass optionalClassMethod];
+
+  return i;
+}