This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Fix TYPE_LANG_SPECIFIC() lossage during volatilization


Using ObjC exception handling on Darwin requires that local variables
be marked 'volatile' so as to not get clobbered by _setjmp()/_longjmp()
that the EH mechanism uses.  To do this, objc_volatilize_decl() calls
get_qualified_type(); unfortunately, the latter knows nothing about
TYPE_LANG_SPECIFIC info and has a tendency to misplace it.  So, we
roll our own objc_get_volatilized_type() instead.


[gcc/objc/ChangeLog] 2005-06-30 Ziemowit Laski <zlaski@apple.com>

       * objc-act.c (objc_build_volatilized_type): New function.
       (objc_volatilize_decl): Call objc_build_volatilized_type()
       instead of build_qualified_type().

[gcc/testsuite/ChangeLog]
2005-06-30  Ziemowit Laski  <zlaski@apple.com>

       * obj-c++.dg/try-catch-11.mm: New.
       * objc.dg/try-catch-10.m: New.

Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.281
diff -u -3 -p -r1.281 objc-act.c
--- gcc/objc/objc-act.c 29 Jun 2005 21:01:25 -0000      1.281
+++ gcc/objc/objc-act.c 1 Jul 2005 01:33:02 -0000
@@ -185,6 +185,7 @@ static tree build_protocol_initializer (
 static tree get_class_ivars (tree, bool);
 static tree generate_protocol_list (tree);
 static void build_protocol_reference (tree);
+static tree objc_build_volatilized_type (tree);

 #ifdef OBJCPLUS
 static void objc_generate_cxx_cdtors (void);
@@ -868,6 +869,41 @@ objc_build_struct (tree name, tree field
   return s;
 }

+/* Build a type differing from TYPE only in that TYPE_VOLATILE is set.
+ Unlike tree.c:build_qualified_type(), preserve TYPE_LANG_SPECIFIC in the
+ process. */
+static tree
+objc_build_volatilized_type (tree type)
+{
+ tree t;
+
+ /* Check if we have not constructed the desired variant already. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ {
+ /* The type qualifiers must (obviously) match up. */
+ if (!TYPE_VOLATILE (t)
+ || (TYPE_READONLY (t) != TYPE_READONLY (type))
+ || (TYPE_RESTRICT (t) != TYPE_RESTRICT (type)))
+ continue;
+
+ /* For pointer types, the pointees (and hence their TYPE_LANG_SPECIFIC
+ info, if any) must match up. */
+ if (POINTER_TYPE_P (t)
+ && (TREE_TYPE (t) != TREE_TYPE (type)))
+ continue;
+
+ /* Everything matches up! */
+ return t;
+ }
+
+ /* Ok, we could not re-use any of the pre-existing variants. Create
+ a new one. */
+ t = build_variant_type_copy (type);
+ TYPE_VOLATILE (t) = 1;
+
+ return t;
+}
+
/* Mark DECL as being 'volatile' for purposes of Darwin
_setjmp()/_longjmp() exception handling. Called from
objc_mark_locals_volatile(). */
@@ -884,8 +920,7 @@ objc_volatilize_decl (tree decl)
struct volatilized_type key;
void **loc;


-      t = build_qualified_type (t, (TYPE_QUALS (t)
-                                   | TYPE_QUAL_VOLATILE));
+      t = objc_build_volatilized_type (t);
       key.type = t;
       loc = htab_find_slot (volatilized_htab, &key, INSERT);

Index: gcc/testsuite/obj-c++.dg/try-catch-11.mm
===================================================================
RCS file: gcc/testsuite/obj-c++.dg/try-catch-11.mm
diff -N gcc/testsuite/obj-c++.dg/try-catch-11.mm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/obj-c++.dg/try-catch-11.mm 1 Jul 2005 01:38:10 -0000
@@ -0,0 +1,40 @@
+/* Ensure that @try/@catch blocks do not mess with types of
+ local objects (other than their volatile bits). */
+
+/* { dg-options "-fobjc-exceptions -fnext-runtime" } */
+/* { dg-do compile } */
+
+#include <objc/Object.h>
+
+@protocol Proto1
+- (int)meth1;
+@end
+
+@protocol Proto2
+- (int)meth2;
+@end
+
+@interface MyClass: Object <Proto2> {
+ int a;
+}
+- (int)meth2;
+- (Object *)parm1: (id)p1 parm2: (id<Proto1>)p2;
+@end
+
+MyClass *mc1, *mc2;
+
+@implementation MyClass
+- (int)meth2 {
+ return a;
+}
+- (Object *)parm1: (id)p1 parm2: (id<Proto1>)p2 {
+ @try {
+ mc2 = p2; /* { dg-warning "type .id <Proto1>. does not conform to the .Proto2. protocol" } */
+ }
+ @catch (id exc) {
+ return exc;
+ }
+ mc1 = p1; /* no warning here! */
+ return self;
+}
+@end
Index: gcc/testsuite/objc.dg/try-catch-10.m
===================================================================
RCS file: gcc/testsuite/objc.dg/try-catch-10.m
diff -N gcc/testsuite/objc.dg/try-catch-10.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/objc.dg/try-catch-10.m 1 Jul 2005 01:38:10 -0000
@@ -0,0 +1,40 @@
+/* Ensure that @try/@catch blocks do not mess with types of
+ local objects (other than their volatile bits). */
+
+/* { dg-options "-fobjc-exceptions -fnext-runtime" } */
+/* { dg-do compile } */
+
+#include <objc/Object.h>
+
+@protocol Proto1
+- (int)meth1;
+@end
+
+@protocol Proto2
+- (int)meth2;
+@end
+
+@interface MyClass: Object <Proto2> {
+ int a;
+}
+- (int)meth2;
+- (Object *)parm1: (id)p1 parm2: (id<Proto1>)p2;
+@end
+
+MyClass *mc1, *mc2;
+
+@implementation MyClass
+- (int)meth2 {
+ return a;
+}
+- (Object *)parm1: (id)p1 parm2: (id<Proto1>)p2 {
+ @try {
+ mc2 = p2; /* { dg-warning "type .id <Proto1>. does not conform to the .Proto2. protocol" } */
+ }
+ @catch (id exc) {
+ return exc;
+ }
+ mc1 = p1; /* no warning here! */
+ return self;
+}
+@end


--------------------------------------------------------------
Ziemowit Laski                 1 Infinite Loop, MS 301-2K
Mac OS X Compiler Group        Cupertino, CA USA  95014-2083
Apple Computer, Inc.           +1.408.974.6229  Fax .5477


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]