aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/class.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@gcc.gnu.org>2007-01-09 19:58:05 +0000
committerTom Tromey <tromey@gcc.gnu.org>2007-01-09 19:58:05 +0000
commit97b8365cafc3a344a22d3980b8ed885f5c6d8357 (patch)
tree996a5f57d4a68c53473382e45cb22f574cb3e4db /gcc/java/class.c
parentc648dedbde727ca3f883bb5fd773aa4af70d3369 (diff)
downloadgcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.zip
gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.gz
gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.bz2
Merged gcj-eclipse branch to trunk.
From-SVN: r120621
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r--gcc/java/class.c207
1 files changed, 179 insertions, 28 deletions
diff --git a/gcc/java/class.c b/gcc/java/class.c
index b1faafc..e9d8174 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -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))