]> gcc.gnu.org Git - gcc.git/commitdiff
In gcc/objc/: 2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
authorNicola Pero <nicola.pero@meta-innovation.com>
Sat, 27 Nov 2010 09:53:43 +0000 (09:53 +0000)
committerNicola Pero <nicola@gcc.gnu.org>
Sat, 27 Nov 2010 09:53:43 +0000 (09:53 +0000)
In gcc/objc/:
2010-11-27  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc-act.c (objc_build_struct): Fixed loops that save and
        restore TYPE_OBJC_INFO to iterate over all variants of the type; a
        special case for the current type is then no longer required.
        Duplicate TYPE_LANG_SPECIFIC for each type before restoring
        TYPE_OBJC_INFO.
        (objc_get_protocol_qualified_type): Updated comments.

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

        * objc.dg/protocol-qualifier-1.m: New.
        * objc.dg/protocol-qualifier-2.m: New.
        * obj-c++.dg/protocol-qualifier-1.mm: New.
        * obj-c++.dg/protocol-qualifier-2.mm: New.

From-SVN: r167195

gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/protocol-qualifier-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/protocol-qualifier-1.m [new file with mode: 0644]
gcc/testsuite/objc.dg/protocol-qualifier-2.m [new file with mode: 0644]

index fb1ee6a4de357b0e9df688321a995e05117d8e4b..7c890ce7e2e36e843ad0db5b670b3ab67e1e098c 100644 (file)
@@ -1,3 +1,12 @@
+2010-11-27  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-act.c (objc_build_struct): Fixed loops that save and
+       restore TYPE_OBJC_INFO to iterate over all variants of the type; a
+       special case for the current type is then no longer required.
+       Duplicate TYPE_LANG_SPECIFIC for each type before restoring
+       TYPE_OBJC_INFO.
+       (objc_get_protocol_qualified_type): Updated comments.
+       
 2010-11-25  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc-act.c (objc_build_struct): Install TYPE_OBJC_INTERFACE
 2010-11-25  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc-act.c (objc_build_struct): Install TYPE_OBJC_INTERFACE
index 042fa359a4f4c8763c67532c265d4983f92cd54e..232708f6dbbce1404e92df46bded91af86e2952f 100644 (file)
@@ -2137,41 +2137,54 @@ objc_build_struct (tree klass, tree fields, tree super_name)
       fields = base;
     }
 
       fields = base;
     }
 
-  /* NB: Calling finish_struct() may cause type TYPE_LANG_SPECIFIC
-     fields in all variants of this RECORD_TYPE to be clobbered (this
-     is because the C frontend stores a sorted version of the list of
-     fields in lang_type if it deems appropriate, and will update and
-     propagate that list to all variants ignoring the fact that we use
-     lang_type for something else and that such propagation will wipe
-     the objc_info away), but it is therein that we store protocol
-     conformance info (e.g., 'NSObject <MyProtocol>').  Hence, we must
-     squirrel away the ObjC-specific information before calling
+  /* NB: Calling finish_struct() may cause type TYPE_OBJC_INFO
+     information in all variants of this RECORD_TYPE to be destroyed
+     (this is because the C frontend manipulates TYPE_LANG_SPECIFIC
+     for something else and then will change all variants to use the
+     same resulting TYPE_LANG_SPECIFIC, ignoring the fact that we use
+     it for ObjC protocols and that such propagation will make all
+     variants use the same objc_info), but it is therein that we store
+     protocol conformance info (e.g., 'NSObject <MyProtocol>').
+     Hence, we must save the ObjC-specific information before calling
      finish_struct(), and then reinstate it afterwards.  */
 
      finish_struct(), and then reinstate it afterwards.  */
 
-  for (t = TYPE_NEXT_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t))
+  for (t = TYPE_MAIN_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t))
     {
     {
-      if (!TYPE_HAS_OBJC_INFO (t))
-       {
-         INIT_TYPE_OBJC_INFO (t);
-         TYPE_OBJC_INTERFACE (t) = klass;
-       }
+      INIT_TYPE_OBJC_INFO (t);
       VEC_safe_push (tree, heap, objc_info, TYPE_OBJC_INFO (t));
     }
 
   s = objc_finish_struct (s, fields);
 
       VEC_safe_push (tree, heap, objc_info, TYPE_OBJC_INFO (t));
     }
 
   s = objc_finish_struct (s, fields);
 
