Commit ca12deb4 by Bryce McKinlay Committed by Bryce McKinlay

re PR java/21045 (Anonymous inner class constructor's exceptions can't be caught or thrown)

2005-07-07  Bryce McKinlay  <mckinlay@redhat.com>

        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-07  Bryce McKinlay  <mckinlay@redhat.com>

        * 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.

From-SVN: r101713
parent b52110d4
2005-07-07 Bryce McKinlay <mckinlay@redhat.com>
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 <mckinlay@redhat.com> 2005-07-05 Bryce McKinlay <mckinlay@redhat.com>
PR java/19674 PR java/19674
......
...@@ -233,13 +233,13 @@ static tree build_try_finally_statement (int, tree, tree); ...@@ -233,13 +233,13 @@ static tree build_try_finally_statement (int, tree, tree);
static tree patch_try_statement (tree); static tree patch_try_statement (tree);
static tree patch_synchronized_statement (tree, tree); static tree patch_synchronized_statement (tree, tree);
static tree patch_throw_statement (tree, tree); static tree patch_throw_statement (tree, tree);
static void add_exception_to_throws (tree, tree);
#ifdef USE_MAPPED_LOCATION #ifdef USE_MAPPED_LOCATION
static void check_thrown_exceptions (source_location, tree, tree); static void check_thrown_exceptions (source_location, tree, tree);
#else #else
static void check_thrown_exceptions (int, tree, tree); static void check_thrown_exceptions (int, tree, tree);
#endif #endif
static int check_thrown_exceptions_do (tree); static int check_thrown_exceptions_do (tree);
static void purge_unchecked_exceptions (tree);
static bool ctors_unchecked_throws_clause_p (tree); static bool ctors_unchecked_throws_clause_p (tree);
static void check_concrete_throws_clauses (tree, tree, tree, tree); static void check_concrete_throws_clauses (tree, tree, tree, tree);
static void check_throws_clauses (tree, tree, tree); static void check_throws_clauses (tree, tree, tree);
...@@ -256,7 +256,7 @@ static tree build_instinit_invocation (tree); ...@@ -256,7 +256,7 @@ static tree build_instinit_invocation (tree);
static void fix_constructors (tree); static void fix_constructors (tree);
static tree build_alias_initializer_parameter_list (int, tree, tree, int *); static tree build_alias_initializer_parameter_list (int, tree, tree, int *);
static tree craft_constructor (tree, tree); 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 tree create_artificial_method (tree, int, tree, tree, tree);
static void start_artificial_method_body (tree); static void start_artificial_method_body (tree);
static void end_artificial_method_body (tree); static void end_artificial_method_body (tree);
...@@ -2082,7 +2082,7 @@ anonymous_class_creation: ...@@ -2082,7 +2082,7 @@ anonymous_class_creation:
must be generated following the hints provided by must be generated following the hints provided by
the `new' expression. Whether a super constructor the `new' expression. Whether a super constructor
of that nature exists or not is to be verified 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 It's during the expansion of a `new' statement
referring to an anonymous class that a ctor will referring to an anonymous class that a ctor will
...@@ -8161,11 +8161,6 @@ java_complete_expand_method (tree mdecl) ...@@ -8161,11 +8161,6 @@ java_complete_expand_method (tree mdecl)
current_this = (!METHOD_STATIC (mdecl) ? current_this = (!METHOD_STATIC (mdecl) ?
BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE); 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' */ /* Install exceptions thrown with `throws' */
PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl)); PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl));
...@@ -8223,9 +8218,6 @@ java_complete_expand_method (tree mdecl) ...@@ -8223,9 +8218,6 @@ java_complete_expand_method (tree mdecl)
POP_EXCEPTIONS(); POP_EXCEPTIONS();
if (currently_caught_type_list) if (currently_caught_type_list)
abort (); 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. */ /* For with each class for which there's code to generate. */
...@@ -9038,7 +9030,8 @@ fix_constructors (tree mdecl) ...@@ -9038,7 +9030,8 @@ fix_constructors (tree mdecl)
/* It is an error for the compiler to generate a default /* It is an error for the compiler to generate a default
constructor if the superclass doesn't have a constructor that constructor if the superclass doesn't have a constructor that
takes no argument, or the same args for an anonymous class */ 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 sclass_decl = TYPE_NAME (CLASSTYPE_SUPER (class_type));
tree save = DECL_NAME (mdecl); tree save = DECL_NAME (mdecl);
...@@ -9051,6 +9044,13 @@ fix_constructors (tree mdecl) ...@@ -9051,6 +9044,13 @@ fix_constructors (tree mdecl)
DECL_NAME (mdecl) = save; 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 /* The constructor body must be crafted by hand. It's the
constructor we defined when we realize we didn't have the constructor we defined when we realize we didn't have the
CLASSNAME() constructor */ CLASSNAME() constructor */
...@@ -9135,19 +9135,18 @@ fix_constructors (tree mdecl) ...@@ -9135,19 +9135,18 @@ fix_constructors (tree mdecl)
} }
/* Browse constructors in the super class, searching for a constructor /* Browse constructors in the super class, searching for a constructor
that doesn't take any argument. Return 0 if one is found, 1 that doesn't take any argument. Return the constructor if one is found,
otherwise. If the current class is an anonymous inner class, look NULL_TREE otherwise. If the current class is an anonymous inner class,
for something that has the same signature. */ look for something that has the same signature. */
static tree
static int get_constructor_super (tree mdecl)
verify_constructor_super (tree mdecl)
{ {
tree class = CLASSTYPE_SUPER (current_class); tree class = CLASSTYPE_SUPER (current_class);
int super_inner = PURE_INNER_CLASS_TYPE_P (class); int super_inner = PURE_INNER_CLASS_TYPE_P (class);
tree sdecl; tree sdecl;
if (!class) if (!class)
return 0; return NULL_TREE;
if (ANONYMOUS_CLASS_P (current_class)) if (ANONYMOUS_CLASS_P (current_class))
{ {
...@@ -9171,7 +9170,7 @@ verify_constructor_super (tree mdecl) ...@@ -9171,7 +9170,7 @@ verify_constructor_super (tree mdecl)
break; break;
if (arg_type == end_params_node && m_arg_type == end_params_node) if (arg_type == end_params_node && m_arg_type == end_params_node)
return 0; return sdecl;
} }
} }
else else
...@@ -9182,10 +9181,10 @@ verify_constructor_super (tree mdecl) ...@@ -9182,10 +9181,10 @@ verify_constructor_super (tree mdecl)
if (super_inner) if (super_inner)
arg = TREE_CHAIN (arg); arg = TREE_CHAIN (arg);
if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node) 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. */ /* Generate code for all context remembered for code generation. */
...@@ -15911,6 +15910,34 @@ patch_throw_statement (tree node, tree wfl_op1) ...@@ -15911,6 +15910,34 @@ patch_throw_statement (tree node, tree wfl_op1)
return node; 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 /* Check that exception said to be thrown by method DECL can be
effectively caught from where DECL is invoked. THIS_EXPR is the effectively caught from where DECL is invoked. THIS_EXPR is the
expression that computes `this' for the method call. */ expression that computes `this' for the method call. */
...@@ -15950,10 +15977,21 @@ check_thrown_exceptions ( ...@@ -15950,10 +15977,21 @@ check_thrown_exceptions (
#else #else
EXPR_WFL_LINECOL (wfl_operator) = location; EXPR_WFL_LINECOL (wfl_operator) = location;
#endif #endif
if (DECL_FINIT_P (current_function_decl)) if (ANONYMOUS_CLASS_P (DECL_CONTEXT (current_function_decl))
parse_error_context && (DECL_FINIT_P (current_function_decl)
(wfl_operator, "Exception %qs can't be thrown in initializer", || DECL_INIT_P (current_function_decl)
lang_printable_name (TREE_VALUE (throws), 0)); || 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 else
{ {
parse_error_context parse_error_context
...@@ -15990,26 +16028,6 @@ check_thrown_exceptions_do (tree exception) ...@@ -15990,26 +16028,6 @@ check_thrown_exceptions_do (tree exception)
return 0; 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 /* This function goes over all of CLASS_TYPE ctors and checks whether
each of them features at least one unchecked exception in its each of them features at least one unchecked exception in its
`throws' clause. If it's the case, it returns `true', `false' `throws' clause. If it's the case, it returns `true', `false'
......
2005-07-07 Bryce McKinlay <mckinlay@redhat.com>
* 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 <tromey@redhat.com> 2005-07-06 Tom Tromey <tromey@redhat.com>
* java/io/InputStreamReader.java (refill): Handle no-progress * java/io/InputStreamReader.java (refill): Handle no-progress
......
public class PR21045
{
class InnerBase {
InnerBase() throws Exception, NullPointerException {}
}
void method() {
try {
InnerBase obj = new InnerBase() {};
} catch (Exception e) {}
}
}
...@@ -347,8 +347,6 @@ ...@@ -347,8 +347,6 @@
15.9.4-runtime-creation-1 15.9.4-runtime-creation-1
15.9.4-runtime-creation-2 15.9.4-runtime-creation-2
15.9.4-runtime-creation-5 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-exception-4
15.9.5.1-superconstructor-7 15.9.5.1-superconstructor-7
15.9.5.1-superconstructor-8 15.9.5.1-superconstructor-8
...@@ -563,8 +561,6 @@ ...@@ -563,8 +561,6 @@
8.3.1.2-final-29 8.3.1.2-final-29
8.3.2-abrupt-3 8.3.2-abrupt-3
8.3.2-abrupt-5 8.3.2-abrupt-5
8.3.2-abrupt-6
8.3.2-abrupt-7
8.3.2.2-super-2 8.3.2.2-super-2
8.3.2.3-illegal-forward-instance-1 8.3.2.3-illegal-forward-instance-1
8.3.2.3-illegal-forward-instance-2 8.3.2.3-illegal-forward-instance-2
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment