mirror of git://gcc.gnu.org/git/gcc.git
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>
|
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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
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));
|
||||||
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));
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
case gave_error:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case chose_cpp:
|
||||||
|
if (lang != lang_cplusplus)
|
||||||
|
goto give_error;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case chose_java:
|
||||||
|
if (lang != lang_java)
|
||||||
|
goto give_error;
|
||||||
|
return;
|
||||||
|
|
||||||
case chose_none:
|
case chose_none:
|
||||||
/* We defaulted to C++ in init_exception_processing.
|
; /* proceed to language selection */
|
||||||
Reconfigure for Java if we changed our minds. */
|
}
|
||||||
if (is_java)
|
|
||||||
|
switch (lang)
|
||||||
|
{
|
||||||
|
case lang_cplusplus:
|
||||||
|
state = chose_cpp;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case lang_java:
|
||||||
|
state = chose_java;
|
||||||
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
|
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
|
||||||
? "__gcj_personality_sj0"
|
? "__gcj_personality_sj0"
|
||||||
: "__gcj_personality_v0");
|
: "__gcj_personality_v0");
|
||||||
state = (is_java ? chose_java : chose_cpp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case chose_cpp:
|
default:
|
||||||
case chose_java:
|
abort ();
|
||||||
if (state != (is_java ? chose_java : chose_cpp))
|
}
|
||||||
{
|
return;
|
||||||
|
|
||||||
|
give_error:
|
||||||
error ("mixing C++ and Java catches in a single translation unit");
|
error ("mixing C++ and Java catches in a single translation unit");
|
||||||
state = gave_error;
|
state = gave_error;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case gave_error:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the catch parameter DECL. */
|
/* Initialize the catch parameter DECL. */
|
||||||
|
|
@ -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. */
|
||||||
|
|
|
||||||
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_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 ()
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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}).
|
||||||
* 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.
|
||||||
|
|
||||||
@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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
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)
|
||||||
@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)
|
||||||
@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)
|
||||||
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. */
|
||||||
#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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue