OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index b1faafc..e9d8174 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions related to building classes and their related objects.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,6 +46,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "cgraph.h"
 #include "tree-iterator.h"
 #include "cgraph.h"
+#include "vecprim.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -68,6 +69,8 @@ static void register_class (void);
 
 struct obstack temporary_obstack;
 
+static const char *cyclic_inheritance_report;
+
 /* The compiler generates different code depending on whether or not
    it can assume certain classes have been compiled down to native
    code or not.  The compiler options -fassume-compiled= and
@@ -497,6 +500,9 @@ set_class_decl_access_flags (int access_flags, tree class_decl)
   if (access_flags & ACC_PRIVATE)   CLASS_PRIVATE (class_decl) = 1;
   if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1;
   if (access_flags & ACC_STRICT)    CLASS_STRICTFP (class_decl) = 1;
+  if (access_flags & ACC_ENUM)      CLASS_ENUM (class_decl) = 1;
+  if (access_flags & ACC_SYNTHETIC) CLASS_SYNTHETIC (class_decl) = 1;
+  if (access_flags & ACC_ANNOTATION) CLASS_ANNOTATION (class_decl) = 1;
 }
 
 /* Return length of inheritance chain of CLAS, where java.lang.Object is 0,
@@ -719,9 +725,6 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
     DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl) =
       htab_create_ggc (50, htab_hash_pointer, htab_eq_pointer, NULL);
 
-  /* Initialize the static method invocation compound list */
-  DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = NULL_TREE;
-
   TREE_CHAIN (fndecl) = TYPE_METHODS (this_class);
   TYPE_METHODS (this_class) = fndecl;
 
@@ -748,6 +751,9 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1;
   if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1;
   if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1;
+  if (access_flags & ACC_SYNTHETIC) DECL_ARTIFICIAL (fndecl) = 1;
+  if (access_flags & ACC_BRIDGE) METHOD_BRIDGE (fndecl) = 1;
+  if (access_flags & ACC_VARARGS) METHOD_VARARGS (fndecl) = 1;
   return fndecl;
 }
 
@@ -780,6 +786,7 @@ add_field (tree class, tree name, tree field_type, int flags)
   TREE_CHAIN (field) = TYPE_FIELDS (class);
   TYPE_FIELDS (class) = field;
   DECL_CONTEXT (field) = class;
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field);
 
   if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1;
   if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1;
@@ -791,15 +798,17 @@ add_field (tree class, tree name, tree field_type, int flags)
       TREE_THIS_VOLATILE (field) = 1;
     }
   if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1;
+  if (flags & ACC_ENUM) FIELD_ENUM (field) = 1;
+  if (flags & ACC_SYNTHETIC) FIELD_SYNTHETIC (field) = 1;
   if (is_static)
     {
       FIELD_STATIC (field) = 1;
       /* Always make field externally visible.  This is required so
         that native methods can always access the field.  */
       TREE_PUBLIC (field) = 1;
-      /* Considered external until we know what classes are being
-        compiled into this object file.  */
-      DECL_EXTERNAL (field) = 1;
+      /* Considered external unless we are compiling it into this
+        object file.  */
+      DECL_EXTERNAL (field) = (is_compiled_class (class) != 2);
     }
 
   return field;
@@ -1219,6 +1228,10 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_VOLATILE;
       if (FIELD_TRANSIENT (decl))
        access_flags |= ACC_TRANSIENT;
+      if (FIELD_ENUM (decl))
+       access_flags |= ACC_ENUM;
+      if (FIELD_SYNTHETIC (decl))
+       access_flags |= ACC_SYNTHETIC;
       return access_flags;
     }
   if (TREE_CODE (decl) == TYPE_DECL)
@@ -1241,6 +1254,12 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_PROTECTED;
       if (CLASS_STRICTFP (decl))
        access_flags |= ACC_STRICT;
