Commit 1f730ff7 by Zack Weinberg Committed by Zack Weinberg

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
parent c9ec8f32
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> 2001-05-12 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* c-parse.in (bison parser, init_reswords): Remove uses of * c-parse.in (bison parser, init_reswords): Remove uses of
......
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> 2001-05-12 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* method.c (build_mangled_C99_name): Remove unused prototype. * method.c (build_mangled_C99_name): Remove unused prototype.
......
...@@ -4018,6 +4018,7 @@ extern tree build_throw PARAMS ((tree)); ...@@ -4018,6 +4018,7 @@ extern tree build_throw PARAMS ((tree));
extern void mark_all_runtime_matches PARAMS ((void)); extern void mark_all_runtime_matches PARAMS ((void));
extern int nothrow_libfn_p PARAMS ((tree)); extern int nothrow_libfn_p PARAMS ((tree));
extern void check_handlers PARAMS ((tree)); extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
/* in expr.c */ /* in expr.c */
extern void init_cplus_expand PARAMS ((void)); extern void init_cplus_expand PARAMS ((void));
......
...@@ -43,7 +43,6 @@ static int dtor_nothrow PARAMS ((tree)); ...@@ -43,7 +43,6 @@ static int dtor_nothrow PARAMS ((tree));
static tree do_end_catch PARAMS ((tree)); static tree do_end_catch PARAMS ((tree));
static void push_eh_cleanup PARAMS ((tree)); static void push_eh_cleanup PARAMS ((tree));
static bool decl_is_java_type PARAMS ((tree decl, int err)); 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 void initialize_handler_parm PARAMS ((tree, tree));
static tree do_allocate_exception PARAMS ((tree)); static tree do_allocate_exception PARAMS ((tree));
static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree)); static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
...@@ -259,9 +258,15 @@ decl_is_java_type (decl, err) ...@@ -259,9 +258,15 @@ decl_is_java_type (decl, err)
return r; return r;
} }
static void /* Select the personality routine to be used for exception handling,
choose_personality_routine (is_java) or issue an error if we need two different ones in the same
bool is_java; 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 { static enum {
chose_none, chose_none,
...@@ -272,28 +277,44 @@ choose_personality_routine (is_java) ...@@ -272,28 +277,44 @@ choose_personality_routine (is_java)
switch (state) switch (state)
{ {
case chose_none: case gave_error:
/* We defaulted to C++ in init_exception_processing. return;
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 chose_cpp: case chose_cpp:
if (lang != lang_cplusplus)
goto give_error;
return;
case chose_java: case chose_java:
if (state != (is_java ? chose_java : chose_cpp)) if (lang != lang_java)
{ goto give_error;
error ("mixing C++ and Java catches in a single translation unit"); return;
state = gave_error;
} case chose_none:
; /* proceed to language selection */
}
switch (lang)
{
case lang_cplusplus:
state = chose_cpp;
break; 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; 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. */ /* Initialize the catch parameter DECL. */
...@@ -318,7 +339,8 @@ initialize_handler_parm (decl, exp) ...@@ -318,7 +339,8 @@ initialize_handler_parm (decl, exp)
&& TREE_CODE (init_type) != REFERENCE_TYPE) && TREE_CODE (init_type) != REFERENCE_TYPE)
init_type = build_reference_type (init_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 /* Since pointers are passed by value, initialize a reference to
pointer catch parm with the address of the temporary. */ pointer catch parm with the address of the temporary. */
......
...@@ -61,6 +61,7 @@ static void handle_pragma_vtable PARAMS ((cpp_reader *)); ...@@ -61,6 +61,7 @@ static void handle_pragma_vtable PARAMS ((cpp_reader *));
static void handle_pragma_unit PARAMS ((cpp_reader *)); static void handle_pragma_unit PARAMS ((cpp_reader *));
static void handle_pragma_interface PARAMS ((cpp_reader *)); static void handle_pragma_interface PARAMS ((cpp_reader *));
static void handle_pragma_implementation 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_init PARAMS ((void));
static void cxx_finish PARAMS ((void)); static void cxx_finish PARAMS ((void));
static void cxx_init_options PARAMS ((void)); static void cxx_init_options PARAMS ((void));
...@@ -687,6 +688,8 @@ init_cp_pragma () ...@@ -687,6 +688,8 @@ init_cp_pragma ()
cpp_register_pragma (parse_in, "GCC", "interface", handle_pragma_interface); cpp_register_pragma (parse_in, "GCC", "interface", handle_pragma_interface);
cpp_register_pragma (parse_in, "GCC", "implementation", cpp_register_pragma (parse_in, "GCC", "implementation",
handle_pragma_implementation); handle_pragma_implementation);
cpp_register_pragma (parse_in, "GCC", "java_exceptions",
handle_pragma_java_exceptions);
} }
const char * const char *
...@@ -1181,6 +1184,18 @@ handle_pragma_implementation (dfile) ...@@ -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 void
do_pending_lang_change () do_pending_lang_change ()
{ {
......
...@@ -3811,6 +3811,7 @@ Predefined Macros,cpp.info,The C Preprocessor}). ...@@ -3811,6 +3811,7 @@ Predefined Macros,cpp.info,The C Preprocessor}).
* Bound member functions:: You can extract a function pointer to the * Bound member functions:: You can extract a function pointer to the
method denoted by a @samp{->*} or @samp{.*} expression. method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Attributes:: Variable, function, and type attributes for C++ only. * 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++. * Deprecated Features:: Things might disappear from g++.
* Backwards Compatibility:: Compatibilities with earlier definitions of C++. * Backwards Compatibility:: Compatibilities with earlier definitions of C++.
@end menu @end menu
...@@ -4380,6 +4381,41 @@ interface table mechanism, instead of regular virtual table dispatch. ...@@ -4380,6 +4381,41 @@ interface table mechanism, instead of regular virtual table dispatch.
@end table @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 @node Deprecated Features
@section Deprecated Features @section Deprecated Features
......
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> 2001-05-11 Richard Henderson <rth@redhat.com>
* configure.in (ia64-*): Don't set SYSDEP_SOURCES. * configure.in (ia64-*): Don't set SYSDEP_SOURCES.
......
...@@ -260,7 +260,6 @@ libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES) ...@@ -260,7 +260,6 @@ libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
@echo $(libgcj_la_OBJECTS) > libgcj.objectlist; @echo $(libgcj_la_OBJECTS) > libgcj.objectlist;
@echo $(libgcj_la_LIBADD) >> libgcj.objectlist; @echo $(libgcj_la_LIBADD) >> libgcj.objectlist;
$(libgcj_la_LINK) -objectlist libgcj.objectlist \ $(libgcj_la_LINK) -objectlist libgcj.objectlist \
../libstdc++-v3/libsupc++/libsupc++convenience.la \
../libffi/libfficonvenience.la \ ../libffi/libfficonvenience.la \
-rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS) -rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS)
......
...@@ -2466,7 +2466,6 @@ libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES) ...@@ -2466,7 +2466,6 @@ libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
@echo $(libgcj_la_OBJECTS) > libgcj.objectlist; @echo $(libgcj_la_OBJECTS) > libgcj.objectlist;
@echo $(libgcj_la_LIBADD) >> libgcj.objectlist; @echo $(libgcj_la_LIBADD) >> libgcj.objectlist;
$(libgcj_la_LINK) -objectlist libgcj.objectlist \ $(libgcj_la_LINK) -objectlist libgcj.objectlist \
../libstdc++-v3/libsupc++/libsupc++convenience.la \
../libffi/libfficonvenience.la \ ../libffi/libfficonvenience.la \
-rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS) -rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS)
......
...@@ -779,6 +779,31 @@ if (i >= count) ...@@ -779,6 +779,31 @@ if (i >= count)
throw new java::lang::IndexOutOfBoundsException(); throw new java::lang::IndexOutOfBoundsException();
</programlisting> </programlisting>
</para> </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>
<sect1><title>Synchronization</title> <sect1><title>Synchronization</title>
......
...@@ -11,6 +11,9 @@ details. */ ...@@ -11,6 +11,9 @@ details. */
#ifndef __JAVA_JVM_H__ #ifndef __JAVA_JVM_H__
#define __JAVA_JVM_H__ #define __JAVA_JVM_H__
// Force C++ compiler to use Java-style exceptions.
#pragma GCC java_exceptions
#include <gcj/javaprims.h> #include <gcj/javaprims.h>
#include <java-assert.h> #include <java-assert.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment