In gcc/objc/: 2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com>
authorNicola Pero <nicola.pero@meta-innovation.com>
Thu, 30 Dec 2010 22:02:09 +0000 (22:02 +0000)
committerNicola Pero <nicola@gcc.gnu.org>
Thu, 30 Dec 2010 22:02:09 +0000 (22:02 +0000)
In gcc/objc/:
2010-12-30  Nicola Pero  <nicola.pero@meta-innovation.com>

* objc-act.c (objc_types_are_equivalent): Fixed comparing protocol
lists.  Check them two-ways to fix comparisons when one protocol
implements the other one, or when one list contains duplicated
protocols.

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

* objc.dg/method-conflict-3.m: New.
* objc.dg/method-conflict-4.m: New.
* obj-c++.dg/method-conflict-3.m: New.
* obj-c++.dg/method-conflict-4.mm: New.

From-SVN: r168356

gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/method-conflict-3.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-conflict-4.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/method-conflict-3.m [new file with mode: 0644]
gcc/testsuite/objc.dg/method-conflict-4.m [new file with mode: 0644]

index 43ef65d6ec9fda2bbacf40fb1ad66d212e049c5e..3edb54edb823dabb7226ddf9f378b471ffd55964 100644 (file)
@@ -1,3 +1,10 @@
+2010-12-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-act.c (objc_types_are_equivalent): Fixed comparing protocol
+       lists.  Check them two-ways to fix comparisons when one protocol
+       implements the other one, or when one list contains duplicated
+       protocols.
+
 2010-12-30  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc-act.c (objc_add_method): When emitting an error because a
index ec7fea59dd3334c3d69a491d751bc2ae319af5b4..a37f3d91457cbf84539e0782b2e65ef7a5517951 100644 (file)
@@ -11925,9 +11925,8 @@ start_method_def (tree method)
   really_start_method (objc_method_context, parm_info);
 }
 
-/* Return 1 if TYPE1 is equivalent to TYPE2
-   for purposes of method overloading.  */
-
+/* Return 1 if TYPE1 is equivalent to TYPE2 for purposes of method
+   overloading.  */
 static int
 objc_types_are_equivalent (tree type1, tree type2)
 {
@@ -11941,6 +11940,7 @@ objc_types_are_equivalent (tree type1, tree type2)
   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
     return 0;
 
+  /* Compare the protocol lists.  */
   type1 = (TYPE_HAS_OBJC_INFO (type1)
           ? TYPE_OBJC_PROTOCOL_LIST (type1)
           : NULL_TREE);
@@ -11948,14 +11948,34 @@ objc_types_are_equivalent (tree type1, tree type2)
           ? TYPE_OBJC_PROTOCOL_LIST (type2)
           : NULL_TREE);
 
-  if (list_length (type1) == list_length (type2))
+  /* If there are no protocols (most common case), the types are
+     identical.  */
+  if (type1 == NULL_TREE && type2 == NULL_TREE)
+    return 1;
+  
+  /* If one has protocols, and the other one hasn't, they are not
+     identical.  */
+  if ((type1 == NULL_TREE && type2 != NULL_TREE)
+      || (type1 != NULL_TREE && type2 == NULL_TREE))
+    return 0;
+  else
     {
-      for (; type2; type2 = TREE_CHAIN (type2))
-       if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
+      /* Else, both have protocols, and we need to do the full
+        comparison.  It is possible that either type1 or type2
+        contain some duplicate protocols in the list, so we can't
+        even just compare list_length as a first check.  */
+      tree t;
+
+      for (t = type2; t; t = TREE_CHAIN (t))
+       if (!lookup_protocol_in_reflist (type1, TREE_VALUE (t)))
+         return 0;
+      
+      for (t = type1; t; t = TREE_CHAIN (t))
+       if (!lookup_protocol_in_reflist (type2, TREE_VALUE (t)))
          return 0;
+      
       return 1;
     }
-  return 0;
 }
 
 /* Return 1 if TYPE1 has the same size and alignment as TYPE2.  */
index 681c27ef6793760436606446ce909e5d5e1e34ee..26bcf8c83b2ac9008592d9ae2052423a738279b2 100644 (file)
@@ -1,3 +1,10 @@
+2010-12-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc.dg/method-conflict-3.m: New.
+       * objc.dg/method-conflict-4.m: New.     
+       * obj-c++.dg/method-conflict-3.m: New.  
+       * obj-c++.dg/method-conflict-4.mm: New.
+
 2010-12-30  Nicola Pero  <nicola.pero@meta-innovation.com>
        
        * objc.dg/class-extension-3.m: Updated.
diff --git a/gcc/testsuite/obj-c++.dg/method-conflict-3.mm b/gcc/testsuite/obj-c++.dg/method-conflict-3.mm
new file mode 100644 (file)
index 0000000..d4b6fbf
--- /dev/null
@@ -0,0 +1,65 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that the compiler can correctly compare protocols in types of
+   method signatures.  */
+
+@protocol A, B, C;
+
+@interface MyClass
+- (void) method1: (id)x;
+- (void) method1: (id)x; /* Ok */
+
+- (void) method2: (id <A>)x;
+- (void) method2: (id <A>)x; /* Ok */
+
+- (void) method3: (id <A, B>)x;
+- (void) method3: (id <A, B>)x; /* Ok */
+
+- (void) method4: (id <A, B>)x;
+- (void) method4: (id <A, B, B>)x; /* Ok */
+
+- (void) method5: (id <A, A, B>)x;
+- (void) method5: (id <A, B, B>)x; /* Ok */
+
+- (void) method6: (id <A, A, B, B, C, C>)x;
+- (void) method6: (id <C, A, B>)x; /* Ok */
+
+- (void) method7: (id)x; /* { dg-warning "previous declaration" } */
+- (void) method7: (id <A>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) method8: (id <A>)x; /* { dg-warning "previous declaration" } */
+- (void) method8: (id)x; /* { dg-error "duplicate declaration" } */
+
+- (void) method9: (id <A>)x; /* { dg-warning "previous declaration" } */
+- (void) method9: (id <B>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodA: (id <A>)x; /* { dg-warning "previous declaration" } */
+- (void) methodA: (id <A, B>)x; /* { dg-error "duplicate declaration" } */
+
+/* FIXME: Bug in the testsuite - the following are done Ok by the compiler, but
+   the testsuite barfs so we have to comment out the tests.  */
+/* - (void) methodB: (id <A, B>)x; dg-warning "previous declaration" */
+/* - (void) methodB: (id <A>)x; dg-error "duplicate declaration" */
+
+/* - (void) methodC: (id <A, B, C>)x;  dg-warning "previous declaration"  */
+/* - (void) methodC: (id <A, B>)x;  dg-error "duplicate declaration"  */
+
+/* - (void) methodD: (id <A, B, C>)x;  dg-warning "previous declaration"  */
+/* - (void) methodD: (id <A, B, A>)x;  dg-error "duplicate declaration"  */
+
+/* - (void) methodE: (MyClass <A, B, C> *)x;  dg-warning "previous declaration"  */
+/* - (void) methodE: (MyClass <A, B, A> *)x;  dg-error "duplicate declaration"  */
+
+- (void) methodF: (MyClass <A, B, A> *)x;
+- (void) methodF: (MyClass <A, B, A> *)x; /* Ok */
+
+/* - (void) methodG: (MyClass *)x;   dg-warning "previous declaration"  */
+/* - (void) methodG: (MyClass <A, B, C> *)x;  dg-error "duplicate declaration"  */
+
+/* - (void) methodH: (MyClass <A, C>*)x;  dg-warning "previous declaration"  */
+/* - (void) methodH: (MyClass *)x;  dg-error "duplicate declaration"  */
+
+@end
diff --git a/gcc/testsuite/obj-c++.dg/method-conflict-4.mm b/gcc/testsuite/obj-c++.dg/method-conflict-4.mm
new file mode 100644 (file)
index 0000000..1031341
--- /dev/null
@@ -0,0 +1,48 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that the compiler can correctly compare protocols in types of
+   method signatures.  In this test we look at protocols implementing
+   other protocols.  The fact that one protocol implements another one
+   doesn't mean that they are identical.  */
+
+@protocol A
+- (void) doSomething;
+@end
+
+@protocol B <A>
+- (void) doSomethingElse;
+@end
+
+@protocol C <A>
+- (void) doYetSomethingElse;
+@end
+
+@interface MyClass2
+- (void) aMethod: (id <A>)x;  /* { dg-error "previous declaration" } */
+- (void) aMethod: (id <B>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) bMethod: (id <B>)x;  /* { dg-error "previous declaration" } */
+- (void) bMethod: (id <A>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) cMethod: (id <A, B>)x;
+- (void) cMethod: (id <B>)x;  /* Ok - because if you implement B, then you also implement A, so <B> == <A, B> */
+
+- (void) dMethod: (id <A, B>)x;
+- (void) dMethod: (id <B, A>)x; /* Ok */
+
+/* FIXME: The compiler works, but the testsuite produces errors anyway.  */
+/* - (void) eMethod: (id <A>)x;   dg-error "previous declaration"  */
+/* - (void) eMethod: (id <B, C>)x;   dg-error "duplicate declaration"  */
+
+/*- (void) fMethod: (id <B, C>)x;   dg-error "previous declaration"  */
+/*- (void) fMethod: (id <A>)x;   dg-error "duplicate declaration"  */
+
+/* - (void) gMethod: (id <A>)x;   dg-error "previous declaration" */
+/* - (void) gMethod: (id <A, B, C>)x;   dg-error "duplicate declaration" */
+
+/* - (void) hMethod: (id <A, B, C>)x;   dg-error "previous declaration" */
+/* - (void) hMethod: (id <A>)x;   dg-error "duplicate declaration" */
+@end
diff --git a/gcc/testsuite/objc.dg/method-conflict-3.m b/gcc/testsuite/objc.dg/method-conflict-3.m
new file mode 100644 (file)
index 0000000..cc4d263
--- /dev/null
@@ -0,0 +1,63 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that the compiler can correctly compare protocols in types of
+   method signatures.  */
+
+@protocol A, B, C;
+
+@interface MyClass
+- (void) method1: (id)x;
+- (void) method1: (id)x; /* Ok */
+
+- (void) method2: (id <A>)x;
+- (void) method2: (id <A>)x; /* Ok */
+
+- (void) method3: (id <A, B>)x;
+- (void) method3: (id <A, B>)x; /* Ok */
+
+- (void) method4: (id <A, B>)x;
+- (void) method4: (id <A, B, B>)x; /* Ok */
+
+- (void) method5: (id <A, A, B>)x;
+- (void) method5: (id <A, B, B>)x; /* Ok */
+
+- (void) method6: (id <A, A, B, B, C, C>)x;
+- (void) method6: (id <C, A, B>)x; /* Ok */
+
+- (void) method7: (id)x; /* { dg-message "previous declaration" } */
+- (void) method7: (id <A>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) method8: (id <A>)x; /* { dg-message "previous declaration" } */
+- (void) method8: (id)x; /* { dg-error "duplicate declaration" } */
+
+- (void) method9: (id <A>)x; /* { dg-message "previous declaration" } */
+- (void) method9: (id <B>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodA: (id <A>)x; /* { dg-message "previous declaration" } */
+- (void) methodA: (id <A, B>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodB: (id <A, B>)x; /* { dg-message "previous declaration" } */
+- (void) methodB: (id <A>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodC: (id <A, B, C>)x; /* { dg-message "previous declaration" } */
+- (void) methodC: (id <A, B>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodD: (id <A, B, C>)x; /* { dg-message "previous declaration" } */
+- (void) methodD: (id <A, B, A>)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodE: (MyClass <A, B, C> *)x; /* { dg-message "previous declaration" } */
+- (void) methodE: (MyClass <A, B, A> *)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodF: (MyClass <A, B, A> *)x;
+- (void) methodF: (MyClass <A, B, A> *)x; /* Ok */
+
+- (void) methodG: (MyClass *)x;  /* { dg-message "previous declaration" } */
+- (void) methodG: (MyClass <A, B, C> *)x; /* { dg-error "duplicate declaration" } */
+
+- (void) methodH: (MyClass <A, C>*)x;  /* { dg-message "previous declaration" } */
+- (void) methodH: (MyClass *)x; /* { dg-error "duplicate declaration" } */
+
+@end
diff --git a/gcc/testsuite/objc.dg/method-conflict-4.m b/gcc/testsuite/objc.dg/method-conflict-4.m
new file mode 100644 (file)
index 0000000..a0c2782
--- /dev/null
@@ -0,0 +1,47 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that the compiler can correctly compare protocols in types of
+   method signatures.  In this test we look at protocols implementing
+   other protocols.  The fact that one protocol implements another one
+   doesn't mean that they are identical.  */
+
+@protocol A
+- (void) doSomething;
+@end
+
+@protocol B <A>
+- (void) doSomethingElse;
+@end
+
+@protocol C <A>
+- (void) doYetSomethingElse;
+@end
+
+@interface MyClass2
+- (void) aMethod: (id <A>)x;  /* { dg-message "previous declaration" } */
+- (void) aMethod: (id <B>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) bMethod: (id <B>)x;  /* { dg-message "previous declaration" } */
+- (void) bMethod: (id <A>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) cMethod: (id <A, B>)x;
+- (void) cMethod: (id <B>)x;  /* Ok - because if you implement B, then you also implement A, so <B> == <A, B> */
+
+- (void) dMethod: (id <A, B>)x;
+- (void) dMethod: (id <B, A>)x; /* Ok */
+
+- (void) eMethod: (id <A>)x;  /* { dg-message "previous declaration" } */
+- (void) eMethod: (id <B, C>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) fMethod: (id <B, C>)x;  /* { dg-message "previous declaration" } */
+- (void) fMethod: (id <A>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) gMethod: (id <A>)x;  /* { dg-message "previous declaration" } */
+- (void) gMethod: (id <A, B, C>)x;  /* { dg-error "duplicate declaration" } */
+
+- (void) hMethod: (id <A, B, C>)x;  /* { dg-message "previous declaration" } */
+- (void) hMethod: (id <A>)x;  /* { dg-error "duplicate declaration" } */
+@end