+      if (CLASS_ENUM (decl))
+       access_flags |= ACC_ENUM;
+      if (CLASS_SYNTHETIC (decl))
+       access_flags |= ACC_SYNTHETIC;
+      if (CLASS_ANNOTATION (decl))
+       access_flags |= ACC_ANNOTATION;
       return access_flags;
     }
   if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -1265,6 +1284,12 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_STRICT;
       if (METHOD_INVISIBLE (decl))
        access_flags |= ACC_INVISIBLE;
+      if (DECL_ARTIFICIAL (decl))
+       access_flags |= ACC_SYNTHETIC;
+      if (METHOD_BRIDGE (decl))
+       access_flags |= ACC_BRIDGE;
+      if (METHOD_VARARGS (decl))
+       access_flags |= ACC_VARARGS;
       return access_flags;
     }
   gcc_unreachable ();
@@ -1646,6 +1671,8 @@ make_class_data (tree type)
       to where objects actually point at, following new g++ ABI. */
   tree dtable_start_offset = build_int_cst (NULL_TREE,
                                            2 * POINTER_SIZE / BITS_PER_UNIT);
+  VEC(int, heap) *field_indexes;
+  tree first_real_field;
 
   this_class_addr = build_static_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
@@ -1655,15 +1682,28 @@ make_class_data (tree type)
     {
       tree dtable = get_dispatch_table (type, this_class_addr);
       uses_jv_markobj = uses_jv_markobj_p (dtable);
-      dtable_decl = build_dtable_decl (type);
-      DECL_INITIAL (dtable_decl) = dtable;
-      TREE_STATIC (dtable_decl) = 1;
-      DECL_ARTIFICIAL (dtable_decl) = 1;
-      DECL_IGNORED_P (dtable_decl) = 1;
+      if (type == class_type_node && class_dtable_decl != NULL_TREE)
+       {
+         /* We've already created some other class, and consequently
+            we made class_dtable_decl.  Now we just want to fill it
+            in.  */
+         dtable_decl = class_dtable_decl;
+       }
+      else
+       {
+         dtable_decl = build_dtable_decl (type);
+         TREE_STATIC (dtable_decl) = 1;
+         DECL_ARTIFICIAL (dtable_decl) = 1;
+         DECL_IGNORED_P (dtable_decl) = 1;
+       }
+
       TREE_PUBLIC (dtable_decl) = 1;
+      DECL_INITIAL (dtable_decl) = dtable;
       if (! flag_indirect_classes)
        rest_of_decl_compilation (dtable_decl, 1, 0);
-      if (type == class_type_node)
+      /* Maybe we're compiling Class as the first class.  If so, set
+        class_dtable_decl to the decl we just made.  */
+      if (type == class_type_node && class_dtable_decl == NULL_TREE)
        class_dtable_decl = dtable_decl;
     }
 
@@ -1673,7 +1713,54 @@ make_class_data (tree type)
     field = TREE_CHAIN (field);  /* Skip dummy fields.  */
   if (field && DECL_NAME (field) == NULL_TREE)
     field = TREE_CHAIN (field);  /* Skip dummy field for inherited data. */
-  for ( ;  field != NULL_TREE;  field = TREE_CHAIN (field))
+  first_real_field = field;
+
+  /* First count static and instance fields.  */
+  for ( ; field != NULL_TREE; field = TREE_CHAIN (field))
+    {
+      if (! DECL_ARTIFICIAL (field))
+       {
+         if (FIELD_STATIC (field))
+           static_field_count++;
+         else if (uses_jv_markobj || !flag_reduced_reflection)
+           instance_field_count++;
+       }
+    }
+  field_count = static_field_count + instance_field_count;
+  field_indexes = VEC_alloc (int, heap, field_count);
+  
+  /* gcj sorts fields so that static fields come first, followed by
+     instance fields.  Unfortunately, by the time this takes place we
+     have already generated the reflection_data for this class, and
+     that data contians indexes into the fields.  So, we generate a
+     permutation that maps each original field index to its final
+     position.  Then we pass this permutation to
+     rewrite_reflection_indexes(), which fixes up the reflection
+     data.  */
+  {
+    int i;
+    int static_count = 0;
+    int instance_count = static_field_count;
+    int field_index;
+
+    for (i = 0, field = first_real_field; 
+        field != NULL_TREE; 
+        field = TREE_CHAIN (field), i++)
+    {
+      if (! DECL_ARTIFICIAL (field))
+       {
+         field_index = 0;
+         if (FIELD_STATIC (field))
+           field_index = static_count++;
+         else if (uses_jv_markobj || !flag_reduced_reflection)
+           field_index = instance_count++;
+         VEC_quick_push (int, field_indexes, field_index);
+       }
+    }
+  }
+
+  for (field = first_real_field; field != NULL_TREE; 
+       field = TREE_CHAIN (field))
     {
       if (! DECL_ARTIFICIAL (field))
        {
@@ -1683,7 +1770,6 @@ make_class_data (tree type)
                  as it is used in the creation of the field itself. */
               tree init = make_field_value (field);
              tree initial = DECL_INITIAL (field);
-             static_field_count++;
              static_fields = tree_cons (NULL_TREE, init, static_fields);
              /* If the initial value is a string constant,
                 prevent output_constant from trying to assemble the value. */
@@ -1696,12 +1782,11 @@ make_class_data (tree type)
          else if (uses_jv_markobj || !flag_reduced_reflection)
            {
               tree init = make_field_value (field);
-             instance_field_count++;
              instance_fields = tree_cons (NULL_TREE, init, instance_fields);
            }
        }
     }
-  field_count = static_field_count + instance_field_count;
+
   if (field_count > 0)
     {
       static_fields = nreverse (static_fields);
@@ -1781,8 +1866,10 @@ make_class_data (tree type)
       DECL_ARTIFICIAL (class_dtable_decl) = 1;
       DECL_IGNORED_P (class_dtable_decl) = 1;
       if (is_compiled_class (class_type_node) != 2)
-       DECL_EXTERNAL (class_dtable_decl) = 1;
-      rest_of_decl_compilation (class_dtable_decl, 1, 0);
+       {
+         DECL_EXTERNAL (class_dtable_decl) = 1;
+         rest_of_decl_compilation (class_dtable_decl, 1, 0);
+       }
     }
 
   super = CLASSTYPE_SUPER (type);
@@ -2001,6 +2088,48 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
 
+  if (TYPE_REFLECTION_DATA (current_class))
+    {
+      int i;
+      int count = TYPE_REFLECTION_DATASIZE (current_class);
+      VEC (constructor_elt, gc) *v
+       = VEC_alloc (constructor_elt, gc, count);
+      unsigned char *data = TYPE_REFLECTION_DATA (current_class);
+      tree max_index = build_int_cst (sizetype, count);
+      tree index = build_index_type (max_index);
+      tree type = build_array_type (unsigned_byte_type_node, index);
+      char buf[64];
+      tree array;
+      static int reflection_data_count;
+
+      sprintf (buf, "_reflection_data_%d", reflection_data_count++);
+      array = build_decl (VAR_DECL, get_identifier (buf), type);
+
+      rewrite_reflection_indexes (field_indexes);
+
+      for (i = 0; i < count; i++)
+       {
+         constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+         elt->index = build_int_cst (sizetype, i);
+         elt->value = build_int_cstu (byte_type_node, data[i]);
+       }
+
+      DECL_INITIAL (array) = build_constructor (type, v);
+      TREE_STATIC (array) = 1;
+      DECL_ARTIFICIAL (array) = 1;
+      DECL_IGNORED_P (array) = 1;
+      TREE_READONLY (array) = 1;
+      TREE_CONSTANT (DECL_INITIAL (array)) = 1;
+      rest_of_decl_compilation (array, 1, 0);
+      
+      PUSH_FIELD_VALUE (cons, "reflection_data", build_address_of (array));
+
+      free (data);
+      TYPE_REFLECTION_DATA (current_class) = NULL;
+    }
+  else
+    PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node);
+
   FINISH_RECORD_CONSTRUCTOR (cons);
 
   DECL_INITIAL (decl) = cons;
