OSDN Git Service

2009-09-01 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / java / typeck.c
index 8cfe5e4..1024b7a 100644 (file)
@@ -1,12 +1,12 @@
 /* Handle types for the GNU compiler for the Java(TM) language.
 /* Handle types for the GNU compiler for the Java(TM) language.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +15,8 @@ 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
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-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.  
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -55,8 +54,7 @@ set_local_type (int slot, tree type)
   int max_locals = DECL_MAX_LOCALS(current_function_decl);
   int nslots = TYPE_IS_WIDE (type) ? 2 : 1;
 
   int max_locals = DECL_MAX_LOCALS(current_function_decl);
   int nslots = TYPE_IS_WIDE (type) ? 2 : 1;
 
-  if (slot < 0 || slot + nslots - 1 >= max_locals)
-    abort ();
+  gcc_assert (slot >= 0 && (slot + nslots - 1 < max_locals));
 
   type_map[slot] = type;
   while (--nslots > 0)
 
   type_map[slot] = type;
   while (--nslots > 0)
@@ -83,22 +81,24 @@ convert_ieee_real_to_integer (tree type, tree expr)
   tree result;
   expr = save_expr (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 = 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 = fold_build3 (COND_EXPR, type,
+                       fold_build2 (NE_EXPR, boolean_type_node, expr, expr),
+                        convert (type, integer_zero_node),
+                        convert_to_integer (type, expr));
+  
+  result = fold_build3 (COND_EXPR, type, 
+                       fold_build2 (LE_EXPR, boolean_type_node, expr, 
+                                    convert (TREE_TYPE (expr), 
+                                             TYPE_MIN_VALUE (type))),
+                       TYPE_MIN_VALUE (type),
+                       result);
+  
+  result = fold_build3 (COND_EXPR, type,
+                       fold_build2 (GE_EXPR, boolean_type_node, expr, 
+                                    convert (TREE_TYPE (expr), 
+                                             TYPE_MAX_VALUE (type))),
+                       TYPE_MAX_VALUE (type),
+                       result);
 
   return result;
 }  
 
   return result;
 }  
@@ -117,9 +117,6 @@ convert (tree type, tree expr)
   if (!expr)
    return error_mark_node;
 
   if (!expr)
    return error_mark_node;
 
-  if (do_not_fold)
-    return build1 (NOP_EXPR, type, expr);
-
   if (type == TREE_TYPE (expr)
       || TREE_CODE (expr) == ERROR_MARK)
     return expr;
   if (type == TREE_TYPE (expr)
       || TREE_CODE (expr) == ERROR_MARK)
     return expr;
@@ -128,28 +125,27 @@ convert (tree type, tree expr)
   if (code == VOID_TYPE)
     return build1 (CONVERT_EXPR, type, expr);
   if (code == BOOLEAN_TYPE)
   if (code == VOID_TYPE)
     return build1 (CONVERT_EXPR, type, expr);
   if (code == BOOLEAN_TYPE)
-    return fold (convert_to_boolean (type, expr));
+    return fold_convert (type, expr);
   if (code == INTEGER_TYPE)
     {
   if (code == INTEGER_TYPE)
     {
-      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));
+      if (type == char_type_node || type == promoted_char_type_node)
+       return fold_convert (type, expr);
+      if ((really_constant_p (expr) || ! flag_unsafe_math_optimizations)
+         && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
+       return convert_ieee_real_to_integer (type, expr);
       else
        {
          /* 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));
       else
        {
          /* 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;
+         if (TREE_CODE (tmp) == INTEGER_CST)
+           TREE_OVERFLOW (tmp) = 0;
          return tmp;
        }
     }    
   if (code == REAL_TYPE)
     return fold (convert_to_real (type, expr));
          return tmp;
        }
     }    
   if (code == REAL_TYPE)
     return fold (convert_to_real (type, expr));
-  if (code == CHAR_TYPE)
-    return fold (convert_to_char (type, expr));
   if (code == POINTER_TYPE)
     return fold (convert_to_pointer (type, expr));
   error ("conversion to non-scalar type requested");
   if (code == POINTER_TYPE)
     return fold (convert_to_pointer (type, expr));
   error ("conversion to non-scalar type requested");
@@ -157,18 +153,6 @@ convert (tree type, tree expr)
 }
 
 
 }
 
 
-tree
-convert_to_char (tree type, tree expr)
-{
-  return build1 (NOP_EXPR, type, expr);
-}
-
-tree
-convert_to_boolean (tree type, tree expr)
-{
-  return build1 (NOP_EXPR, type, expr);
-}
-
 /* Return a data type that has machine mode MODE.
    If the mode is an integer,
    then UNSIGNEDP selects between signed and unsigned types.  */
 /* Return a data type that has machine mode MODE.
    If the mode is an integer,
    then UNSIGNEDP selects between signed and unsigned types.  */
