aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zackw@stanford.edu>2001-05-13 01:28:18 +0000
committerZack Weinberg <zack@gcc.gnu.org>2001-05-13 01:28:18 +0000
commit1f730ff7b674c4309a3684f9e7f901ccf01da9c7 (patch)
tree49246e78a7ee8c4a59b8982faf4c2837e13775cb
parentc9ec8f321f955dd9750f73d6957afbb0bac842e5 (diff)
downloadgcc-1f730ff7b674c4309a3684f9e7f901ccf01da9c7.zip
gcc-1f730ff7b674c4309a3684f9e7f901ccf01da9c7.tar.gz
gcc-1f730ff7b674c4309a3684f9e7f901ccf01da9c7.tar.bz2
except.c (choose_personality_routine): Export.
gcc/cp: * except.c (choose_personality_routine): Export. Add explanatory comment. Take an enum languages, not a boolean. (initialize_handler_parm): Adjust to match. * cp-tree.h: Prototype choose_personality_routine. * lex.c (handle_pragma_java_exceptions): New function. (init_cp_pragma): Register #pragma GCC java_exceptions. gcc: * extend.texi: Document #pragma GCC java_exceptions. libjava: * Makefile.am (libgcj_la_OBJECTS): Remove libsupc++convenience.la. * Makefile.in: Regenerate (by hand). * include/jvm.h: Add #pragma GCC java_exceptions at top of file. * doc/cni.sgml: Document #pragma GCC java_exceptions. From-SVN: r42027
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/except.c62
-rw-r--r--gcc/cp/lex.c15
-rw-r--r--gcc/extend.texi36
-rw-r--r--libjava/ChangeLog7
-rw-r--r--libjava/Makefile.am1
-rw-r--r--libjava/Makefile.in1
-rw-r--r--libjava/doc/cni.sgml25
-rw-r--r--libjava/include/jvm.h3
11 files changed, 142 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8ea9949..3f91ca1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2001-05-12 Zack Weinberg <zackw@stanford.edu>
+
+ * extend.texi: Document #pragma GCC java_exceptions.
+
2001-05-12 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* c-parse.in (bison parser, init_reswords): Remove uses of
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c9408a..67f50d0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2001-05-12 Zack Weinberg <zackw@stanford.edu>
+
+ * except.c (choose_personality_routine): Export. Add
+ explanatory comment. Take an enum languages, not a boolean.
+ (initialize_handler_parm): Adjust to match.
+ * cp-tree.h: Prototype choose_personality_routine.
+ * lex.c (handle_pragma_java_exceptions): New function.
+ (init_cp_pragma): Register #pragma GCC java_exceptions.
+
2001-05-12 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* method.c (build_mangled_C99_name): Remove unused prototype.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d313fcd..1735042 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4018,6 +4018,7 @@ extern tree build_throw PARAMS ((tree));
extern void mark_all_runtime_matches PARAMS ((void));
extern int nothrow_libfn_p PARAMS ((tree));
extern void check_handlers PARAMS ((tree));
+extern void choose_personality_routine PARAMS ((enum languages));
/* in expr.c */
extern void init_cplus_expand PARAMS ((void));
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index aa372c8..e4f04e8 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -43,7 +43,6 @@ static int dtor_nothrow PARAMS ((tree));
static tree do_end_catch PARAMS ((tree));
static void push_eh_cleanup PARAMS ((tree));
static bool decl_is_java_type PARAMS ((tree decl, int err));
-static void choose_personality_routine PARAMS ((bool));
static void initialize_handler_parm PARAMS ((tree, tree));
static tree do_allocate_exception PARAMS ((tree));
static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
@@ -259,9 +258,15 @@ decl_is_java_type (decl, err)
return r;
}
-static void
-choose_personality_routine (is_java)
- bool is_java;
+/* Select the personality routine to be used for exception handling,
+ or issue an error if we need two different ones in the same
+ translation unit.
+ ??? At present eh_personality_libfunc is set to
+ __gxx_personality_(sj|v)0 in init_exception_processing - should it
+ be done here instead? */
+void
+choose_personality_routine (lang)
+ enum languages lang;
{
static enum {
chose_none,
@@ -272,28 +277,44 @@ choose_personality_routine (is_java)
switch (state)
{
- case chose_none:
- /* We defaulted to C++ in init_exception_processing.
- Reconfigure for Java if we changed our minds. */
- if (is_java)
- eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- ? "__gcj_personality_sj0"
- : "__gcj_personality_v0");
- state = (is_java ? chose_java : chose_cpp);
- break;
+ case gave_error:
+ return;
case chose_cpp:
+ if (lang != lang_cplusplus)
+ goto give_error;
+ return;
+
case chose_java:
- if (state != (is_java ? chose_java : chose_cpp))
- {
- error ("mixing C++ and Java catches in a single translation unit");
- state = gave_error;
- }
+ if (lang != lang_java)
+ goto give_error;
+ return;
+
+ case chose_none:
+ ; /* proceed to language selection */
+ }
+
+ switch (lang)
+ {
+ case lang_cplusplus:
+ state = chose_cpp;
break;
- case gave_error:
+ case lang_java:
+ state = chose_java;
+ eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ ? "__gcj_personality_sj0"
+ : "__gcj_personality_v0");
break;
+
+ default:
+ abort ();
}
+ return;
+
+ give_error:
+ error ("mixing C++ and Java catches in a single translation unit");
+ state = gave_error;
}
/* Initialize the catch parameter DECL. */
@@ -318,7 +339,8 @@ initialize_handler_parm (decl, exp)
&& TREE_CODE (init_type) != REFERENCE_TYPE)
init_type = build_reference_type (init_type);
- choose_personality_routine (decl_is_java_type (init_type, 0));
+ choose_personality_routine (decl_is_java_type (init_type, 0)
+ ? lang_java : lang_cplusplus);
/* Since pointers are passed by value, initialize a reference to
pointer catch parm with the address of the temporary. */
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index f005482..ac4c854 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -61,6 +61,7 @@ static void handle_pragma_vtable PARAMS ((cpp_reader *));
static void handle_pragma_unit PARAMS ((cpp_reader *));
static void handle_pragma_interface PARAMS ((cpp_reader *));
static void handle_pragma_implementation PARAMS ((cpp_reader *));
+static void handle_pragma_java_exceptions PARAMS ((cpp_reader *));
static void cxx_init PARAMS ((void));
static void cxx_finish PARAMS ((void));
static void cxx_init_options PARAMS ((void));
@@ -687,6 +688,8 @@ init_cp_pragma ()
cpp_register_pragma (parse_in, "GCC", "interface", handle_pragma_interface);
cpp_register_pragma (parse_in, "GCC", "implementation",
handle_pragma_implementation);
+ cpp_register_pragma (parse_in, "GCC", "java_exceptions",
+ handle_pragma_java_exceptions);
}
const char *
@@ -1181,6 +1184,18 @@ handle_pragma_implementation (dfile)
}
}
+/* Indicate that this file uses Java-personality exception handling. */
+static void
+handle_pragma_java_exceptions (dfile)
+ cpp_reader *dfile ATTRIBUTE_UNUSED;
+{
+ tree x;
+ if (c_lex (&x) != CPP_EOF)
+ warning ("junk at end of #pragma GCC java_exceptions");
+
+ choose_personality_routine (lang_java);
+}
+
void
do_pending_lang_change ()
{
diff --git a/gcc/extend.texi b/gcc/extend.texi
index 5c52fcb..6b08843 100644
--- a/gcc/extend.texi
+++ b/gcc/extend.texi
@@ -3811,6 +3811,7 @@ Predefined Macros,cpp.info,The C Preprocessor}).
* Bound member functions:: You can extract a function pointer to the
method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Attributes:: Variable, function, and type attributes for C++ only.
+* Java Exceptions:: Tweaking exception handling to work with Java.
* Deprecated Features:: Things might disappear from g++.
* Backwards Compatibility:: Compatibilities with earlier definitions of C++.
@end menu
@@ -4380,6 +4381,41 @@ interface table mechanism, instead of regular virtual table dispatch.
@end table
+@node Java Exceptions
+@section Java Exceptions
+
+The Java language uses a slightly different exception handling model
+from C++. Normally, GNU C++ will automatically detect when you are
+writing C++ code that uses Java exceptions, and handle them
+appropriately. However, if C++ code only needs to execute destructors
+when Java exceptions are thrown through it, GCC will guess incorrectly.
+Sample problematic code:
+
+@example
+ struct S @{ ~S(); @};
+ extern void bar(); // is implemented in Java and may throw exceptions
+ void foo()
+ @{
+ S s;
+ bar();
+ @}
+@end example
+
+@noindent
+The usual effect of an incorrect guess is a link failure, complaining of
+a missing routine called @samp{__gxx_personality_v0}.
+
+You can inform the compiler that Java exceptions are to be used in a
+translation unit, irrespective of what it might think, by writing
+@samp{@w{#pragma GCC java_exceptions}} at the head of the file. This
+@samp{#pragma} must appear before any functions that throw or catch
+exceptions, or run destructors when exceptions are thrown through them.
+
+You cannot mix Java and C++ exceptions in the same translation unit. It
+is believed to be safe to throw a C++ exception from one file through
+another file compiled for the for the Java exception model, or vice
+versa, but there may be bugs in this area.
+
@node Deprecated Features
@section Deprecated Features
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 379a43b..56784e0 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,10 @@
+2001-05-12 Zack Weinberg <zackw@stanford.edu>
+
+ * Makefile.am (libgcj_la_OBJECTS): Remove libsupc++convenience.la.
+ * Makefile.in: Regenerate (by hand).
+ * include/jvm.h: Add #pragma GCC java_exceptions at top of file.
+ * doc/cni.sgml: Document #pragma GCC java_exceptions.
+
2001-05-11 Richard Henderson <rth@redhat.com>
* configure.in (ia64-*): Don't set SYSDEP_SOURCES.
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index d5644a15..3760b32 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -260,7 +260,6 @@ libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
@echo $(libgcj_la_OBJECTS) > libgcj.objectlist;
@echo $(libgcj_la_LIBADD) >> libgcj.objectlist;
$(libgcj_la_LINK) -objectlist libgcj.objectlist \
- ../libstdc++-v3/libsupc++/libsupc++convenience.la \
../libffi/libfficonvenience.la \
-rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS)
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index d4435b6..2002567 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -2466,7 +2466,6 @@ libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
@echo $(libgcj_la_OBJECTS) > libgcj.objectlist;
@echo $(libgcj_la_LIBADD) >> libgcj.objectlist;
$(libgcj_la_LINK) -objectlist libgcj.objectlist \
- ../libstdc++-v3/libsupc++/libsupc++convenience.la \
../libffi/libfficonvenience.la \
-rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS)
diff --git a/libjava/doc/cni.sgml b/libjava/doc/cni.sgml
index 0c82ca6..495e3e9 100644
--- a/libjava/doc/cni.sgml
+++ b/libjava/doc/cni.sgml
@@ -779,6 +779,31 @@ if (i >= count)
throw new java::lang::IndexOutOfBoundsException();
</programlisting>
</para>
+<para>
+Normally, GNU C++ will automatically detect when you are writing C++
+code that uses Java exceptions, and handle them appropriately.
+However, if C++ code only needs to execute destructors when Java
+exceptions are thrown through it, GCC will guess incorrectly. Sample
+problematic code:
+<programlisting>
+ struct S { ~S(); };
+ extern void bar(); // is implemented in Java and may throw exceptions
+ void foo()
+ {
+ S s;
+ bar();
+ }
+</programlisting>
+The usual effect of an incorrect guess is a link failure, complaining of
+a missing routine called <literal>__gxx_personality_v0</literal>.
+</para>
+<para>
+You can inform the compiler that Java exceptions are to be used in a
+translation unit, irrespective of what it might think, by writing
+<literal>#pragma GCC java_exceptions</literal> at the head of the
+file. This <literal>#pragma</literal> must appear before any
+functions that throw or catch exceptions, or run destructors when
+exceptions are thrown through them.</para>
</sect1>
<sect1><title>Synchronization</title>
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 50af756..1e80fbc 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -11,6 +11,9 @@ details. */
#ifndef __JAVA_JVM_H__
#define __JAVA_JVM_H__
+// Force C++ compiler to use Java-style exceptions.
+#pragma GCC java_exceptions
+
#include <gcj/javaprims.h>
#include <java-assert.h>