From f0f3a77740016ecd1168ce689bbc36d705ddff49 Mon Sep 17 00:00:00 2001 From: Alexandre Petit-Bianco Date: Tue, 8 Aug 2000 03:33:36 +0000 Subject: [PATCH] 2000-08-07 Alexandre Petit-Bianco * parse.y (maybe_yank_clinit): When generating bytecode: non empty method bodies not to rule out discarding `'; don't use to initialize static fields with constant initializers. 2000-08-01 Alexandre Petit-Bianco * gjavah.c (print_method_info): Added `synth' parameter. Skip synthetic methods. (method_synthetic): New global. (HANDLE_METHOD): Recognize synthetic method and tell `print_method_info' about it. (HANDLE_END_METHOD): Do not issue an additional `;\n' if we're processing a synthetic method. * jcf-reader.c (skip_attribute): New function. ( skip_attribute): Likewise. 2000-08-01 Alexandre Petit-Bianco * parse.y (build_outer_field_access): Fixed comments. (fix_constructors): Emit the initialization of this$ before calling $finit$. (resolve_qualified_expression_name): Build an access to `decl' if necessary. 2000-07-31 Alexandre Petit-Bianco * parse-scan.y (curent_class): Non longer const. (inner_qualifier, inner_qualifier_length): Deleted. (current_class_length): New global. (bracket_count): Fixed typo in leading comment. (anonymous_count): New global. (class_instance_creation_expression:): Handle anonymous classes. (anonymous_class_creation:): New rule. (push_class_context): Rewritten. (pop_class_context): Likewise. (INNER_QUALIFIER): Macro deleted. (report_class_declaration): call `push_class_context' when entering the function. `fprintf' format modified not to use INNER_QUALIFIER. (report_class_declaration): Assign `package_name' and `current_class' to NULL separatly. 2000-07-31 Alexandre Petit-Bianco * expr.c (build_invokeinterface): Call layout_class_methods on target interface. (http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00339.html) From-SVN: r35560 --- gcc/java/ChangeLog | 57 +++++++++++++++++++++++++ gcc/java/expr.c | 1 + gcc/java/gjavah.c | 68 +++++++++++++++++++---------- gcc/java/jcf-reader.c | 60 ++++++++++++++++++++++++++ gcc/java/parse-scan.y | 99 +++++++++++++++++++++++++++++-------------- gcc/java/parse.y | 83 +++++++++++++++++++++++++----------- 6 files changed, 290 insertions(+), 78 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 681e99316b9..f8c3803841d 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,11 @@ +2000-08-07 Alexandre Petit-Bianco * lang-options.h: Added a comma after the last element to avoid @@ -17,6 +25,55 @@ Sun Aug 6 00:47:24 2000 Ovidiu Predescu * class.c (build_dtable_decl): Initialize dummy. +2000-08-01 Alexandre Petit-Bianco + + * parse.y (maybe_yank_clinit): When generating bytecode: non empty + method bodies not to rule out discarding `'; don't use + to initialize static fields with constant initializers. + +2000-08-01 Alexandre Petit-Bianco + + * gjavah.c (print_method_info): Added `synth' parameter. Skip + synthetic methods. + (method_synthetic): New global. + (HANDLE_METHOD): Recognize synthetic method and tell + `print_method_info' about it. + (HANDLE_END_METHOD): Do not issue an additional `;\n' if we're + processing a synthetic method. + * jcf-reader.c (skip_attribute): New function. + ( skip_attribute): Likewise. + +2000-08-01 Alexandre Petit-Bianco + + * parse.y (build_outer_field_access): Fixed comments. + (fix_constructors): Emit the initialization of this$ before + calling $finit$. + (resolve_qualified_expression_name): Build an access to `decl' if + necessary. + +2000-07-31 Alexandre Petit-Bianco + + * parse-scan.y (curent_class): Non longer const. + (inner_qualifier, inner_qualifier_length): Deleted. + (current_class_length): New global. + (bracket_count): Fixed typo in leading comment. + (anonymous_count): New global. + (class_instance_creation_expression:): Handle anonymous classes. + (anonymous_class_creation:): New rule. + (push_class_context): Rewritten. + (pop_class_context): Likewise. + (INNER_QUALIFIER): Macro deleted. + (report_class_declaration): call `push_class_context' when + entering the function. `fprintf' format modified not to use + INNER_QUALIFIER. + (report_class_declaration): Assign `package_name' and + `current_class' to NULL separatly. + +2000-07-31 Alexandre Petit-Bianco + + * expr.c (build_invokeinterface): Call layout_class_methods on + target interface. + 2000-07-27 Tom Tromey Anthony Green Alexandre Petit-Bianco diff --git a/gcc/java/expr.c b/gcc/java/expr.c index f01940f6490..af59e63ba98 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -1783,6 +1783,7 @@ build_invokeinterface (dtable, method) lookup_field (&dtable_type, class_ident)); interface = DECL_CONTEXT (method); + layout_class_methods (interface); i = 1; for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++) diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c index b8a37f72b26..bca748a1ad2 100644 --- a/gcc/java/gjavah.c +++ b/gcc/java/gjavah.c @@ -116,7 +116,7 @@ static struct method_name *method_name_list; static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2)); static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int)); static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int)); -static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2)); +static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2, int)); static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *, int)); static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int, @@ -182,26 +182,45 @@ static int method_pass; static int method_declared = 0; static int method_access = 0; static int method_printed = 0; -#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \ - if (method_pass) \ - { \ - decompiled = 0; method_printed = 0; \ - if (out) \ - print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \ - } \ - else \ - { \ - print_method_info (NULL, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \ - if (! stubs && ! flag_jni) \ - add_class_decl (out, jcf, SIGNATURE); \ - } +static int method_synthetic = 0; +#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \ + { \ + method_synthetic = 0; \ + if (ATTRIBUTE_COUNT) \ + method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \ + (const char *)"Synthetic", 9); \ + /* If a synthetic methods have been declared, its attribute aren't \ + worth reading (and triggering side-effects). We skip them an \ + set ATTRIBUTE_COUNT to zero so that they'll be skipped in \ + jcf_parse_one_method. */ \ + if (method_synthetic) \ + { \ + skip_attribute (jcf, ATTRIBUTE_COUNT); \ + ATTRIBUTE_COUNT = 0; \ + } \ + if (method_pass && !method_synthetic) \ + { \ + decompiled = 0; method_printed = 0; \ + if (out) \ + print_method_info (out, jcf, NAME, SIGNATURE, \ + ACCESS_FLAGS, method_synthetic); \ + } \ + else if (!method_synthetic) \ + { \ + print_method_info (NULL, jcf, NAME, SIGNATURE, \ + ACCESS_FLAGS, method_synthetic); \ + if (! stubs && ! flag_jni) \ + add_class_decl (out, jcf, SIGNATURE); \ + } \ + } -#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \ +#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \ if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH); static int decompiled = 0; -#define HANDLE_END_METHOD() \ - if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out); +#define HANDLE_END_METHOD() \ + if (out && method_printed && !method_synthetic) \ + fputs (decompiled || stubs ? "\n" : ";\n", out); #include "jcf-reader.c" @@ -670,9 +689,9 @@ DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags), static void -DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), +DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth), FILE *stream AND JCF* jcf - AND int name_index AND int sig_index AND JCF_u2 flags) + AND int name_index AND int sig_index AND JCF_u2 flags AND int synth) { const unsigned char *str; int length, is_init = 0; @@ -684,10 +703,15 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), fprintf (stream, ""); str = JPOOL_UTF_DATA (jcf, name_index); length = JPOOL_UTF_LENGTH (jcf, name_index); - if (str[0] == '<' || str[0] == '$') + + /* Ignore synthetic methods. */ + if (synth) + return; + + if (str[0] == '<') { - /* Ignore internally generated methods like and - $finit$. However, treat as a constructor. */ + /* Ignore the internally generated method . However, + treat as a constructor. */ if (! utf8_cmp (str, length, "")) is_init = 1; else if (! METHOD_IS_FINAL (jcf->access_flags, flags) diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c index 878c4de86b1..1b081e54fbe 100644 --- a/gcc/java/jcf-reader.c +++ b/gcc/java/jcf-reader.c @@ -27,6 +27,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "zipfile.h" static int get_attribute PARAMS ((JCF *)); +static int peek_attribute PARAMS ((JCF *, int, const char *, int)); +static void skip_attribute PARAMS ((JCF *, int)); static int jcf_parse_preamble PARAMS ((JCF *)); static int jcf_parse_constant_pool PARAMS ((JCF *)); static void jcf_parse_class PARAMS ((JCF *)); @@ -35,6 +37,64 @@ static int jcf_parse_one_method PARAMS ((JCF *)); static int jcf_parse_methods PARAMS ((JCF *)); static int jcf_parse_final_attributes PARAMS ((JCF *)); +/* Go through all available attribute (ATTRIBUTE_NUMER) and try to + identify PEEKED_NAME. Return 1 if PEEKED_NAME was found, 0 + otherwise. JCF is restored to its initial position before + returning. */ + +static int +peek_attribute (jcf, attribute_number, peeked_name, peeked_name_length) + JCF *jcf; + int attribute_number; + const char *peeked_name; + int peeked_name_length; +{ + int to_return = 0; + long absolute_offset = (long)JCF_TELL (jcf); + int i; + + for (i = 0; !to_return && i < attribute_number; i++) + { + uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); + uint32 attribute_length = JCF_readu4 (jcf); + int name_length; + const unsigned char *name_data; + + JCF_FILL (jcf, (long) attribute_length); + if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf) + || JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) + continue; + + name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); + name_data = JPOOL_UTF_DATA (jcf, attribute_name); + + if (name_length == peeked_name_length + && ! memcmp (name_data, peeked_name, peeked_name_length)) + { + to_return = 1; + break; + } + + JCF_SKIP (jcf, attribute_length); + } + + JCF_SEEK (jcf, absolute_offset); + return to_return; +} + +static void +skip_attribute (jcf, number_of_attribute) + JCF *jcf; + int number_of_attribute; +{ + while (number_of_attribute--) + { + JCF_FILL (jcf, 6); + (void) JCF_readu2 (jcf); + JCF_SKIP (jcf, JCF_readu4 (jcf)); + } +} + static int DEFUN(get_attribute, (jcf), JCF *jcf) diff --git a/gcc/java/parse-scan.y b/gcc/java/parse-scan.y index f4d10b840e8..2b8b78d75bc 100644 --- a/gcc/java/parse-scan.y +++ b/gcc/java/parse-scan.y @@ -63,12 +63,11 @@ static int absorber; #define USE_ABSORBER absorber = 0 /* Keep track of the current class name and package name. */ -static const char *current_class; +static char *current_class; static const char *package_name; /* Keep track of the current inner class qualifier. */ -static char *inner_qualifier; -static int inner_qualifier_length; +static int current_class_length; /* Keep track of whether things have be listed before. */ static int previous_output; @@ -76,10 +75,13 @@ static int previous_output; /* Record modifier uses */ static int modifier_value; -/* Keep track of number of bracket pairs after a variable declarator +/* Keeps track of number of bracket pairs after a variable declarator id. */ static int bracket_count; +/* Numbers anonymous classes */ +static int anonymous_count; + /* Record a method declaration */ struct method_declarator { const char *method_name; @@ -897,20 +899,22 @@ primary_no_new_array: class_instance_creation_expression: NEW_TK class_type OP_TK argument_list CP_TK | NEW_TK class_type OP_TK CP_TK - /* Added, JDK1.1 inner classes but modified to use - 'class_type' instead of 'TypeName' (type_name) mentionned - in the documentation but doesn't exist. */ -| NEW_TK class_type OP_TK argument_list CP_TK class_body -| NEW_TK class_type OP_TK CP_TK class_body - /* Added, JDK1.1 inner classes, modified to use name or - primary instead of primary solely which couldn't work in - all situations. */ +| anonymous_class_creation | something_dot_new identifier OP_TK CP_TK | something_dot_new identifier OP_TK CP_TK class_body | something_dot_new identifier OP_TK argument_list CP_TK | something_dot_new identifier OP_TK argument_list CP_TK class_body ; +anonymous_class_creation: + NEW_TK class_type OP_TK CP_TK + { report_class_declaration (NULL); } + class_body +| NEW_TK class_type OP_TK argument_list CP_TK + { report_class_declaration (NULL); } + class_body +; + something_dot_new: /* Added, not part of the specs. */ name DOT_TK NEW_TK { USE_ABSORBER; } @@ -1128,29 +1132,61 @@ static void push_class_context (name) const char *name; { - size_t name_length = strlen (name); - inner_qualifier = xrealloc (inner_qualifier, - inner_qualifier_length + name_length+2); - memcpy (inner_qualifier+inner_qualifier_length, name, name_length); - inner_qualifier_length += name_length; - inner_qualifier [inner_qualifier_length] = '$'; - inner_qualifier [++inner_qualifier_length] = '\0'; + /* If we already have CURRENT_CLASS set, we're in an inter + class. Mangle its name. */ + if (current_class) + { + const char *p; + char anonymous [3]; + int additional_length; + + /* NAME set to NULL indicates an anonymous class, which are named by + numbering them. */ + if (!name) + { + sprintf (anonymous, "%d", ++anonymous_count); + p = anonymous; + } + else + p = name; + + additional_length = strlen (p)+1; /* +1 for `$' */ + current_class = xrealloc (current_class, + current_class_length + additional_length + 1); + current_class [current_class_length] = '$'; + strcpy (¤t_class [current_class_length+1], p); + current_class_length += additional_length; + } + else + { + if (!name) + return; + current_class_length = strlen (name); + current_class = xmalloc (current_class_length+1); + strcpy (current_class, name); + } } static void pop_class_context () { - while (--inner_qualifier_length > 0 - && inner_qualifier [inner_qualifier_length-1] != '$') + /* Go back to the last `$' and cut. */ + while (--current_class_length > 0 + && current_class [current_class_length] != '$') ; - inner_qualifier = xrealloc (inner_qualifier, inner_qualifier_length+1); - if (inner_qualifier_length == -1) - inner_qualifier_length = 0; - inner_qualifier [inner_qualifier_length] = '\0'; + if (current_class_length) + { + current_class = xrealloc (current_class, current_class_length+1); + current_class [current_class_length] = '\0'; + } + else + { + current_class = NULL; + anonymous_count = 0; + } } /* Actions defined here */ -#define INNER_QUALIFIER (inner_qualifier ? inner_qualifier : "") static void report_class_declaration (name) @@ -1158,6 +1194,7 @@ report_class_declaration (name) { extern int flag_dump_class, flag_list_filename; + push_class_context (name); if (flag_dump_class) { if (!previous_output) @@ -1168,13 +1205,10 @@ report_class_declaration (name) } if (package_name) - fprintf (out, "%s.%s%s ", package_name, INNER_QUALIFIER, name); + fprintf (out, "%s.%s ", package_name, current_class); else - fprintf (out, "%s%s ", INNER_QUALIFIER, name); + fprintf (out, "%s ", current_class); } - - push_class_context (name); - current_class = name; } static void @@ -1208,7 +1242,8 @@ report_main_declaration (declarator) void reset_report () { previous_output = 0; - current_class = package_name = NULL; + package_name = NULL; + current_class = NULL; } void diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 61d875c8894..684297962ec 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -7523,12 +7523,14 @@ maybe_yank_clinit (mdecl) if (!DECL_CLINIT_P (mdecl)) return 0; - - /* If the body isn't empty, then we keep */ + + /* If the body isn't empty, then we keep . Note that if + we're emitting classfiles, this isn't enough not to rule it + out. */ fbody = DECL_FUNCTION_BODY (mdecl); if ((bbody = BLOCK_EXPR_BODY (fbody))) bbody = BLOCK_EXPR_BODY (bbody); - if (bbody && bbody != empty_stmt_node) + if (bbody && ! flag_emit_class_files && bbody != empty_stmt_node) return 0; type = DECL_CONTEXT (mdecl); @@ -7536,9 +7538,34 @@ maybe_yank_clinit (mdecl) for (current = (current ? TREE_CHAIN (current) : current); current; current = TREE_CHAIN (current)) - if (!(FIELD_STATIC (current) && FIELD_FINAL (current) - && DECL_INITIAL (current) && TREE_CONSTANT (DECL_INITIAL (current)))) - break; + { + tree f_init; + + /* We're not interested in non static field */ + if (!FIELD_STATIC (current)) + continue; + + /* Anything that isn't String or a basic type is ruled out -- or + if we now how to deal with it (when doing things natively) we + should generated an empty so that SUID are computed + correctly. */ + if (! JSTRING_TYPE_P (TREE_TYPE (current)) + && ! JNUMERIC_TYPE_P (TREE_TYPE (current))) + break; + + f_init = DECL_INITIAL (current); + /* If we're emitting native code, we want static final fields to + have constant initializers. If we don't meet these + conditions, we keep */ + if (!flag_emit_class_files + && !(FIELD_FINAL (current) && f_init && TREE_CONSTANT (f_init))) + break; + /* If we're emitting bytecode, we want static fields to have + constant initializers or no initializer. If we don't meet + these conditions, we keep */ + if (flag_emit_class_files && f_init && !TREE_CONSTANT (f_init)) + break; + } if (current) return 0; @@ -7661,7 +7688,7 @@ build_outer_field_access (id, decl) tree ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class))); /* If decl's class is the direct outer class of the current_class, - build the access as `this$.'. Not that we will break + build the access as `this$.'. Note that we will break the `private' barrier if we're not emitting bytecodes. */ if (ctx == DECL_CONTEXT (decl) && (!FIELD_PRIVATE (decl) || !flag_emit_class_files )) @@ -7677,7 +7704,7 @@ build_outer_field_access (id, decl) int lc = EXPR_WFL_LINECOL (id); /* Now we chain the required number of calls to the access$0 to - get a hold to the enclosing instance we need, and the we + get a hold to the enclosing instance we need, and then we build the field access. */ access = build_access_to_thisn (ctx, DECL_CONTEXT (decl), lc); @@ -8269,14 +8296,21 @@ build_dot_class_method (class) } static tree -build_dot_class_method_invocation (name) - tree name; +build_dot_class_method_invocation (type) + tree type; { - tree s = make_node (STRING_CST); - TREE_STRING_LENGTH (s) = IDENTIFIER_LENGTH (name); + tree sig_id, s; + + if (TYPE_ARRAY_P (type)) + sig_id = build_java_signature (type); + else + sig_id = DECL_NAME (TYPE_NAME (type)); + + s = make_node (STRING_CST); + TREE_STRING_LENGTH (s) = IDENTIFIER_LENGTH (sig_id); TREE_STRING_POINTER (s) = obstack_alloc (expression_obstack, TREE_STRING_LENGTH (s)+1); - strcpy (TREE_STRING_POINTER (s), IDENTIFIER_POINTER (name)); + strcpy (TREE_STRING_POINTER (s), IDENTIFIER_POINTER (sig_id)); return build_method_invocation (build_wfl_node (get_identifier ("class$")), build_tree_list (NULL_TREE, s)); } @@ -8318,6 +8352,11 @@ fix_constructors (mdecl) CLASSNAME() constructor */ start_artificial_method_body (mdecl); + /* Insert an assignment to the this$ hidden field, if + necessary */ + if ((thisn_assign = build_thisn_assign ())) + java_method_add_stmt (mdecl, thisn_assign); + /* We don't generate a super constructor invocation if we're compiling java.lang.Object. build_super_invocation takes care of that. */ @@ -8327,11 +8366,6 @@ fix_constructors (mdecl) super invocation. */ add_instance_initializer (mdecl); - /* Insert an assignment to the this$ hidden field, if - necessary */ - if ((thisn_assign = build_thisn_assign ())) - java_method_add_stmt (mdecl, thisn_assign); - end_artificial_method_body (mdecl); } /* Search for an explicit constructor invocation */ @@ -8363,14 +8397,14 @@ fix_constructors (mdecl) compound = add_stmt_to_compound (compound, NULL_TREE, build_super_invocation (mdecl)); - /* Insert the instance initializer block right here, after the - super invocation. */ - add_instance_initializer (mdecl); - /* Generate the assignment to this$, if necessary */ if ((thisn_assign = build_thisn_assign ())) compound = add_stmt_to_compound (compound, NULL_TREE, thisn_assign); + /* Insert the instance initializer block right here, after the + super invocation. */ + add_instance_initializer (mdecl); + /* Fix the constructor main block if we're adding extra stmts */ if (compound) { @@ -9170,6 +9204,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) current_class); return 1; } + if (outer_field_access_p (current_class, decl)) + decl = build_outer_field_access (qual_wfl, decl); } else { @@ -13114,8 +13150,7 @@ patch_incomplete_class_ref (node) synthetic static method `class$'. */ if (!TYPE_DOT_CLASS (current_class)) build_dot_class_method (current_class); - ref_type = - build_dot_class_method_invocation (DECL_NAME (TYPE_NAME (ref_type))); + ref_type = build_dot_class_method_invocation (ref_type); return java_complete_tree (ref_type); }