From 6df8a9dd552113f43274ba4bf09830d2525ff4e9 Mon Sep 17 00:00:00 2001 From: zack Date: Sun, 13 May 2001 01:28:18 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42027 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 4 ++++ gcc/cp/ChangeLog | 9 ++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/except.c | 62 ++++++++++++++++++++++++++++++++++----------------- gcc/cp/lex.c | 15 +++++++++++++ gcc/extend.texi | 36 ++++++++++++++++++++++++++++++ libjava/ChangeLog | 7 ++++++ libjava/Makefile.am | 1 - libjava/Makefile.in | 1 - libjava/doc/cni.sgml | 25 +++++++++++++++++++++ libjava/include/jvm.h | 3 +++ 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 + + * extend.texi: Document #pragma GCC java_exceptions. + 2001-05-12 Neil Booth * 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 + + * 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 * 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 + + * 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 * configure.in (ia64-*): Don't set SYSDEP_SOURCES. diff --git a/libjava/Makefile.am b/libjava/Makefile.am index d5644a1..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(); + +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: + + struct S { ~S(); }; + extern void bar(); // is implemented in Java and may throw exceptions + void foo() + { + S s; + bar(); + } + +The usual effect of an incorrect guess is a link failure, complaining of +a missing routine called __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 +#pragma GCC java_exceptions at the head of the +file. This #pragma must appear before any +functions that throw or catch exceptions, or run destructors when +exceptions are thrown through them. Synchronization 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 #include -- 2.7.4