@@ -209,106 +193,6 @@ java_type_for_size (unsigned bits, int unsignedp)
   return 0;
 }
 
   return 0;
 }
 
-/* Return a type the same as TYPE except unsigned or
-   signed according to UNSIGNEDP.  */
-
-tree
-java_signed_or_unsigned_type (int unsignedp, tree type)
-{
-  if (! INTEGRAL_TYPE_P (type))
-    return type;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (int_type_node))
-    return unsignedp ? unsigned_int_type_node : int_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (byte_type_node))
-    return unsignedp ? unsigned_byte_type_node : byte_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (short_type_node))
-    return unsignedp ? unsigned_short_type_node : short_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_type_node))
-    return unsignedp ? unsigned_long_type_node : long_type_node;
-  return type;
-}
-
-/* Return a signed type the same as TYPE in other respects.  */
-
-tree
-java_signed_type (tree type)
-{
-  return java_signed_or_unsigned_type (0, type);
-}
-
-/* Return an unsigned type the same as TYPE in other respects.  */
-
-tree
-java_unsigned_type (tree 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 true if successful.  */
-
-bool
-java_mark_addressable (tree exp)
-{
-  tree x = exp;
-  while (1)
-    switch (TREE_CODE (x))
-      {
-      case ADDR_EXPR:
-      case COMPONENT_REF:
-      case ARRAY_REF:
-      case REALPART_EXPR:
-      case IMAGPART_EXPR:
-       x = TREE_OPERAND (x, 0);
-       break;
-
-      case TRUTH_ANDIF_EXPR:
-      case TRUTH_ORIF_EXPR:
-      case COMPOUND_EXPR:
-       x = TREE_OPERAND (x, 1);
-       break;
-
-      case COND_EXPR:
-       return java_mark_addressable (TREE_OPERAND (x, 1))
-         && java_mark_addressable (TREE_OPERAND (x, 2));
-
-      case CONSTRUCTOR:
-       TREE_ADDRESSABLE (x) = 1;
-       return true;
-
-      case INDIRECT_REF:
-       /* We sometimes add a cast *(TYPE*)&FOO to handle type and mode
-          incompatibility problems.  Handle this case by marking FOO.  */
-       if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR
-           && TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR)
-         {
-           x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
-           break;
-         }
-       if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
-         {
-           x = TREE_OPERAND (x, 0);
-           break;
-         }
-       return true;
-
-      case VAR_DECL:
-      case CONST_DECL:
-      case PARM_DECL:
-      case RESULT_DECL:
-      case FUNCTION_DECL:
-       TREE_ADDRESSABLE (x) = 1;
-#if 0  /* poplevel deals with this now.  */
-       if (DECL_CONTEXT (x) == 0)
-         TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
-#endif
-       /* drops through */
-      default:
-       return true;
-    }
-}
-
 /* Thorough checking of the arrayness of TYPE.  */
 
 int
 /* Thorough checking of the arrayness of TYPE.  */
 
 int
@@ -342,7 +226,7 @@ java_array_type_length (tree array_type)
   return -1;
 }
 
   return -1;
 }
 
-/* An array of unknown length will be ultimately given an length of
+/* An array of unknown length will be ultimately given a length of
    -2, so that we can still have `length' producing a negative value
    even if found. This was part of an optimization aiming at removing
    `length' from static arrays. We could restore it, FIXME.  */
    -2, so that we can still have `length' producing a negative value
    even if found. This was part of an optimization aiming at removing
    `length' from static arrays. We could restore it, FIXME.  */
@@ -354,8 +238,7 @@ build_prim_array_type (tree element_type, HOST_WIDE_INT length)
 
   if (length != -1)
     {
 
   if (length != -1)
     {
-      tree max_index = build_int_2 (length - 1, (0 == length ? -1 : 0));
-      TREE_TYPE (max_index) = sizetype;
+      tree max_index = build_int_cst (sizetype, length - 1);
       index = build_index_type (max_index);
     }
   return build_array_type (element_type, index);
       index = build_index_type (max_index);
     }
   return build_array_type (element_type, index);
