diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index bb7f08a6e74..88284867b65 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,15 @@ +2005-07-07 Bryce McKinlay + + PR java/21045 + * parse.y (add_exception_to_throws): New function. + (purge_unchecked_exceptions): Removed. + (get_constructor_super): Renamed from verify_constructor_super. Now + returns the super constructor after verification. + (java_complete_expand_method): Don't use purge_unchecked_exceptions + or save/restore the exception list. + (check_thrown_exceptions): Add uncaught exceptions in anonymous + class initializers and constructors to the throws clause of the method. + 2005-07-05 Bryce McKinlay PR java/19674 diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 89e3e6e05e2..9a094e5d61b 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -233,13 +233,13 @@ static tree build_try_finally_statement (int, tree, tree); static tree patch_try_statement (tree); static tree patch_synchronized_statement (tree, tree); static tree patch_throw_statement (tree, tree); +static void add_exception_to_throws (tree, tree); #ifdef USE_MAPPED_LOCATION static void check_thrown_exceptions (source_location, tree, tree); #else static void check_thrown_exceptions (int, tree, tree); #endif static int check_thrown_exceptions_do (tree); -static void purge_unchecked_exceptions (tree); static bool ctors_unchecked_throws_clause_p (tree); static void check_concrete_throws_clauses (tree, tree, tree, tree); static void check_throws_clauses (tree, tree, tree); @@ -256,7 +256,7 @@ static tree build_instinit_invocation (tree); static void fix_constructors (tree); static tree build_alias_initializer_parameter_list (int, tree, tree, int *); static tree craft_constructor (tree, tree); -static int verify_constructor_super (tree); +static tree get_constructor_super (tree); static tree create_artificial_method (tree, int, tree, tree, tree); static void start_artificial_method_body (tree); static void end_artificial_method_body (tree); @@ -2082,7 +2082,7 @@ anonymous_class_creation: must be generated following the hints provided by the `new' expression. Whether a super constructor of that nature exists or not is to be verified - later on in verify_constructor_super. + later on in get_constructor_super. It's during the expansion of a `new' statement referring to an anonymous class that a ctor will @@ -8161,11 +8161,6 @@ java_complete_expand_method (tree mdecl) current_this = (!METHOD_STATIC (mdecl) ? BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE); - /* Purge the `throws' list of unchecked exceptions (we save a copy - of the list and re-install it later.) */ - exception_copy = copy_list (DECL_FUNCTION_THROWS (mdecl)); - purge_unchecked_exceptions (mdecl); - /* Install exceptions thrown with `throws' */ PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl)); @@ -8223,9 +8218,6 @@ java_complete_expand_method (tree mdecl) POP_EXCEPTIONS(); if (currently_caught_type_list) abort (); - - /* Restore the copy of the list of exceptions. */ - DECL_FUNCTION_THROWS (mdecl) = exception_copy; } /* For with each class for which there's code to generate. */ @@ -9038,7 +9030,8 @@ fix_constructors (tree mdecl) /* It is an error for the compiler to generate a default constructor if the superclass doesn't have a constructor that takes no argument, or the same args for an anonymous class */ - if (verify_constructor_super (mdecl)) + tree sdecl = get_constructor_super (mdecl); + if (sdecl == NULL_TREE) { tree sclass_decl = TYPE_NAME (CLASSTYPE_SUPER (class_type)); tree save = DECL_NAME (mdecl); @@ -9051,6 +9044,13 @@ fix_constructors (tree mdecl) DECL_NAME (mdecl) = save; } + if (ANONYMOUS_CLASS_P (class_type)) + { + /* Copy throws clause from the super constructor. */ + tree throws = DECL_FUNCTION_THROWS (sdecl); + DECL_FUNCTION_THROWS (mdecl) = copy_list (throws); + } + /* The constructor body must be crafted by hand. It's the constructor we defined when we realize we didn't have the CLASSNAME() constructor */ @@ -9135,19 +9135,18 @@ fix_constructors (tree mdecl) } /* Browse constructors in the super class, searching for a constructor - that doesn't take any argument. Return 0 if one is found, 1 - otherwise. If the current class is an anonymous inner class, look - for something that has the same signature. */ - -static int -verify_constructor_super (tree mdecl) + that doesn't take any argument. Return the constructor if one is found, + NULL_TREE otherwise. If the current class is an anonymous inner class, + look for something that has the same signature. */ +static tree +get_constructor_super (tree mdecl) { tree class = CLASSTYPE_SUPER (current_class); int super_inner = PURE_INNER_CLASS_TYPE_P (class); tree sdecl; if (!class) - return 0; + return NULL_TREE; if (ANONYMOUS_CLASS_P (current_class)) { @@ -9171,7 +9170,7 @@ verify_constructor_super (tree mdecl) break; if (arg_type == end_params_node && m_arg_type == end_params_node) - return 0; + return sdecl; } } else @@ -9182,10 +9181,10 @@ verify_constructor_super (tree mdecl) if (super_inner) arg = TREE_CHAIN (arg); if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node) - return 0; + return sdecl; } } - return 1; + return NULL_TREE; } /* Generate code for all context remembered for code generation. */ @@ -15911,6 +15910,34 @@ patch_throw_statement (tree node, tree wfl_op1) return node; } +/* Add EXCEPTION to the throws clause of MDECL. If MDECL already throws + a super-class of EXCEPTION, keep the superclass instead. If MDECL already + throws a sub-class of EXCEPTION, replace the sub-class with EXCEPTION. */ +static void +add_exception_to_throws (tree mdecl, tree exception) +{ + tree mthrows; + + /* Ignore unchecked exceptions. */ + if (IS_UNCHECKED_EXCEPTION_P (exception)) + return; + + for (mthrows = DECL_FUNCTION_THROWS (mdecl); + mthrows; mthrows = TREE_CHAIN (mthrows)) + { + if (inherits_from_p (exception, TREE_VALUE (mthrows))) + return; + if (inherits_from_p (TREE_VALUE (mthrows), exception)) + { + TREE_VALUE (mthrows) = exception; + return; + } + } + + mthrows = DECL_FUNCTION_THROWS (mdecl); + DECL_FUNCTION_THROWS (mdecl) = build_tree_list (mthrows, exception); +} + /* Check that exception said to be thrown by method DECL can be effectively caught from where DECL is invoked. THIS_EXPR is the expression that computes `this' for the method call. */ @@ -15950,10 +15977,21 @@ check_thrown_exceptions ( #else EXPR_WFL_LINECOL (wfl_operator) = location; #endif - if (DECL_FINIT_P (current_function_decl)) - parse_error_context - (wfl_operator, "Exception %qs can't be thrown in initializer", - lang_printable_name (TREE_VALUE (throws), 0)); + if (ANONYMOUS_CLASS_P (DECL_CONTEXT (current_function_decl)) + && (DECL_FINIT_P (current_function_decl) + || DECL_INIT_P (current_function_decl) + || DECL_CONSTRUCTOR_P (current_function_decl))) + { + /* Add "throws" to the initializer's exception list */ + tree exception = TREE_VALUE (throws); + add_exception_to_throws (current_function_decl, exception); + } + else if (DECL_FINIT_P (current_function_decl)) + { + parse_error_context + (wfl_operator, "Exception %qs can't be thrown in initializer", + lang_printable_name (TREE_VALUE (throws), 0)); + } else { parse_error_context @@ -15990,26 +16028,6 @@ check_thrown_exceptions_do (tree exception) return 0; } -static void -purge_unchecked_exceptions (tree mdecl) -{ - tree throws = DECL_FUNCTION_THROWS (mdecl); - tree new = NULL_TREE; - - while (throws) - { - tree next = TREE_CHAIN (throws); - if (!IS_UNCHECKED_EXCEPTION_P (TREE_VALUE (throws))) - { - TREE_CHAIN (throws) = new; - new = throws; - } - throws = next; - } - /* List is inverted here, but it doesn't matter */ - DECL_FUNCTION_THROWS (mdecl) = new; -} - /* This function goes over all of CLASS_TYPE ctors and checks whether each of them features at least one unchecked exception in its `throws' clause. If it's the case, it returns `true', `false' diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 657e238d879..e0825bbc4ea 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,9 @@ +2005-07-07 Bryce McKinlay + + * testsuite/libjava.compile/PR21045.java: New test. + * testsuite/libjava.jacks/jacks.xfail: Remove 15.9.5.1-exception-1, + 15.9.5.1-exception-3, 8.3.2-abrupt-6, 8.3.2-abrupt-7. + 2005-07-06 Tom Tromey * java/io/InputStreamReader.java (refill): Handle no-progress diff --git a/libjava/testsuite/libjava.compile/PR21045.java b/libjava/testsuite/libjava.compile/PR21045.java new file mode 100644 index 00000000000..3d34ee1f304 --- /dev/null +++ b/libjava/testsuite/libjava.compile/PR21045.java @@ -0,0 +1,11 @@ +public class PR21045 +{ + class InnerBase { + InnerBase() throws Exception, NullPointerException {} + } + void method() { + try { + InnerBase obj = new InnerBase() {}; + } catch (Exception e) {} + } +} diff --git a/libjava/testsuite/libjava.jacks/jacks.xfail b/libjava/testsuite/libjava.jacks/jacks.xfail index b8ac229b62f..68af018a5f4 100644 --- a/libjava/testsuite/libjava.jacks/jacks.xfail +++ b/libjava/testsuite/libjava.jacks/jacks.xfail @@ -347,8 +347,6 @@ 15.9.4-runtime-creation-1 15.9.4-runtime-creation-2 15.9.4-runtime-creation-5 -15.9.5.1-exception-1 -15.9.5.1-exception-3 15.9.5.1-exception-4 15.9.5.1-superconstructor-7 15.9.5.1-superconstructor-8 @@ -563,8 +561,6 @@ 8.3.1.2-final-29 8.3.2-abrupt-3 8.3.2-abrupt-5 -8.3.2-abrupt-6 -8.3.2-abrupt-7 8.3.2.2-super-2 8.3.2.3-illegal-forward-instance-1 8.3.2.3-illegal-forward-instance-2