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
This commit is contained in:
parent
b52110d478
commit
ca12deb43e
@ -1,3 +1,15 @@
|
||||
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>
|
||||
|
||||
PR java/19674
|
||||
|
110
gcc/java/parse.y
110
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'
|
||||
|
@ -1,3 +1,9 @@
|
||||
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>
|
||||
|
||||
* java/io/InputStreamReader.java (refill): Handle no-progress
|
||||
|
11
libjava/testsuite/libjava.compile/PR21045.java
Normal file
11
libjava/testsuite/libjava.compile/PR21045.java
Normal file
@ -0,0 +1,11 @@
|
||||
public class PR21045
|
||||
{
|
||||
class InnerBase {
|
||||
InnerBase() throws Exception, NullPointerException {}
|
||||
}
|
||||
void method() {
|
||||
try {
|
||||
InnerBase obj = new InnerBase() {};
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user