Patchwork =?UTF-8?Q?libobjc:=20clarify=20behaviour=20of=20class=5FconformsToProtoc?= =?UTF-8?Q?ol()?=

login
register
mail settings
Submitter Nicola Pero
Date Dec. 24, 2010, 3:32 p.m.
Message ID <1293204766.92369606@192.168.2.228>
Download mbox | patch
Permalink /patch/76631/
State New
Headers show

Comments

Nicola Pero - Dec. 24, 2010, 3:32 p.m.
This patch documents clearly the behaviour of class_conformsToProtocol() with respect to superclasses.  Our current implementation behaves identically to the 
Apple runtime and only tests the class but not the superclasses.

Committed to trunk.

Thanks

PS: I wonder if it is worth running the GNU Objective-C runtime API tests with the 
Apple runtime as well.  The purpose wouldn't be to test the Apple runtime; it would
rather be to test that the testcase are correct and that the behaviour they require
from the runtime API is indeed the one of the Apple runtime.  Then, if someone makes
a change to the GNU runtime API making it incompatible with the Apple one, and adds
a testcase for it (assuming all changes come with a testcase), they would notice 
when the test runs on the Apple runtime, as it would fail there.

There are cases where we want or need to differ in behaviour; but these should not
be the norm.  They should be rare, well-documented and thought-of exceptions, where 
we can add an #ifdef in the tests.
IainS - Dec. 24, 2010, 3:49 p.m.
On 24 Dec 2010, at 15:32, Nicola Pero wrote:
>
> PS: I wonder if it is worth running the GNU Objective-C runtime API  
> tests with the
> Apple runtime as well.  The purpose wouldn't be to test the Apple  
> runtime; it would
> rather be to test that the testcase are correct and that the  
> behaviour they require
> from the runtime API is indeed the one of the Apple runtime.  Then,  
> if someone makes
> a change to the GNU runtime API making it incompatible with the  
> Apple one, and adds
> a testcase for it (assuming all changes come with a testcase), they  
> would notice
> when the test runs on the Apple runtime, as it would fail there.

seems like a good idea...
... shouldn't be too hard to arrange .. maybe give it a spin after Xmas.
cheers
Iain

Patch

Index: libobjc/ChangeLog
===================================================================
--- libobjc/ChangeLog   (revision 168215)
+++ libobjc/ChangeLog   (working copy)
@@ -1,3 +1,8 @@ 
+2010-12-24  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc/runtime.h (class_conformsToProtocol,
+       class_copyProtocolList): Updated documentation.
+
 2010-12-23  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * init.c (create_tree_of_subclasses_inherited_from): Updated
Index: libobjc/objc/runtime.h
===================================================================
--- libobjc/objc/runtime.h      (revision 168215)
+++ libobjc/objc/runtime.h      (working copy)
@@ -768,7 +768,11 @@  objc_EXPORT Protocol **objc_copyProtocolList (unsi
 objc_EXPORT BOOL class_addProtocol (Class class_, Protocol *protocol);
 
 /* Return YES if the class 'class_' conforms to Protocol 'protocol',
-   and NO if not.  */
+   and NO if not.  This function does not check superclasses; if you
+   want to check for superclasses (in the way that [NSObject
+   +conformsToProtocol:] does) you need to iterate over the class
+   hierarchy using class_getSuperclass(), and call
+   class_conformsToProtocol() for each of them.  */
 objc_EXPORT BOOL class_conformsToProtocol (Class class_, Protocol *protocol);
 
 /* Return all the protocols that the class conforms to.  The return
@@ -777,7 +781,9 @@  objc_EXPORT BOOL class_conformsToProtocol (Class c
    class.  It does not include protocols adopted by superclasses.  The
    list is terminated by NULL.  Optionally, if you pass a non-NULL
    'numberOfReturnedProtocols' pointer, the unsigned int that it
-   points to will be filled with the number of protocols returned.  */
+   points to will be filled with the number of protocols returned.
+   This function does not return protocols that superclasses conform
+   to.  */
 objc_EXPORT Protocol **class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols);
 
 /* Return YES if protocol 'protocol' conforms to protocol
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog     (revision 168225)
+++ gcc/testsuite/ChangeLog     (working copy)
@@ -1,3 +1,9 @@ 
+2010-12-24  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * obj-c.dg/gnu-api-2-class.m: Test that class_conformsToProtocol()
+       does not check the superclasses.
+       * obj-c++.dg/gnu-api-2-class.mm: Same change.   
+
 2010-12-24  Alexander Monakov  <amonakov@ispras.ru>
 
        PR rtl-optimization/47036
Index: gcc/testsuite/objc.dg/gnu-api-2-class.m
===================================================================
--- gcc/testsuite/objc.dg/gnu-api-2-class.m     (revision 168225)
+++ gcc/testsuite/objc.dg/gnu-api-2-class.m     (working copy)
@@ -42,6 +42,12 @@ 
 - (id) variable { return variable_ivar; }
 @end
 
+@interface MyOtherSubClass : MySubClass
+@end
+
+@implementation MyOtherSubClass
+@end
+
 @interface DifferentClass : MyRootClass
 - (id) myClass;
 - (id) self;
@@ -188,6 +194,11 @@  int main(int argc, void **args)
 
     if (!class_conformsToProtocol (objc_getClass ("MySubClass"), @protocol (MyProtocol)))
       abort ();
+
+    /* Test that class_conformsToProtocol checks the class, but not
+       superclasses.  */
+    if (class_conformsToProtocol (objc_getClass ("MyOtherSubClass"), @protocol (MyProtocol)))
+      abort ();
   }
 
   printf ("Testing class_copyIvarList ()...\n");
Index: gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm (revision 168225)
+++ gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm (working copy)
@@ -42,6 +42,12 @@ 
 - (id) variable { return variable_ivar; }
 @end
 
+@interface MyOtherSubClass : MySubClass
+@end
+
+@implementation MyOtherSubClass
+@end
+
 @interface DifferentClass : MyRootClass
 - (id) myClass;
 - (id) self;
@@ -188,6 +194,11 @@  int main ()
 
     if (!class_conformsToProtocol (objc_getClass ("MySubClass"), @protocol (MyProtocol)))
       abort ();
+
+    /* Test that class_conformsToProtocol checks the class, but not
+       superclasses.  */
+    if (class_conformsToProtocol (objc_getClass ("MyOtherSubClass"), @protocol (MyProtocol)))
+      abort ();
   }
 
   std::cout << "Testing class_copyIvarList ()...\n";