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
This commit is contained in:
Jeff Sturm 2003-11-18 03:57:08 +00:00 committed by Jeff Sturm
parent a78e4fa764
commit b8ca854ad1
4 changed files with 110 additions and 35 deletions

View File

@ -1,3 +1,29 @@
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.

View File

@ -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")));

View File

@ -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]

View File

@ -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);