objective-c++, C++ exceptions, and objc_msgsend
Geoffrey Keating
gkeating@apple.com
Fri Oct 21 01:28:00 GMT 2005
The objc_msgsend* builtins are marked as TREE_NOTHROW in C++ by
default, like all builtins, but because these functions can (in fact,
always do) call user functions, they can throw.
This testcase is a regression relative to gcc 3.4, because before then
the optimisers wouldn't notice that no exceptions were possible and
so wouldn't remove the try/catch statement.
Bootstrapped & tested on powerpc-darwin8.
--
- Geoffrey Keating <geoffk@apple.com>
===File ~/patches/gcc-4308031.patch=========================
Index: objc/ChangeLog
2005-10-20 Geoffrey Keating <geoffk@apple.com>
* objc-act.c (synth_module_prologue): Clear TREE_NOTHROW
on objc_msgSend and like builtin functions.
Index: testsuite/ChangeLog
2005-10-20 Geoffrey Keating <geoffk@apple.com>
* obj-c++.dg/except-1.mm: New.
Index: objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.292
diff -u -p -u -p -r1.292 objc-act.c
--- objc/objc-act.c 17 Oct 2005 14:51:03 -0000 1.292
+++ objc/objc-act.c 21 Oct 2005 00:00:20 -0000
@@ -1597,6 +1597,10 @@ synth_module_prologue (void)
(xref_tag (RECORD_TYPE,
get_identifier (UTAG_IVAR_LIST)));
+ /* TREE_NOTHROW is cleared for the message-sending functions,
+ because the function that gets called can throw in Obj-C++, or
+ could itself call something that can throw even in Obj-C. */
+
if (flag_next_runtime)
{
/* NB: In order to call one of the ..._stret (struct-returning)
@@ -1626,12 +1630,21 @@ synth_module_prologue (void)
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
+ /* These can throw, because the function that gets called can throw
+ in Obj-C++, or could itself call something that can throw even
+ in Obj-C. */
+ TREE_NOTHROW (umsg_decl) = 0;
+ TREE_NOTHROW (umsg_nonnil_decl) = 0;
+ TREE_NOTHROW (umsg_stret_decl) = 0;
+ TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
+
/* id objc_msgSend_Fast (id, SEL, ...)
__attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
#ifdef OFFS_MSGSEND_FAST
umsg_fast_decl = builtin_function (TAG_MSGSEND_FAST,
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_fast_decl) = 0;
DECL_ATTRIBUTES (umsg_fast_decl)
= tree_cons (get_identifier ("hard_coded_address"),
build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
@@ -1654,6 +1667,8 @@ synth_module_prologue (void)
umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
type, 0, NOT_BUILT_IN, 0,
NULL_TREE);
+ TREE_NOTHROW (umsg_super_decl) = 0;
+ TREE_NOTHROW (umsg_super_stret_decl) = 0;
}
else
{
@@ -1676,6 +1691,7 @@ synth_module_prologue (void)
umsg_decl = builtin_function (TAG_MSGSEND,
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_decl) = 0;
/* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
type
@@ -1686,6 +1702,7 @@ synth_module_prologue (void)
umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_super_decl) = 0;
/* The following GNU runtime entry point is called to initialize
each module:
Index: testsuite/obj-c++.dg/except-1.mm
===================================================================
RCS file: testsuite/obj-c++.dg/except-1.mm
diff -N testsuite/obj-c++.dg/except-1.mm
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/obj-c++.dg/except-1.mm 21 Oct 2005 00:00:24 -0000
@@ -0,0 +1,65 @@
+/* { dg-do run { target "*-*-darwin*" } } */
+/* { dg-options "-framework Foundation" } */
+
+/* This tests that exceptions work. It used to fail because
+ objc_msgSend was marked with DECL_NOTHROW.
+ If you include objc/Object.h, the problem goes away, because
+ that file includes objc/objc-runtime.h which explicitly prototypes
+ objc_msgSend without 'nothrow'. */
+
+#include <Foundation/Foundation.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// ObjectiveC class header
+@interface ObjCclass : NSObject {
+}
+-(void)method1;
+-(void)method2;
+@end
+
+// C++ class header
+class CPPclass {
+public:
+ void function1();
+};
+
+
+// Main
+int main(int argc, char *argv[])
+{
+ ObjCclass * foo = [[ObjCclass alloc] init];
+ [foo method1];
+ exit (0);
+}
+
+
+// ObjectiveC implementation
+@implementation ObjCclass
+
+-(void) method1
+{
+ try {
+ [self method2];
+ }
+ catch(...) {
+ return;
+ }
+}
+
+-(void) method2
+{
+ CPPclass foo;
+ foo.function1();
+}
+
+@end
+
+
+// C++ implementation
+void CPPclass::function1()
+{
+ throw (1);
+ /* Shouldn't be here because we threw. */
+ abort ();
+}
============================================================
More information about the Gcc-patches
mailing list