@@ -2066,11 +2195,13 @@ is_compiled_class (tree class)
     return 1;
   if (TYPE_ARRAY_P (class))
     return 0;
+  /* We have to check this explicitly to avoid trying to load a class
+     that we're currently parsing.  */
   if (class == current_class)
     return 2;
 
   seen_in_zip = (TYPE_JCF (class) && JCF_SEEN_IN_ZIP (TYPE_JCF (class)));
-  if (CLASS_FROM_CURRENTLY_COMPILED_P (class) || seen_in_zip)
+  if (CLASS_FROM_CURRENTLY_COMPILED_P (class))
     {
       /* The class was seen in the current ZIP file and will be
         available as a compiled class in the future but may not have
@@ -2182,7 +2313,7 @@ push_super_field (tree this_class, tree super_class)
 /* Handle the different manners we may have to lay out a super class.  */
 
 static tree
-maybe_layout_super_class (tree super_class, tree this_class)
+maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED)
 {
   if (!super_class)
     return NULL_TREE;
@@ -2201,6 +2332,7 @@ maybe_layout_super_class (tree super_class, tree this_class)
        super_class = TREE_TYPE (super_class);
       else
        {
+#if 0
          /* do_resolve_class expects an EXPR_WITH_FILE_LOCATION, so
             we give it one.  */
          tree this_wrap = NULL_TREE;
@@ -2226,6 +2358,8 @@ maybe_layout_super_class (tree super_class, tree this_class)
          if (!super_class)
            return NULL_TREE;   /* FIXME, NULL_TREE not checked by caller. */
          super_class = TREE_TYPE (super_class);
+#endif
+         gcc_unreachable ();
        }
     }
   if (!TYPE_SIZE (super_class))
@@ -2234,6 +2368,22 @@ maybe_layout_super_class (tree super_class, tree this_class)
   return super_class;
 }
 
+/* safe_layout_class just makes sure that we can load a class without
+   disrupting the current_class, input_file, input_line, etc, information
+   about the class processed currently.  */
+
+void
+safe_layout_class (tree class)
+{
+  tree save_current_class = current_class;
+  location_t save_location = input_location;
+
+  layout_class (class);
+
+  current_class = save_current_class;
+  input_location = save_location;
+}
+
 void
 layout_class (tree this_class)
 {
@@ -2450,9 +2600,10 @@ layout_class_method (tree this_class, tree super_class,
   tree method_name = DECL_NAME (method_decl);
 
   TREE_PUBLIC (method_decl) = 1;
-  /* Considered external until we know what classes are being
-     compiled into this object file.  */
-  DECL_EXTERNAL (method_decl) = 1;
+  /* Considered external unless it is being compiled into this object
+     file.  */
+  DECL_EXTERNAL (method_decl) = ((is_compiled_class (this_class) != 2)
+                                || METHOD_NATIVE (method_decl));
 
   if (ID_INIT_P (method_name))
     {
@@ -2464,14 +2615,14 @@ layout_class_method (tree this_class, tree super_class,
            p = ptr;
        }
       DECL_CONSTRUCTOR_P (method_decl) = 1;
-      build_java_argument_signature (TREE_TYPE (method_decl));
+      build_java_signature (TREE_TYPE (method_decl));
     }
   else if (! METHOD_STATIC (method_decl))
     {
       tree method_sig =
-       build_java_argument_signature (TREE_TYPE (method_decl));
+       build_java_signature (TREE_TYPE (method_decl));
       bool method_override = false;
-      tree super_method = lookup_argument_method (super_class, method_name,
+      tree super_method = lookup_java_method (super_class, method_name,
                                                  method_sig);
       if (super_method != NULL_TREE
          && ! METHOD_DUMMY (super_method))