-  /* Point the struct at its related Objective-C class.  We do this
-     after calling finish_struct() because otherwise finish_struct()
-     would wipe TYPE_OBJC_INTERFACE() out.  */
-  if (!TYPE_HAS_OBJC_INFO (s))
-    INIT_TYPE_OBJC_INFO (s);
-
-  TYPE_OBJC_INTERFACE (s) = klass;
-
-  for (i = 0, t = TYPE_NEXT_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t), i++)
+  for (i = 0, t = TYPE_MAIN_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t), i++)
     {
     {
+      /* We now want to restore the different TYPE_OBJC_INFO, but we
+        have the additional problem that the C frontend doesn't just
+        copy TYPE_LANG_SPECIFIC from one variant to the other; it
+        actually makes all of them the *same* TYPE_LANG_SPECIFIC.  As
+        we need a different TYPE_OBJC_INFO for each (and
+        TYPE_OBJC_INFO is a field in TYPE_LANG_SPECIFIC), we need to
+        make a copy of each TYPE_LANG_SPECIFIC before we modify
+        TYPE_OBJC_INFO.  */
+      if (TYPE_LANG_SPECIFIC (t))
+       {
+         /* Create a copy of TYPE_LANG_SPECIFIC.  */
+         struct lang_type *old_lang_type = TYPE_LANG_SPECIFIC (t);
+         ALLOC_OBJC_TYPE_LANG_SPECIFIC (t);
+         memcpy (TYPE_LANG_SPECIFIC (t), old_lang_type,
+                 SIZEOF_OBJC_TYPE_LANG_SPECIFIC);
+       }
+      else
+       {
+         /* Just create a new one.  */
+         ALLOC_OBJC_TYPE_LANG_SPECIFIC (t);
+       }
+      /* Replace TYPE_OBJC_INFO with the saved one.  This restores any
+        protocol information that may have been associated with the
+        type.  */
       TYPE_OBJC_INFO (t) = VEC_index (tree, objc_info, i);
       TYPE_OBJC_INFO (t) = VEC_index (tree, objc_info, i);
-      /* Replace the IDENTIFIER_NODE with an actual @interface.  */
+      /* Replace the IDENTIFIER_NODE with an actual @interface now
+        that we have it.  */
       TYPE_OBJC_INTERFACE (t) = klass;
     }
   VEC_free (tree, heap, objc_info);
       TYPE_OBJC_INTERFACE (t) = klass;
     }
   VEC_free (tree, heap, objc_info);
@@ -2766,9 +2779,12 @@ objc_non_volatilized_type (tree type)
   return type;
 }
 
   return type;
 }
 
-/* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
-   either name an Objective-C class, or refer to the special 'id' or 'Class'
-   types.  If INTERFACE is not a valid ObjC type, just return it unchanged.  */
+/* Construct a PROTOCOLS-qualified variant of INTERFACE, where
+   INTERFACE may either name an Objective-C class, or refer to the
+   special 'id' or 'Class' types.  If INTERFACE is not a valid ObjC
+   type, just return it unchanged.  This function is often called when
+   PROTOCOLS is NULL_TREE, in which case we simply look up the
+   appropriate INTERFACE.  */
 
 tree
 objc_get_protocol_qualified_type (tree interface, tree protocols)
 
 tree
 objc_get_protocol_qualified_type (tree interface, tree protocols)
@@ -4422,6 +4438,9 @@ objc_declare_class (tree ident_list)
 
          record = xref_tag (RECORD_TYPE, ident);
          INIT_TYPE_OBJC_INFO (record);
 
          record = xref_tag (RECORD_TYPE, ident);
          INIT_TYPE_OBJC_INFO (record);
+         /* In the case of a @class declaration, we store the ident
+            in the TYPE_OBJC_INTERFACE.  If later an @interface is
+            found, we'll replace the ident with the interface.  */
          TYPE_OBJC_INTERFACE (record) = ident;
          hash_class_name_enter (cls_name_hash_list, ident, NULL_TREE);
        }
          TYPE_OBJC_INTERFACE (record) = ident;
          hash_class_name_enter (cls_name_hash_list, ident, NULL_TREE);
        }
index bc402c4453f1ec2c86c880672f446f0d15c67c5f..d0b568a735e08f1ae30aa7e5d6a2e7f0b8d2d4e8 100644 (file)
@@ -1,3 +1,10 @@
+2010-11-27  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc.dg/protocol-qualifier-1.m: New.  
+       * objc.dg/protocol-qualifier-2.m: New.
+       * obj-c++.dg/protocol-qualifier-1.mm: New.      
+       * obj-c++.dg/protocol-qualifier-2.mm: New.
+
 2010-11-26  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * lib/gnat.exp: Load gcc.exp.
 2010-11-26  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * lib/gnat.exp: Load gcc.exp.
