X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fjava%2Ftypeck.c;h=0e6e404a3620067353118740360e5d090c9b9d94;hp=eb3b5339963d048449d4716272df94309653eb21;hb=f6cc6a0817157a9069e1989d975a08a7e299cb9f;hpb=7158d1b0d84ccc576ccbb6bef6a3d853c49f3c72 diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c index eb3b5339963..0e6e404a362 100644 --- a/gcc/java/typeck.c +++ b/gcc/java/typeck.c @@ -1,21 +1,21 @@ /* Handle types for the GNU compiler for the Java(TM) language. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to +along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -27,7 +27,10 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" +#include "real.h" #include "obstack.h" #include "flags.h" #include "java-tree.h" @@ -36,20 +39,18 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "toplev.h" #include "ggc.h" -static tree convert_ieee_real_to_integer PARAMS ((tree, tree)); -static tree parse_signature_type PARAMS ((const unsigned char **, - const unsigned char *)); -static tree lookup_do PARAMS ((tree, tree, tree, tree, tree (*)(tree))); +static tree convert_ieee_real_to_integer (tree, tree); +static tree parse_signature_type (const unsigned char **, + const unsigned char *); +static tree lookup_do (tree, int, tree, tree, tree (*)(tree)); +static tree build_null_signature (tree); tree * type_map; -extern struct obstack permanent_obstack; /* Set the type of the local variable with index SLOT to TYPE. */ void -set_local_type (slot, type) - int slot; - tree type; +set_local_type (int slot, tree type) { int max_locals = DECL_MAX_LOCALS(current_function_decl); int nslots = TYPE_IS_WIDE (type) ? 2 : 1; @@ -77,28 +78,27 @@ set_local_type (slot, type) : (int)expr))) */ static tree -convert_ieee_real_to_integer (type, expr) - tree type, expr; +convert_ieee_real_to_integer (tree type, tree expr) { tree result; expr = save_expr (expr); - result = build (COND_EXPR, type, - build (NE_EXPR, boolean_type_node, expr, expr), - convert (type, integer_zero_node), - convert_to_integer (type, expr)); + result = build3 (COND_EXPR, type, + build2 (NE_EXPR, boolean_type_node, expr, expr), + convert (type, integer_zero_node), + convert_to_integer (type, expr)); - result = build (COND_EXPR, type, - build (LE_EXPR, boolean_type_node, expr, - convert (TREE_TYPE (expr), TYPE_MIN_VALUE (type))), - TYPE_MIN_VALUE (type), - result); - - result = build (COND_EXPR, type, - build (GE_EXPR, boolean_type_node, expr, - convert (TREE_TYPE (expr), TYPE_MAX_VALUE (type))), - TYPE_MAX_VALUE (type), - result); + result = build3 (COND_EXPR, type, + build2 (LE_EXPR, boolean_type_node, expr, + convert (TREE_TYPE (expr), TYPE_MIN_VALUE (type))), + TYPE_MIN_VALUE (type), + result); + + result = build3 (COND_EXPR, type, + build2 (GE_EXPR, boolean_type_node, expr, + convert (TREE_TYPE (expr), TYPE_MAX_VALUE (type))), + TYPE_MAX_VALUE (type), + result); return result; } @@ -110,10 +110,9 @@ convert_ieee_real_to_integer (type, expr) not permitted by the language being compiled. */ tree -convert (type, expr) - tree type, expr; +convert (tree type, tree expr) { - register enum tree_code code = TREE_CODE (type); + enum tree_code code = TREE_CODE (type); if (!expr) return error_mark_node; @@ -132,13 +131,20 @@ convert (type, expr) return fold (convert_to_boolean (type, expr)); if (code == INTEGER_TYPE) { - if (! flag_fast_math + if (! flag_unsafe_math_optimizations && ! flag_emit_class_files && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) return fold (convert_ieee_real_to_integer (type, expr)); else - return fold (convert_to_integer (type, expr)); + { + /* fold very helpfully sets the overflow status if a type + overflows in a narrowing integer conversion, but Java + doesn't care. */ + tree tmp = fold (convert_to_integer (type, expr)); + TREE_OVERFLOW (tmp) = 0; + return tmp; + } } if (code == REAL_TYPE) return fold (convert_to_real (type, expr)); @@ -152,39 +158,23 @@ convert (type, expr) tree -convert_to_char (type, expr) - tree type, expr; +convert_to_char (tree type, tree expr) { return build1 (NOP_EXPR, type, expr); } tree -convert_to_boolean (type, expr) - tree type, expr; +convert_to_boolean (tree type, tree expr) { return build1 (NOP_EXPR, type, expr); } -/* Print an error message for invalid use of an incomplete type. - VALUE is the expression that was used (or 0 if that isn't known) - and TYPE is the type that was invalid. */ - -void -incomplete_type_error (value, type) - tree value ATTRIBUTE_UNUSED; - tree type ATTRIBUTE_UNUSED; -{ - error ("internal error - use of undefined type"); -} - /* Return a data type that has machine mode MODE. If the mode is an integer, then UNSIGNEDP selects between signed and unsigned types. */ tree -type_for_mode (mode, unsignedp) - enum machine_mode mode; - int unsignedp; +java_type_for_mode (enum machine_mode mode, int unsignedp) { if (mode == TYPE_MODE (int_type_node)) return unsignedp ? unsigned_int_type_node : int_type_node; @@ -206,9 +196,7 @@ type_for_mode (mode, unsignedp) that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */ tree -type_for_size (bits, unsignedp) - unsigned bits; - int unsignedp; +java_type_for_size (unsigned bits, int unsignedp) { if (bits <= TYPE_PRECISION (byte_type_node)) return unsignedp ? unsigned_byte_type_node : byte_type_node; @@ -225,9 +213,7 @@ type_for_size (bits, unsignedp) signed according to UNSIGNEDP. */ tree -signed_or_unsigned_type (unsignedp, type) - int unsignedp; - tree type; +java_signed_or_unsigned_type (int unsignedp, tree type) { if (! INTEGRAL_TYPE_P (type)) return type; @@ -245,31 +231,27 @@ signed_or_unsigned_type (unsignedp, type) /* Return a signed type the same as TYPE in other respects. */ tree -signed_type (type) - tree type; +java_signed_type (tree type) { - return signed_or_unsigned_type (0, type); + return java_signed_or_unsigned_type (0, type); } /* Return an unsigned type the same as TYPE in other respects. */ tree -unsigned_type (type) - tree type; +java_unsigned_type (tree type) { - return signed_or_unsigned_type (1, type); - + return java_signed_or_unsigned_type (1, type); } /* Mark EXP saying that we need to be able to take the address of it; it should not be allocated in a register. - Value is 1 if successful. */ + Value is true if successful. */ -int -mark_addressable (exp) - tree exp; +bool +java_mark_addressable (tree exp) { - register tree x = exp; + tree x = exp; while (1) switch (TREE_CODE (x)) { @@ -288,12 +270,12 @@ mark_addressable (exp) break; case COND_EXPR: - return mark_addressable (TREE_OPERAND (x, 1)) - & mark_addressable (TREE_OPERAND (x, 2)); + return java_mark_addressable (TREE_OPERAND (x, 1)) + && java_mark_addressable (TREE_OPERAND (x, 2)); case CONSTRUCTOR: TREE_ADDRESSABLE (x) = 1; - return 1; + return true; case INDIRECT_REF: /* We sometimes add a cast *(TYPE*)&FOO to handle type and mode @@ -309,7 +291,7 @@ mark_addressable (exp) x = TREE_OPERAND (x, 0); break; } - return 1; + return true; case VAR_DECL: case CONST_DECL: @@ -323,15 +305,14 @@ mark_addressable (exp) #endif /* drops through */ default: - return 1; + return true; } } /* Thorough checking of the arrayness of TYPE. */ int -is_array_type_p (type) - tree type; +is_array_type_p (tree type) { return TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE @@ -342,8 +323,7 @@ is_array_type_p (type) Return -1 if the length is unknown or non-constant. */ HOST_WIDE_INT -java_array_type_length (array_type) - tree array_type; +java_array_type_length (tree array_type) { tree arfld; if (TREE_CODE (array_type) == POINTER_TYPE) @@ -352,26 +332,33 @@ java_array_type_length (array_type) if (arfld != NULL_TREE) { tree index_type = TYPE_DOMAIN (TREE_TYPE (arfld)); - tree high = TYPE_MAX_VALUE (index_type); - if (TREE_CODE (high) == INTEGER_CST) - return TREE_INT_CST_LOW (high) + 1; + if (index_type != NULL_TREE) + { + tree high = TYPE_MAX_VALUE (index_type); + if (TREE_CODE (high) == INTEGER_CST) + return TREE_INT_CST_LOW (high) + 1; + } } return -1; } /* An array of unknown length will be ultimately given an length of -2, so that we can still have `length' producing a negative value - even if found. This was part of an optimization amaing at removing + even if found. This was part of an optimization aiming at removing `length' from static arrays. We could restore it, FIXME. */ tree -build_prim_array_type (element_type, length) - tree element_type; - HOST_WIDE_INT length; +build_prim_array_type (tree element_type, HOST_WIDE_INT length) { - tree max_index = build_int_2 (length - 1, (0 == length ? -1 : 0)); - TREE_TYPE (max_index) = sizetype; - return build_array_type (element_type, build_index_type (max_index)); + tree index = NULL; + + if (length != -1) + { + tree max_index = build_int_2 (length - 1, (0 == length ? -1 : 0)); + TREE_TYPE (max_index) = sizetype; + index = build_index_type (max_index); + } + return build_array_type (element_type, index); } /* Return a Java array type with a given ELEMENT_TYPE and LENGTH. @@ -379,9 +366,7 @@ build_prim_array_type (element_type, length) The LENGTH is -1 if the length is unknown. */ tree -build_java_array_type (element_type, length) - tree element_type; - HOST_WIDE_INT length; +build_java_array_type (tree element_type, HOST_WIDE_INT length) { tree sig, t, fld, atype, arfld; char buf[12]; @@ -406,7 +391,9 @@ build_java_array_type (element_type, length) el_name = TYPE_NAME (el_name); if (TREE_CODE (el_name) == TYPE_DECL) el_name = DECL_NAME (el_name); - TYPE_NAME (t) = identifier_subst (el_name, "", '.', '.', "[]"); + TYPE_NAME (t) = build_decl (TYPE_DECL, + identifier_subst (el_name, "", '.', '.', "[]"), + t); set_java_signature (t, sig); set_super_info (0, t, object_type_node, 0); @@ -420,6 +407,7 @@ build_java_array_type (element_type, length) DECL_CONTEXT (fld) = t; FIELD_PUBLIC (fld) = 1; FIELD_FINAL (fld) = 1; + TREE_READONLY (fld) = 1; atype = build_prim_array_type (element_type, length); arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype); @@ -439,13 +427,12 @@ build_java_array_type (element_type, length) /* Promote TYPE to the type actually used for fields and parameters. */ tree -promote_type (type) - tree type; +promote_type (tree type) { switch (TREE_CODE (type)) { case RECORD_TYPE: - return build_pointer_type (CLASS_TO_HANDLE_TYPE (type)); + return build_pointer_type (type); case BOOLEAN_TYPE: if (type == boolean_type_node) return promoted_boolean_type_node; @@ -474,8 +461,7 @@ promote_type (type) Return the seen TREE_TYPE, updating *PTR. */ static tree -parse_signature_type (ptr, limit) - const unsigned char **ptr, *limit; +parse_signature_type (const unsigned char **ptr, const unsigned char *limit) { tree type; @@ -501,7 +487,7 @@ parse_signature_type (ptr, limit) case 'L': { const unsigned char *start = ++(*ptr); - register const unsigned char *str = start; + const unsigned char *str = start; for ( ; ; str++) { if (str >= limit) @@ -524,9 +510,7 @@ parse_signature_type (ptr, limit) Return a gcc type node. */ tree -parse_signature_string (sig_string, sig_length) - const unsigned char *sig_string; - int sig_length; +parse_signature_string (const unsigned char *sig_string, int sig_length) { tree result_type; const unsigned char *str = sig_string; @@ -576,11 +560,18 @@ get_type_from_signature (tree signature) return type; } +/* Ignore signature and always return null. Used by has_method. */ + +static tree +build_null_signature (tree type ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} + /* Return the signature string for the arguments of method type TYPE. */ tree -build_java_argument_signature (type) - tree type; +build_java_argument_signature (tree type) { extern struct obstack temporary_obstack; tree sig = TYPE_ARGUMENT_SIGNATURE (type); @@ -607,8 +598,7 @@ build_java_argument_signature (type) /* Return the signature of the given TYPE. */ tree -build_java_signature (type) - tree type; +build_java_signature (tree type) { tree sig, t; while (TREE_CODE (type) == POINTER_TYPE) @@ -688,9 +678,7 @@ build_java_signature (type) /* Save signature string SIG (an IDENTIFIER_NODE) in TYPE for future use. */ void -set_java_signature (type, sig) - tree type; - tree sig; +set_java_signature (tree type, tree sig) { tree old_sig; while (TREE_CODE (type) == POINTER_TYPE) @@ -706,131 +694,197 @@ set_java_signature (type, sig) #endif } -/* Search in class SEARCHED_CLASS (and its superclasses) for a method - matching METHOD_NAME and signature SIGNATURE. If SEARCHED_INTERFACE is - not NULL_TREE then first search its superinterfaces for a similar match. - Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is - used on method candidates to build their (sometimes partial) - signature. */ - +/* Search in SEARCHED_CLASS and its superclasses for a method matching + METHOD_NAME and signature METHOD_SIGNATURE. This function will + only search for methods declared in the class hierarchy; interfaces + will not be considered. Returns NULL_TREE if the method is not + found. */ tree -lookup_argument_method (searched_class, method_name, method_signature) - tree searched_class, method_name, method_signature; +lookup_argument_method (tree searched_class, tree method_name, + tree method_signature) { - return lookup_do (searched_class, NULL_TREE, method_name, method_signature, + return lookup_do (searched_class, 0, + method_name, method_signature, build_java_argument_signature); } -/* Search in class SEARCHED_CLASS (and its superclasses and - implemented interfaces) for a method matching METHOD_NAME and - argument signature METHOD_SIGNATURE. Return a FUNCTION_DECL on - success, or NULL_TREE if none found. (Contrast lookup_java_method, - which takes into account return type.) */ - +/* Like lookup_argument_method, but lets the caller set any flags + desired. */ tree -lookup_argument_method2 (searched_class, method_name, method_signature) - tree searched_class, method_name, method_signature; +lookup_argument_method_generic (tree searched_class, tree method_name, + tree method_signature, int flags) { - return lookup_do (CLASSTYPE_SUPER (searched_class), searched_class, + return lookup_do (searched_class, flags, method_name, method_signature, build_java_argument_signature); } + /* Search in class SEARCHED_CLASS (and its superclasses) for a method matching METHOD_NAME and signature METHOD_SIGNATURE. Return a FUNCTION_DECL on success, or NULL_TREE if none found. (Contrast - lookup_argument_method, which ignores return type.) If + lookup_argument_method, which ignores return type.) If SEARCHED_CLASS is an interface, search it too. */ - tree -lookup_java_method (searched_class, method_name, method_signature) - tree searched_class, method_name, method_signature; +lookup_java_method (tree searched_class, tree method_name, + tree method_signature) { - tree searched_interface; - - /* If this class is an interface class, search its superinterfaces - * first. A superinterface is not an interface's superclass: a super - * interface is implemented by the interface. */ - - searched_interface = (CLASS_INTERFACE (TYPE_NAME (searched_class)) ? - searched_class : NULL_TREE); - return lookup_do (searched_class, searched_interface, method_name, + return lookup_do (searched_class, SEARCH_INTERFACE, method_name, method_signature, build_java_signature); } -/* Search in class SEARCHED_CLASS (an its superclasses) for a method - matching METHOD_NAME and signature SIGNATURE. Also search in - SEARCHED_INTERFACE (an its superinterfaces) for a similar match. - Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is - used on method candidates to build their (sometimes partial) - signature. */ +/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME. */ +int +has_method (tree class, tree method_name) +{ + return lookup_do (class, SEARCH_INTERFACE, + method_name, NULL_TREE, + build_null_signature) != NULL_TREE; +} +/* Search in class SEARCHED_CLASS, but not its superclasses, for a + method matching METHOD_NAME and signature SIGNATURE. A private + helper for lookup_do. */ static tree -lookup_do (searched_class, searched_interface, method_name, signature, signature_builder) - tree searched_class, searched_interface, method_name, signature; - tree (*signature_builder) PARAMS ((tree)); +shallow_find_method (tree searched_class, int flags, tree method_name, + tree signature, tree (*signature_builder) (tree)) { tree method; - - if (searched_interface) - { - int i; - int interface_len = - TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_interface)) - 1; - - for (i = interface_len; i > 0; i--) - { - tree child = - TREE_VEC_ELT (TYPE_BINFO_BASETYPES (searched_interface), i); - tree iclass = BINFO_TYPE (child); - - /* If the superinterface hasn't been loaded yet, do so now. */ - if (CLASS_FROM_SOURCE_P (iclass)) - safe_layout_class (iclass); - else if (!CLASS_LOADED_P (iclass)) - load_class (iclass, 1); - - for (method = TYPE_METHODS (iclass); - method != NULL_TREE; method = TREE_CHAIN (method)) - { - tree method_sig = (*signature_builder) (TREE_TYPE (method)); - - if (DECL_NAME (method) == method_name && method_sig == signature) - return method; - } - - /* it could be defined in a supersuperinterface */ - if (CLASS_INTERFACE (TYPE_NAME (iclass))) - { - method = lookup_do (iclass, iclass, method_name, - signature, signature_builder); - if (method != NULL_TREE) - return method; - } - } - } - - while (searched_class != NULL_TREE) + for (method = TYPE_METHODS (searched_class); + method != NULL_TREE; method = TREE_CHAIN (method)) { - for (method = TYPE_METHODS (searched_class); - method != NULL_TREE; method = TREE_CHAIN (method)) + tree method_sig = (*signature_builder) (TREE_TYPE (method)); + if (DECL_NAME (method) == method_name && method_sig == signature) { - tree method_sig = (*signature_builder) (TREE_TYPE (method)); - if (DECL_NAME (method) == method_name && method_sig == signature) + /* If the caller requires a visible method, then we + skip invisible methods here. */ + if (! (flags & SEARCH_VISIBLE) + || ! METHOD_INVISIBLE (method)) return method; } - searched_class = CLASSTYPE_SUPER (searched_class); + } + return NULL_TREE; +} + +/* Search in the superclasses of SEARCHED_CLASS for a method matching + METHOD_NAME and signature SIGNATURE. A private helper for + lookup_do. */ +static tree +find_method_in_superclasses (tree searched_class, int flags, + tree method_name, tree signature, + tree (*signature_builder) (tree)) +{ + tree klass; + for (klass = CLASSTYPE_SUPER (searched_class); klass != NULL_TREE; + klass = CLASSTYPE_SUPER (klass)) + { + tree method; + method = shallow_find_method (klass, flags, method_name, + signature, signature_builder); + if (method != NULL_TREE) + return method; } return NULL_TREE; } +/* Search in the interfaces of SEARCHED_CLASS and its superinterfaces + for a method matching METHOD_NAME and signature SIGNATURE. A + private helper for lookup_do. */ +static tree +find_method_in_interfaces (tree searched_class, int flags, tree method_name, + tree signature, tree (*signature_builder) (tree)) +{ + int i; + tree binfo, base_binfo; + + for (binfo = TYPE_BINFO (searched_class), i = 1; + BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + { + tree iclass = BINFO_TYPE (base_binfo); + tree method; + + /* If the superinterface hasn't been loaded yet, do so now. */ + if (CLASS_FROM_SOURCE_P (iclass)) + safe_layout_class (iclass); + else if (!CLASS_LOADED_P (iclass)) + load_class (iclass, 1); + + /* First, we look in ICLASS. If that doesn't work we'll + recursively look through all its superinterfaces. */ + method = shallow_find_method (iclass, flags, method_name, + signature, signature_builder); + if (method != NULL_TREE) + return method; + + method = find_method_in_interfaces + (iclass, flags, method_name, signature, signature_builder); + if (method != NULL_TREE) + return method; + } + + return NULL_TREE; +} + + +/* Search in class SEARCHED_CLASS (and its superclasses) for a method + matching METHOD_NAME and signature SIGNATURE. FLAGS control some + parameters of the search. + + SEARCH_INTERFACE means also search interfaces and superinterfaces + of SEARCHED_CLASS. + + SEARCH_SUPER means skip SEARCHED_CLASS and start with its + superclass. + + SEARCH_VISIBLE means skip methods for which METHOD_INVISIBLE is + set. + + Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is + used on method candidates to build their (sometimes partial) + signature. */ +static tree +lookup_do (tree searched_class, int flags, tree method_name, + tree signature, tree (*signature_builder) (tree)) +{ + tree method; + + if (searched_class == NULL_TREE) + return NULL_TREE; + + if (flags & SEARCH_SUPER) + { + searched_class = CLASSTYPE_SUPER (searched_class); + if (searched_class == NULL_TREE) + return NULL_TREE; + } + + /* First look in our own methods. */ + method = shallow_find_method (searched_class, flags, method_name, + signature, signature_builder); + if (method) + return method; + + /* Then look in our superclasses. */ + if (! CLASS_INTERFACE (TYPE_NAME (searched_class))) + method = find_method_in_superclasses (searched_class, flags, method_name, + signature, signature_builder); + if (method) + return method; + + /* If that doesn't work, look in our interfaces. */ + if (flags & SEARCH_INTERFACE) + method = find_method_in_interfaces (searched_class, flags, method_name, + signature, signature_builder); + + return method; +} + /* Search in class CLAS for a constructor matching METHOD_SIGNATURE. Return a FUNCTION_DECL on success, or NULL_TREE if none found. */ tree -lookup_java_constructor (clas, method_signature) - tree clas, method_signature; +lookup_java_constructor (tree clas, tree method_signature) { tree method = TYPE_METHODS (clas); for ( ; method != NULL_TREE; method = TREE_CHAIN (method)) @@ -847,11 +901,7 @@ lookup_java_constructor (clas, method_signature) Promotion. It assumes that both T1 and T2 are eligible to BNP. */ tree -binary_numeric_promotion (t1, t2, exp1, exp2) - tree t1; - tree t2; - tree *exp1; - tree *exp2; +binary_numeric_promotion (tree t1, tree t2, tree *exp1, tree *exp2) { if (t1 == double_type_node || t2 == double_type_node) {