mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-02 16:23:56 +08:00
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:
parent
a78e4fa764
commit
b8ca854ad1
@ -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.
|
||||
|
@ -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")));
|
||||
|
@ -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]
|
||||
|
109
gcc/java/parse.y
109
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user