From b8ca854ad184062c5fb41768804d73a8b18d28b4 Mon Sep 17 00:00:00 2001 From: Jeff Sturm Date: Tue, 18 Nov 2003 03:57:08 +0000 Subject: [PATCH] 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 --- gcc/java/ChangeLog | 26 +++++++++++ gcc/java/decl.c | 4 -- gcc/java/java-tree.h | 6 --- gcc/java/parse.y | 109 +++++++++++++++++++++++++++++++++---------- 4 files changed, 110 insertions(+), 35 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 995b21a2f3d..ea30c778e8a 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,29 @@ +2003-11-17 Jeff Sturm + + 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 Fix PR java/12739. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 4b0c4963f3a..b8f09e1dfaa 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 eb0db483963..2c706c9fe44 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 375e7ec8266..5613c876798 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);