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:
parent
c9ec8f321f
commit
1f730ff7b6
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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. */
|
||||
|
15
gcc/cp/lex.c
15
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 ()
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user