aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Sturm <jsturm@one-point.com>2003-11-18 03:57:08 +0000
committerJeff Sturm <jsturm@gcc.gnu.org>2003-11-18 03:57:08 +0000
commitb8ca854ad184062c5fb41768804d73a8b18d28b4 (patch)
treef2c4076691ff089f645cb3ea0584d76a88894787
parenta78e4fa7643f1264968e86476a2f39a2a241f202 (diff)
downloadgcc-b8ca854ad184062c5fb41768804d73a8b18d28b4.zip
gcc-b8ca854ad184062c5fb41768804d73a8b18d28b4.tar.gz
gcc-b8ca854ad184062c5fb41768804d73a8b18d28b4.tar.bz2
re PR java/12857 (Illegal method modifier when loading a generated .class)
Fix PR java/12857. decl.c (java_init_decl_processing): Don't initialize class_not_found_type_node, no_class_def_found_type_node. java-tree.h (JTI_CLASS_NOT_FOUND_TYPE_NODE, JTI_NO_CLASS_DEF_FOUND_TYPE_NODE): Remove from java_tree_index. (class_not_found_type_node, no_class_def_found_type_node): Don't define. parse.y (build_dot_class_method_invocation): Add this_class argument. Qualify method invocations to a different class. (create_new_parser_context): Initialize saved_data_ctx to 0. (java_parser_context_save_global): Initialize saved_data_ctx to 1. (build_dot_class_method): Don't load classes. Register incomplete types. (build_incomplete_class_ref): Special cases for interfaces and inner classes. Move build_dot_class_method call to here... (patch_incomplete_class_ref): ...from here. Pass current_class to build_dot_class_method_invocation. (build_assertion): Pass class_type to build_dot_class_method_invocation. (encapsulate_with_try_catch): Handle EXPR_WITH_FILE_LOCATION node. From-SVN: r73691
-rw-r--r--gcc/java/ChangeLog26
-rw-r--r--gcc/java/decl.c4
-rw-r--r--gcc/java/java-tree.h6
-rw-r--r--gcc/java/parse.y109
4 files changed, 110 insertions, 35 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 995b21a..ea30c77 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,5 +1,31 @@
2003-11-17 Jeff Sturm <jsturm@one-point.com>
+ Fix PR java/12857.
+
+ decl.c (java_init_decl_processing): Don't initialize
+ class_not_found_type_node, no_class_def_found_type_node.
+
+ java-tree.h (JTI_CLASS_NOT_FOUND_TYPE_NODE,
+ JTI_NO_CLASS_DEF_FOUND_TYPE_NODE): Remove from java_tree_index.
+ (class_not_found_type_node, no_class_def_found_type_node):
+ Don't define.
+
+ parse.y (build_dot_class_method_invocation): Add this_class
+ argument. Qualify method invocations to a different class.
+ (create_new_parser_context): Initialize saved_data_ctx to 0.
+ (java_parser_context_save_global): Initialize saved_data_ctx to 1.
+ (build_dot_class_method): Don't load classes. Register
+ incomplete types.
+ (build_incomplete_class_ref): Special cases for interfaces
+ and inner classes. Move build_dot_class_method call to here...
+ (patch_incomplete_class_ref): ...from here. Pass current_class
+ to build_dot_class_method_invocation.
+ (build_assertion): Pass class_type to
+ build_dot_class_method_invocation.
+ (encapsulate_with_try_catch): Handle EXPR_WITH_FILE_LOCATION node.
+
+2003-11-17 Jeff Sturm <jsturm@one-point.com>
+
Fix PR java/12739.
* java-tree.h (BLOCK_EMPTY_P): Define.
* parse.y (java_complete_lhs): Check for empty blocks
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 4b0c496..b8f09e1 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -553,10 +553,6 @@ java_init_decl_processing (void)
lookup_class (get_identifier ("java.lang.RuntimeException"));
error_exception_type_node =
lookup_class (get_identifier ("java.lang.Error"));
- class_not_found_type_node =
- lookup_class (get_identifier ("java.lang.ClassNotFoundException"));
- no_class_def_found_type_node =
- lookup_class (get_identifier ("java.lang.NoClassDefFoundError"));
rawdata_ptr_type_node
= promote_type (lookup_class (get_identifier ("gnu.gcj.RawData")));
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index eb0db48..2c706c9 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -308,8 +308,6 @@ enum java_tree_index
JTI_RUNTIME_EXCEPTION_TYPE_NODE,
JTI_ERROR_EXCEPTION_TYPE_NODE,
JTI_RAWDATA_PTR_TYPE_NODE,
- JTI_CLASS_NOT_FOUND_TYPE_NODE,
- JTI_NO_CLASS_DEF_FOUND_TYPE_NODE,
JTI_BYTE_ARRAY_TYPE_NODE,
JTI_SHORT_ARRAY_TYPE_NODE,
@@ -492,10 +490,6 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
java_global_trees[JTI_ERROR_EXCEPTION_TYPE_NODE]
#define rawdata_ptr_type_node \
java_global_trees[JTI_RAWDATA_PTR_TYPE_NODE]
-#define class_not_found_type_node \
- java_global_trees[JTI_CLASS_NOT_FOUND_TYPE_NODE]
-#define no_class_def_found_type_node \
- java_global_trees[JTI_NO_CLASS_DEF_FOUND_TYPE_NODE]
#define byte_array_type_node \
java_global_trees[JTI_BYTE_ARRAY_TYPE_NODE]
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index 375e7ec..5613c87 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -326,7 +326,7 @@ static void patch_anonymous_class (tree, tree, tree);
static void add_inner_class_fields (tree, tree);
static tree build_dot_class_method (tree);
-static tree build_dot_class_method_invocation (tree);
+static tree build_dot_class_method_invocation (tree, tree);
static void create_new_parser_context (int);
static tree maybe_build_class_init_for_field (tree, tree);
@@ -2660,7 +2660,9 @@ create_new_parser_context (int copy_from_previous)
if (copy_from_previous)
{
memcpy (new, ctxp, sizeof (struct parser_ctxt));
- new->saved_data_ctx = 1;
+ /* This flag, indicating the context saves global values,
+ should only be set by java_parser_context_save_global. */
+ new->saved_data_ctx = 0;
}
else
memset (new, 0, sizeof (struct parser_ctxt));
@@ -2733,7 +2735,10 @@ java_parser_context_save_global (void)
/* If this context already stores data, create a new one suitable
for data storage. */
else if (ctxp->saved_data)
- create_new_parser_context (1);
+ {
+ create_new_parser_context (1);
+ ctxp->saved_data_ctx = 1;
+ }
ctxp->lineno = input_line;
ctxp->class_type = current_class;
@@ -8724,7 +8729,7 @@ build_dot_class_method (tree class)
{
#define BWF(S) build_wfl_node (get_identifier ((S)))
#define MQN(X,Y) make_qualified_name ((X), (Y), 0)
- tree args, tmp, saved_current_function_decl, mdecl;
+ tree args, tmp, saved_current_function_decl, mdecl, qual_name;
tree stmt, throw_stmt;
if (!get_message_wfl)
@@ -8741,15 +8746,17 @@ build_dot_class_method (tree class)
/* Build the qualified name java.lang.Class.forName */
tmp = MQN (MQN (MQN (BWF ("java"),
BWF ("lang")), BWF ("Class")), BWF ("forName"));
- load_class (class_not_found_type_node, 1);
- load_class (no_class_def_found_type_node, 1);
/* Create the "class$" function */
mdecl = create_artificial_method (class, ACC_STATIC,
build_pointer_type (class_type_node),
classdollar_identifier_node, args);
- DECL_FUNCTION_THROWS (mdecl) =
- build_tree_list (NULL_TREE, no_class_def_found_type_node);
+ qual_name = MQN (MQN (BWF ("java"), BWF ("lang")),
+ BWF ("NoClassDefFoundError"));
+ DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE, qual_name);
+ register_incomplete_type (JDEP_EXCEPTION, qual_name, NULL_TREE, NULL_TREE);
+ JDEP_GET_PATCH (CLASSD_LAST (ctxp->classd_list)) =
+ &TREE_VALUE (DECL_FUNCTION_THROWS (mdecl));
/* We start by building the try block. We need to build:
return (java.lang.Class.forName (type)); */
@@ -8772,8 +8779,9 @@ build_dot_class_method (tree class)
throw_stmt = build1 (THROW_EXPR, NULL_TREE, throw_stmt);
/* Encapsulate STMT in a try block. The catch clause executes THROW_STMT */
- stmt = encapsulate_with_try_catch (0, class_not_found_type_node,
- stmt, throw_stmt);
+ qual_name = MQN (MQN (BWF ("java"), BWF ("lang")),
+ BWF ("ClassNotFoundException"));
+ stmt = encapsulate_with_try_catch (0, qual_name, stmt, throw_stmt);
fix_method_argument_names (args, mdecl);
layout_class_method (class, NULL_TREE, mdecl, NULL_TREE);
@@ -8788,9 +8796,10 @@ build_dot_class_method (tree class)
}
static tree
-build_dot_class_method_invocation (tree type)
+build_dot_class_method_invocation (tree this_class, tree type)
{
- tree sig_id, s;
+ tree dot_class_method = TYPE_DOT_CLASS (this_class);
+ tree sig_id, s, t;
if (TYPE_ARRAY_P (type))
sig_id = build_java_signature (type);
@@ -8803,8 +8812,14 @@ build_dot_class_method_invocation (tree type)
s = build_string (IDENTIFIER_LENGTH (sig_id),
IDENTIFIER_POINTER (sig_id));
- return build_method_invocation (build_wfl_node (classdollar_identifier_node),
- build_tree_list (NULL_TREE, s));
+ t = build_method_invocation (build_wfl_node (DECL_NAME (dot_class_method)),
+ build_tree_list (NULL_TREE, s));
+ if (DECL_CONTEXT (dot_class_method) != this_class)
+ {
+ tree class_name = DECL_NAME (TYPE_NAME (DECL_CONTEXT (dot_class_method)));
+ t = make_qualified_primary (build_wfl_node (class_name), t, 0);
+ }
+ return t;
}
/* This section of the code deals with constructor. */
@@ -14099,6 +14114,44 @@ static tree
build_incomplete_class_ref (int location, tree class_name)
{
tree node = build1 (CLASS_LITERAL, NULL_TREE, class_name);
+ tree class_decl = GET_CPC ();
+ tree this_class = TREE_TYPE (class_decl);
+
+ /* Generate the synthetic static method `class$'. (Previously we
+ deferred this, causing different method tables to be emitted
+ for native code and bytecode.) */
+ if (!TYPE_DOT_CLASS (this_class)
+ && !JPRIMITIVE_TYPE_P (class_name)
+ && !(TREE_CODE (class_name) == VOID_TYPE))
+ {
+ tree target_class;
+
+ if (CLASS_INTERFACE (TYPE_NAME (this_class)))
+ {
+ /* For interfaces, adding a static 'class$' method directly
+ is illegal. So create an inner class to contain the new
+ method. Empirically this matches the behavior of javac. */
+ tree t = build_wfl_node (DECL_NAME (TYPE_NAME (object_type_node)));
+ tree inner = create_anonymous_class (0, t);
+ target_class = TREE_TYPE (inner);
+ end_class_declaration (1);
+ }
+ else
+ {
+ /* For inner classes, add a 'class$' method to their outermost
+ context, creating it if necessary. */
+ while (INNER_CLASS_DECL_P (class_decl))
+ class_decl = DECL_CONTEXT (class_decl);
+ target_class = TREE_TYPE (class_decl);
+ }
+
+ if (TYPE_DOT_CLASS (target_class) == NULL_TREE)
+ build_dot_class_method (target_class);
+
+ if (this_class != target_class)
+ TYPE_DOT_CLASS (this_class) = TYPE_DOT_CLASS (target_class);
+ }
+
EXPR_WFL_LINECOL (node) = location;
return node;
}
@@ -14113,12 +14166,6 @@ patch_incomplete_class_ref (tree node)
if (!(ref_type = resolve_type_during_patch (type)))
return error_mark_node;
- /* Generate the synthetic static method `class$'. (Previously we
- deferred this, causing different method tables to be emitted
- for native code and bytecode.) */
- if (!TYPE_DOT_CLASS (current_class))
- build_dot_class_method (current_class);
-
/* If we're not emitting class files and we know ref_type is a
compiled class, build a direct reference. */
if ((! flag_emit_class_files && is_compiled_class (ref_type))
@@ -14134,7 +14181,7 @@ patch_incomplete_class_ref (tree node)
/* If we're emitting class files and we have to deal with non
primitive types, we invoke the synthetic static method `class$'. */
- ref_type = build_dot_class_method_invocation (ref_type);
+ ref_type = build_dot_class_method_invocation (current_class, ref_type);
return java_complete_tree (ref_type);
}
@@ -15398,7 +15445,7 @@ build_assertion (int location, tree condition, tree value)
if (!TYPE_DOT_CLASS (class_type))
build_dot_class_method (class_type);
- classdollar = build_dot_class_method_invocation (class_type);
+ classdollar = build_dot_class_method_invocation (class_type, class_type);
/* Call CLASS.desiredAssertionStatus(). */
id = build_wfl_node (get_identifier ("desiredAssertionStatus"));
@@ -15456,7 +15503,7 @@ build_assertion (int location, tree condition, tree value)
catches TYPE and executes CATCH_STMTS. */
static tree
-encapsulate_with_try_catch (int location, tree type, tree try_stmts,
+encapsulate_with_try_catch (int location, tree type_or_name, tree try_stmts,
tree catch_stmts)
{
tree try_block, catch_clause_param, catch_block, catch;
@@ -15465,8 +15512,20 @@ encapsulate_with_try_catch (int location, tree type, tree try_stmts,
try_block = build_expr_block (try_stmts, NULL_TREE);
/* Build a catch block: we need a catch clause parameter */
- catch_clause_param = build_decl (VAR_DECL,
- wpv_id, build_pointer_type (type));
+ if (TREE_CODE (type_or_name) == EXPR_WITH_FILE_LOCATION)
+ {
+ tree catch_type = obtain_incomplete_type (type_or_name);
+ jdep *dep;
+ catch_clause_param = build_decl (VAR_DECL, wpv_id, catch_type);
+ register_incomplete_type (JDEP_VARIABLE, type_or_name,
+ catch_clause_param, catch_type);
+ dep = CLASSD_LAST (ctxp->classd_list);
+ JDEP_GET_PATCH (dep) = &TREE_TYPE (catch_clause_param);
+ }
+ else
+ catch_clause_param = build_decl (VAR_DECL, wpv_id,
+ build_pointer_type (type_or_name));
+
/* And a block */
catch_block = build_expr_block (NULL_TREE, catch_clause_param);