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
This commit is contained in:
Zack Weinberg 2001-05-13 01:28:18 +00:00 committed by Zack Weinberg
parent c9ec8f321f
commit 1f730ff7b6
11 changed files with 142 additions and 22 deletions

View File

@ -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

View File

@ -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.

View File

@ -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));

View File

@ -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. */

View File

@ -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 ()
{

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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>

View File

@ -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>