@@ -369,7 +252,7 @@ tree
 build_java_array_type (tree element_type, HOST_WIDE_INT length)
 {
   tree sig, t, fld, atype, arfld;
 build_java_array_type (tree element_type, HOST_WIDE_INT length)
 {
   tree sig, t, fld, atype, arfld;
-  char buf[12];
+  char buf[23];
   tree elsig = build_java_signature (element_type);
   tree el_name = element_type;
   buf[0] = '[';
   tree elsig = build_java_signature (element_type);
   tree el_name = element_type;
   buf[0] = '[';
@@ -391,9 +274,19 @@ build_java_array_type (tree element_type, HOST_WIDE_INT length)
   el_name = TYPE_NAME (el_name);
   if (TREE_CODE (el_name) == TYPE_DECL)
     el_name = DECL_NAME (el_name);
   el_name = TYPE_NAME (el_name);
   if (TREE_CODE (el_name) == TYPE_DECL)
     el_name = DECL_NAME (el_name);
-  TYPE_NAME (t) = build_decl (TYPE_DECL,
-                             identifier_subst (el_name, "", '.', '.', "[]"),
+  {
+    char suffix[23];
+    if (length >= 0)
+      sprintf (suffix, "[%d]", (int)length); 
+    else
+      strcpy (suffix, "[]");
+    TYPE_NAME (t) 
+      = TYPE_STUB_DECL (t)
+      = build_decl (input_location, TYPE_DECL,
+                   identifier_subst (el_name, "", '.', '.', suffix),
                              t);
                              t);
+    TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (t)) = true;
+  }
 
   set_java_signature (t, sig);
   set_super_info (0, t, object_type_node, 0);
 
   set_java_signature (t, sig);
   set_super_info (0, t, object_type_node, 0);
@@ -402,7 +295,8 @@ build_java_array_type (tree element_type, HOST_WIDE_INT length)
   TYPE_ARRAY_ELEMENT (t) = element_type;
 
   /* Add length pseudo-field. */
   TYPE_ARRAY_ELEMENT (t) = element_type;
 
   /* Add length pseudo-field. */
-  fld = build_decl (FIELD_DECL, get_identifier ("length"), int_type_node);
+  fld = build_decl (input_location,
+                   FIELD_DECL, get_identifier ("length"), int_type_node);
   TYPE_FIELDS (t) = fld;
   DECL_CONTEXT (fld) = t;
   FIELD_PUBLIC (fld) = 1;
   TYPE_FIELDS (t) = fld;
   DECL_CONTEXT (fld) = t;
   FIELD_PUBLIC (fld) = 1;
@@ -410,7 +304,8 @@ build_java_array_type (tree element_type, HOST_WIDE_INT length)
   TREE_READONLY (fld) = 1;
 
   atype = build_prim_array_type (element_type, length);
   TREE_READONLY (fld) = 1;
 
   atype = build_prim_array_type (element_type, length);
-  arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype);
+  arfld = build_decl (input_location,
+                     FIELD_DECL, get_identifier ("data"), atype);
   DECL_CONTEXT (arfld) = t;
   TREE_CHAIN (fld) = arfld;
   DECL_ALIGN (arfld) = TYPE_ALIGN (element_type);
   DECL_CONTEXT (arfld) = t;
   TREE_CHAIN (fld) = arfld;
   DECL_ALIGN (arfld) = TYPE_ALIGN (element_type);
@@ -437,11 +332,9 @@ promote_type (tree type)
       if (type == boolean_type_node)
        return promoted_boolean_type_node;
       goto handle_int;
       if (type == boolean_type_node)
        return promoted_boolean_type_node;
       goto handle_int;
-    case CHAR_TYPE:
+    case INTEGER_TYPE:
       if (type == char_type_node)
        return promoted_char_type_node;
       if (type == char_type_node)
        return promoted_char_type_node;
-      goto handle_int;
-    case INTEGER_TYPE:
     handle_int:
       if (TYPE_PRECISION (type) < TYPE_PRECISION (int_type_node))
        {
     handle_int:
       if (TYPE_PRECISION (type) < TYPE_PRECISION (int_type_node))
        {
@@ -464,9 +357,7 @@ static tree
 parse_signature_type (const unsigned char **ptr, const unsigned char *limit)
 {
   tree type;
 parse_signature_type (const unsigned char **ptr, const unsigned char *limit)
 {
   tree type;
-
-  if (*ptr >= limit)
-    abort ();
+  gcc_assert (*ptr < limit);
 
   switch (**ptr)
     {
 
   switch (**ptr)
     {
@@ -490,17 +381,16 @@ parse_signature_type (const unsigned char **ptr, const unsigned char *limit)
        const unsigned char *str = start;
        for ( ; ; str++)
          {
        const unsigned char *str = start;
        for ( ; ; str++)
          {
-           if (str >= limit)
-             abort ();
+           gcc_assert (str < limit);
            if (*str == ';')
              break;
          }
        *ptr = str+1;
            if (*str == ';')
              break;
          }
        *ptr = str+1;
-       type = lookup_class (unmangle_classname (start, str - start));
+       type = lookup_class (unmangle_classname ((const char *) start, str - start));
        break;
       }
     default:
        break;
       }
     default:
-      abort ();
+      gcc_unreachable ();
     }
   return promote_type (type);
 }
     }
   return promote_type (type);
 }
