This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: RFA: Fix java/21045
- From: Bryce McKinlay <mckinlay at redhat dot com>
- To: java-patches at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Wed, 06 Jul 2005 22:28:37 -0400
- Subject: Patch: RFA: Fix java/21045
When an anonymous class is instantiated based on a constructor with a
throws clause, we need to copy the throws clause of the
super-constructor into the new synthetic constructor for the anonymous
class. Currently GCJ does not do this, resulting in an error because a
constructor's throws clause must normally match the constructor it is
overriding.
In addition, it is legal to throw from an anonymous class initializer.
Exceptions thrown from an anonymous class initializer need to be added
to the initializer's throws clause.
One complication here is purge_unchecked_exceptions:
java_complete_expand_method was saving the methods throws list, removing
unchecked exceptions from it, and restoring the throws list later. This
meant that exceptions could not be added to the throws list during
expansion of the method. purge_unchecked_exceptions seems to be
unneccessary, since exception checking code is already testing
IS_UNCHECKED_EXCEPTION_P everywhere that it matters, as far as I can
tell. So I have removed it. There is some further discussion of this
here: http://gcc.gnu.org/ml/java/2001-08/msg00113.html
No testsuite regressions, and 4 new JACKS passes. OK to commit?
Bryce
2005-07-06 Bryce McKinlay <mckinlay@redhat.com>
PR java/21045
* parse.y (add_exception_to_throws): New function.
(purge_unchecked_exceptions): Removed.
(fix_constructors): When building an anonymous inner class
constructor, copy exception signature from the superclass being
overriden.
(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-06 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.
Index: gcc/java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.546
diff -u -r1.546 parse.y
--- gcc/java/parse.y 5 Jul 2005 21:09:44 -0000 1.546
+++ gcc/java/parse.y 7 Jul 2005 00:15:42 -0000
@@ -233,13 +233,13 @@
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 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
}
/* 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 @@
break;
if (arg_type == end_params_node && m_arg_type == end_params_node)
- return 0;
+ return sdecl;
}
}
else
@@ -9182,10 +9181,10 @@
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 @@
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 @@
#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 @@
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'
Index: libjava/testsuite/libjava.compile/PR21045.java
===================================================================
RCS file: libjava/testsuite/libjava.compile/PR21045.java
diff -N libjava/testsuite/libjava.compile/PR21045.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libjava/testsuite/libjava.compile/PR21045.java 7 Jul 2005 00:15:42 -0000
@@ -0,0 +1,11 @@
+public class PR21045
+{
+ class InnerBase {
+ InnerBase() throws Exception, NullPointerException {}
+ }
+ void method() {
+ try {
+ InnerBase obj = new InnerBase() {};
+ } catch (Exception e) {}
+ }
+}
Index: libjava/testsuite/libjava.jacks/jacks.xfail
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/libjava.jacks/jacks.xfail,v
retrieving revision 1.26
diff -u -r1.26 jacks.xfail
--- libjava/testsuite/libjava.jacks/jacks.xfail 6 Jul 2005 15:07:46 -0000 1.26
+++ libjava/testsuite/libjava.jacks/jacks.xfail 7 Jul 2005 00:15:42 -0000
@@ -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