diff --git a/gcc/testsuite/obj-c++.dg/protocol-qualifier-1.mm b/gcc/testsuite/obj-c++.dg/protocol-qualifier-1.mm
new file mode 100644 (file)
index 0000000..c84bfbf
--- /dev/null
@@ -0,0 +1,33 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that protocol qualifiers work in the same way with @class and @interface.  */
+
+#include <objc/objc.h>
+
+@protocol MyProtocol
+- (void) method;
+@end
+
+
+/* This first snippet gives no warnings, which is correct as 'object'
+   implements <MyProtocol> and hence responds to 'method'.  Note how
+   the details of the class 'MyClass' are never used.  */
+@interface MyClass
+@end
+
+void test (MyClass <MyProtocol> *object)
+{
+  [object method];
+}
+
+
+/* This second snippet should behave identically.  'object' still implements
+   the same protocol and responds to 'method'.  The details of MyClass or
+   MyClass2 are irrelevant.  */
+@class MyClass2;
+
+void test2 (MyClass2 <MyProtocol> *object)
+{
+  [object method];
+}
diff --git a/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm b/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm
new file mode 100644 (file)
index 0000000..fd25d8f
--- /dev/null
@@ -0,0 +1,31 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that protocol qualifiers are maintained correctly when a
+   @class is replaced by its @interface.  */
+
+#include <objc/objc.h>
+
+@protocol MyProtocol
+- (void) method;
+@end
+
+@class MyClass;
+
+static MyClass <MyProtocol> *object1;
+static MyClass *object2;
+
+/* Declarating the @interface now will need to update all the existing
+   ObjC types referring to MyClass with the new information.  We need
+   to test that protocol information is not lost in the process.  */
+@interface MyClass
+@end
+
+void test1 (void)
+{
+  [object1 method]; /* Ok */
+  [object2 method]; /* { dg-warning ".MyClass. may not respond to ..method." } */
+                    /* { dg-warning "without a matching method" "" { target *-*-* } 27 } */
+                    /* { dg-warning "will be assumed to return" "" { target *-*-* } 27 } */
+                    /* { dg-warning "as arguments" "" { target *-*-* } 27 } */
+}
diff --git a/gcc/testsuite/objc.dg/protocol-qualifier-1.m b/gcc/testsuite/objc.dg/protocol-qualifier-1.m
new file mode 100644 (file)
index 0000000..c84bfbf
--- /dev/null
@@ -0,0 +1,33 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that protocol qualifiers work in the same way with @class and @interface.  */
+
+#include <objc/objc.h>
+
+@protocol MyProtocol
+- (void) method;
+@end
+
+
+/* This first snippet gives no warnings, which is correct as 'object'
+   implements <MyProtocol> and hence responds to 'method'.  Note how
+   the details of the class 'MyClass' are never used.  */
+@interface MyClass
+@end
+
+void test (MyClass <MyProtocol> *object)
+{
+  [object method];
+}
+
+
+/* This second snippet should behave identically.  'object' still implements
+   the same protocol and responds to 'method'.  The details of MyClass or
+   MyClass2 are irrelevant.  */
+@class MyClass2;
+
+void test2 (MyClass2 <MyProtocol> *object)
+{
+  [object method];
+}
diff --git a/gcc/testsuite/objc.dg/protocol-qualifier-2.m b/gcc/testsuite/objc.dg/protocol-qualifier-2.m
new file mode 100644 (file)
index 0000000..fd25d8f
--- /dev/null
@@ -0,0 +1,31 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that protocol qualifiers are maintained correctly when a
+   @class is replaced by its @interface.  */
+
+#include <objc/objc.h>
+
+@protocol MyProtocol
+- (void) method;
+@end
+
+@class MyClass;
+
+static MyClass <MyProtocol> *object1;
+static MyClass *object2;
+
+/* Declarating the @interface now will need to update all the existing
+   ObjC types referring to MyClass with the new information.  We need
+   to test that protocol information is not lost in the process.  */
+@interface MyClass
+@end
+
+void test1 (void)
+{
+  [object1 method]; /* Ok */
+  [object2 method]; /* { dg-warning ".MyClass. may not respond to ..method." } */
+                    /* { dg-warning "without a matching method" "" { target *-*-* } 27 } */
+                    /* { dg-warning "will be assumed to return" "" { target *-*-* } 27 } */
+                    /* { dg-warning "as arguments" "" { target *-*-* } 27 } */
+}
This page took 0.082996 seconds and 5 git commands to generate.