@@ -611,9 +501,13 @@ build_java_signature (tree type)
       switch (TREE_CODE (type))
        {
        case BOOLEAN_TYPE: sg[0] = 'Z';  goto native;
       switch (TREE_CODE (type))
        {
        case BOOLEAN_TYPE: sg[0] = 'Z';  goto native;
-       case CHAR_TYPE:    sg[0] = 'C';  goto native;
        case VOID_TYPE:    sg[0] = 'V';  goto native;
        case INTEGER_TYPE:
        case VOID_TYPE:    sg[0] = 'V';  goto native;
        case INTEGER_TYPE:
+          if (type == char_type_node || type == promoted_char_type_node)
+           {
+             sg[0] = 'C';
+             goto native;
+           }
          switch (TYPE_PRECISION (type))
            {
            case  8:       sg[0] = 'B';  goto native;
          switch (TYPE_PRECISION (type))
            {
            case  8:       sg[0] = 'B';  goto native;
@@ -668,7 +562,7 @@ build_java_signature (tree type)
          break;
        bad_type:
        default:
          break;
        bad_type:
        default:
-         abort ();
+         gcc_unreachable ();
        }
       TYPE_SIGNATURE (type) = sig;
     }
        }
       TYPE_SIGNATURE (type) = sig;
     }
@@ -733,11 +627,11 @@ lookup_java_method (tree searched_class, tree method_name,
                    method_signature, build_java_signature);
 }
 
                    method_signature, build_java_signature);
 }
 
-/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME.  */
+/* Return true iff KLASS (or its ancestors) has a method METHOD_NAME.  */
 int
 int
-has_method (tree class, tree method_name)
+has_method (tree klass, tree method_name)
 {
 {
-  return lookup_do (class, SEARCH_INTERFACE,
+  return lookup_do (klass, SEARCH_INTERFACE,
                    method_name, NULL_TREE,
                    build_null_signature) != NULL_TREE;
 }
                    method_name, NULL_TREE,
                    build_null_signature) != NULL_TREE;
 }
@@ -796,25 +690,22 @@ find_method_in_interfaces (tree searched_class, int flags, tree method_name,
                            tree signature, tree (*signature_builder) (tree))
 {
   int i;
                            tree signature, tree (*signature_builder) (tree))
 {
   int i;
-  int interface_len = 
-    TREE_VEC_LENGTH (BINFO_BASE_BINFOS (TYPE_BINFO (searched_class))) - 1;
+  tree binfo, base_binfo;
 
 
-  for (i = interface_len; i > 0; i--)
+  for (binfo = TYPE_BINFO (searched_class), i = 1;
+       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
     {
-      tree child = BINFO_BASE_BINFO (TYPE_BINFO (searched_class), i);
-      tree iclass = BINFO_TYPE (child);
+      tree iclass = BINFO_TYPE (base_binfo);
       tree method;
          
       /* If the superinterface hasn't been loaded yet, do so now.  */
       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))
+      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, 
        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);      
+                                   signature, signature_builder);      
       if (method != NULL_TREE)
        return method;
   
       if (method != NULL_TREE)
        return method;
   
@@ -849,6 +740,7 @@ lookup_do (tree searched_class, int flags, tree method_name,
           tree signature, tree (*signature_builder) (tree))
 {
   tree method;
           tree signature, tree (*signature_builder) (tree))
 {
   tree method;
+  tree orig_class = searched_class;
     
   if (searched_class == NULL_TREE)
     return NULL_TREE;
     
   if (searched_class == NULL_TREE)
     return NULL_TREE;
@@ -875,7 +767,7 @@ lookup_do (tree searched_class, int flags, tree method_name,
   
   /* If that doesn't work, look in our interfaces.  */
   if (flags & SEARCH_INTERFACE)
   
   /* If that doesn't work, look in our interfaces.  */
   if (flags & SEARCH_INTERFACE)
-    method = find_method_in_interfaces (searched_class, flags, method_name, 
+    method = find_method_in_interfaces (orig_class, flags, method_name, 
                                        signature, signature_builder);
   
   return method;
                                        signature, signature_builder);
   
   return method;