aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-11-27 09:53:43 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-11-27 09:53:43 +0000
commita693d3a8f55ffcf432401f5890fa1a55fc86eaf1 (patch)
tree895f2f8651a945915cdbeae810ca04b6e2835748 /gcc
parenta5c7ea1d6235f4affed430e1ecb74ef316643135 (diff)
downloadgcc-a693d3a8f55ffcf432401f5890fa1a55fc86eaf1.zip
gcc-a693d3a8f55ffcf432401f5890fa1a55fc86eaf1.tar.gz
gcc-a693d3a8f55ffcf432401f5890fa1a55fc86eaf1.tar.bz2
In gcc/objc/: 2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/objc/ChangeLog9
-rw-r--r--gcc/objc/objc-act.c75
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/obj-c++.dg/protocol-qualifier-1.mm33
-rw-r--r--gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm31
-rw-r--r--gcc/testsuite/objc.dg/protocol-qualifier-1.m33
-rw-r--r--gcc/testsuite/objc.dg/protocol-qualifier-2.m31
7 files changed, 191 insertions, 28 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index fb1ee6a..7c890ce 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -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
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 042fa35..232708f6 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -2137,41 +2137,54 @@ objc_build_struct (tree klass, tree fields, tree super_name)
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. */
- 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);
- /* 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);
- /* 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);
@@ -2766,9 +2779,12 @@ objc_non_volatilized_type (tree 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)
@@ -4422,6 +4438,9 @@ objc_declare_class (tree ident_list)
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);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bc402c4..d0b568a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
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
index 0000000..c84bfbf
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/protocol-qualifier-1.mm
@@ -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
index 0000000..fd25d8f
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm
@@ -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
index 0000000..c84bfbf
--- /dev/null
+++ b/gcc/testsuite/objc.dg/protocol-qualifier-1.m
@@ -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
index 0000000..fd25d8f
--- /dev/null
+++ b/gcc/testsuite/objc.dg/protocol-qualifier-2.m
@@ -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 } */
+}