diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/except.c | 62 | ||||
-rw-r--r-- | gcc/cp/lex.c | 15 | ||||
-rw-r--r-- | gcc/extend.texi | 36 |
6 files changed, 107 insertions, 20 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 <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 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 <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. 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 |