/* Functions related to building classes and their related objects.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "system.h"
#include "tree.h"
#include "rtl.h"
+#include "flags.h"
#include "java-tree.h"
#include "jcf.h"
#include "obstack.h"
#include "toplev.h"
-
-static tree mangle_class_field PROTO ((tree class));
+#include "output.h"
+#include "parse.h"
+
+static tree mangle_class_field PARAMS ((tree class));
+static tree make_method_value PARAMS ((tree));
+static tree build_java_method_type PARAMS ((tree, tree, int));
+static int32 hashUtf8String PARAMS ((const char *, int));
+static tree make_field_value PARAMS ((tree));
+static tree get_dispatch_vector PARAMS ((tree));
+static tree get_dispatch_table PARAMS ((tree, tree));
+static void append_gpp_mangled_type PARAMS ((struct obstack *, tree));
+static tree mangle_static_field PARAMS ((tree));
+static void add_interface_do PARAMS ((tree, tree, int));
+static tree maybe_layout_super_class PARAMS ((tree, tree));
+static int assume_compiled PARAMS ((const char *));
+static struct hash_entry *init_test_hash_newfunc PARAMS ((struct hash_entry *,
+ struct hash_table *,
+ hash_table_key));
static rtx registerClass_libfunc;
extern struct obstack permanent_obstack;
extern struct obstack temporary_obstack;
+/* 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
+ -fno-assume-compiled= are used to create a tree of
+ assume_compiled_node objects. This tree is queried to determine if
+ a class is assume to be compiled or not. Each node in the tree
+ represents either a package or a specific class. */
+
+typedef struct assume_compiled_node_struct
+{
+ /* The class or package name. */
+ const char *ident;
+
+ /* Non-zero if this represents an exclusion. */
+ int excludep;
+
+ /* Pointers to other nodes in the tree. */
+ struct assume_compiled_node_struct *parent;
+ struct assume_compiled_node_struct *sibling;
+ struct assume_compiled_node_struct *child;
+} assume_compiled_node;
+
+static assume_compiled_node *find_assume_compiled_node
+ PARAMS ((assume_compiled_node *, const char *));
+
+/* This is the root of the include/exclude tree. */
+
+static assume_compiled_node *assume_compiled_tree;
+
+/* Return the node that most closely represents the class whose name
+ is IDENT. Start the search from NODE. Return NULL if an
+ appropriate node does not exist. */
+
+static assume_compiled_node *
+find_assume_compiled_node (node, ident)
+ assume_compiled_node *node;
+ const char *ident;
+{
+ while (node)
+ {
+ size_t node_ident_length = strlen (node->ident);
+
+ /* node_ident_length is zero at the root of the tree. If the
+ identifiers are the same length, then we have matching
+ classes. Otherwise check if we've matched an enclosing
+ package name. */
+
+ if (node_ident_length == 0
+ || (strncmp (ident, node->ident, node_ident_length) == 0
+ && (strlen (ident) == node_ident_length
+ || ident[node_ident_length] == '.')))
+ {
+ /* We've found a match, however, there might be a more
+ specific match. */
+
+ assume_compiled_node *found = find_assume_compiled_node (node->child,
+ ident);
+ if (found)
+ return found;
+ else
+ return node;
+ }
+
+ /* No match yet. Continue through the sibling list. */
+ node = node->sibling;
+ }
+
+ /* No match at all in this tree. */
+ return NULL;
+}
+
+/* Add a new IDENT to the include/exclude tree. It's an exclusion
+ if EXCLUDEP is non-zero. */
+
+void
+add_assume_compiled (ident, excludep)
+ const char *ident;
+ int excludep;
+{
+ assume_compiled_node *parent;
+ assume_compiled_node *node =
+ (assume_compiled_node *) xmalloc (sizeof (assume_compiled_node));
+
+ node->ident = xstrdup (ident);
+ node->excludep = excludep;
+ node->child = NULL;
+
+ /* Create the root of the tree if it doesn't exist yet. */
+
+ if (NULL == assume_compiled_tree)
+ {
+ assume_compiled_tree =
+ (assume_compiled_node *) xmalloc (sizeof (assume_compiled_node));
+ assume_compiled_tree->ident = "";
+ assume_compiled_tree->excludep = 0;
+ assume_compiled_tree->sibling = NULL;
+ assume_compiled_tree->child = NULL;
+ assume_compiled_tree->parent = NULL;
+ }
+
+ /* Calling the function with the empty string means we're setting
+ excludep for the root of the hierarchy. */
+
+ if (0 == ident[0])
+ {
+ assume_compiled_tree->excludep = excludep;
+ return;
+ }
+
+ /* Find the parent node for this new node. PARENT will either be a
+ class or a package name. Adjust PARENT accordingly. */
+
+ parent = find_assume_compiled_node (assume_compiled_tree, ident);
+ if (ident[strlen (parent->ident)] != '.')
+ parent = parent->parent;
+
+ /* Insert NODE into the tree. */
+
+ node->parent = parent;
+ node->sibling = parent->child;
+ parent->child = node;
+}
+
+/* Returns non-zero if IDENT is the name of a class that the compiler
+ should assume has been compiled to FIXME */
+
+static int
+assume_compiled (ident)
+ const char *ident;
+{
+ assume_compiled_node *i;
+ int result;
+
+ if (NULL == assume_compiled_tree)
+ return 1;
+
+ i = find_assume_compiled_node (assume_compiled_tree,
+ ident);
+
+ result = ! i->excludep;
+
+ return (result);
+}
+
/* Return an IDENTIFIER_NODE the same as (OLD_NAME, OLD_LENGTH).
except that characters matching OLD_CHAR are substituted by NEW_CHAR.
Also, PREFIX is prepended, and SUFFIX is appended. */
tree
mangled_classname (prefix, type)
- char *prefix;
- tree type;
+ const char *prefix;
+ tree type;
{
tree ident = TYPE_NAME (type);
if (TREE_CODE (ident) != IDENTIFIER_NODE)
ident = DECL_NAME (ident);
- return identifier_subst (ident, prefix, '/', '_', "");
+ return identifier_subst (ident, prefix, '.', '_', "");
}
tree
#else
TYPE_BINFO (type) = make_tree_vec (6);
#endif
- CLASS_P (type) = 1;
+ MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
pop_obstacks ();
return type;
const char *name; int name_length;
{
tree to_return = ident_subst (name, name_length, "", '/', '.', "");
- if (to_return != get_identifier ((char *)name))
- QUALIFIED_P (to_return) = 1;
+ /* It's not sufficient to compare to_return and get_identifier
+ (name) to determine whether to_return is qualified. There are
+ cases in signature analysis where name will be stripped of a
+ trailing ';'. */
+ name = IDENTIFIER_POINTER (to_return);
+ while (*name)
+ if (*name++ == '.')
+ {
+ QUALIFIED_P (to_return) = 1;
+ break;
+ }
+
return to_return;
}
int save_lineno = lineno;
tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
push_obstacks (&permanent_obstack, &permanent_obstack);
+ CLASS_P (class_type) = 1;
input_filename = IDENTIFIER_POINTER (source_name);
lineno = 0;
decl = build_decl (TYPE_DECL, class_name, class_type);
CLASS_HAS_SUPER (this_class) = 1;
}
pop_obstacks ();
-
+
if (access_flags & ACC_PUBLIC) CLASS_PUBLIC (class_decl) = 1;
if (access_flags & ACC_FINAL) CLASS_FINAL (class_decl) = 1;
if (access_flags & ACC_SUPER) CLASS_SUPER (class_decl) = 1;
if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1;
if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1;
+ if (access_flags & ACC_STATIC) CLASS_STATIC (class_decl) = 1;
}
/* Return length of inheritance chain of CLAS, where java.lang.Object is 0,
int depth = 0;
if (! CLASS_LOADED_P (clas))
load_class (clas, 1);
+ if (TYPE_SIZE (clas) == error_mark_node)
+ return -1;
while (clas != object_type_node)
{
depth++;
return 0;
}
+/* Return a 1 iff TYPE1 is an enclosing context for TYPE2 */
+
+int
+enclosing_context_p (type1, type2)
+ tree type1, type2;
+{
+ if (!INNER_CLASS_TYPE_P (type2))
+ return 0;
+
+ for (type2 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2)));
+ type2;
+ type2 = (INNER_CLASS_TYPE_P (type2) ?
+ TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))) : NULL_TREE))
+ {
+ if (type2 == type1)
+ return 1;
+ }
+
+ return 0;
+}
+
static void
add_interface_do (basetype_vec, interface_class, i)
tree basetype_vec, interface_class;
tree this_class, interface_class;
{
tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
- tree interface_binfo = make_tree_vec (6);
int i;
int n = TREE_VEC_LENGTH (basetype_vec);
for (i = 0; ; i++)
add_interface_do (basetype_vec, interface_class, i);
}
+#if 0
/* Return the address of a pointer to the first FUNCTION_DECL
in the list (*LIST) whose DECL_NAME is NAME. */
list = &TREE_CHAIN (*list);
return list;
}
+#endif
-tree
+static tree
build_java_method_type (fntype, this_class, access_flags)
tree fntype;
tree this_class;
return build_method_type (CLASS_TO_HANDLE_TYPE (this_class), fntype);
}
+static struct hash_entry *
+init_test_hash_newfunc (entry, table, string)
+ struct hash_entry *entry;
+ struct hash_table *table;
+ hash_table_key string ATTRIBUTE_UNUSED;
+{
+ struct init_test_hash_entry *ret = (struct init_test_hash_entry *) entry;
+ if (ret == NULL)
+ {
+ ret = ((struct init_test_hash_entry *)
+ hash_allocate (table, sizeof (struct init_test_hash_entry)));
+ if (ret == NULL)
+ return NULL;
+ }
+ ret->init_test_decl = 0;
+ return (struct hash_entry *) ret;
+}
+
+/* Hash table helpers. Also reused in find_applicable_accessible_methods_list
+ (parse.y). The hash of a tree node is it's pointer value,
+ comparison is direct. */
+
+unsigned long
+java_hash_hash_tree_node (k)
+ hash_table_key k;
+{
+ return (long) k;
+}
+
+boolean
+java_hash_compare_tree_node (k1, k2)
+ hash_table_key k1;
+ hash_table_key k2;
+{
+ return ((char*) k1 == (char*) k2);
+}
+
tree
add_method_1 (handle_class, access_flags, name, function_type)
tree handle_class;
DECL_LANG_SPECIFIC (fndecl)
= (struct lang_decl *) permalloc (sizeof (struct lang_decl));
- bzero (DECL_LANG_SPECIFIC (fndecl), sizeof (struct lang_decl));
+ bzero ((PTR) DECL_LANG_SPECIFIC (fndecl), sizeof (struct lang_decl));
+
+ /* Initialize the static initializer test table. */
+ hash_table_init (&DECL_FUNCTION_INIT_TEST_TABLE (fndecl),
+ init_test_hash_newfunc, java_hash_hash_tree_node,
+ java_hash_compare_tree_node);
TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class);
TYPE_METHODS (handle_class) = fndecl;
if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1;
if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1;
- if (access_flags & ACC_PRIVATE) METHOD_PRIVATE (fndecl) = 1;
- if (access_flags & ACC_NATIVE) METHOD_NATIVE (fndecl) = 1;
- if (access_flags & ACC_STATIC) METHOD_STATIC (fndecl) = 1;
- if (access_flags & ACC_FINAL) METHOD_FINAL (fndecl) = 1;
+ if (access_flags & ACC_PRIVATE)
+ METHOD_PRIVATE (fndecl) = DECL_INLINE (fndecl) = 1;
+ if (access_flags & ACC_NATIVE)
+ {
+ METHOD_NATIVE (fndecl) = 1;
+ DECL_EXTERNAL (fndecl) = 1;
+ }
+ if (access_flags & ACC_STATIC)
+ METHOD_STATIC (fndecl) = DECL_INLINE (fndecl) = 1;
+ if (access_flags & ACC_FINAL)
+ METHOD_FINAL (fndecl) = DECL_INLINE (fndecl) = 1;
if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1;
if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1;
if (access_flags & ACC_TRANSIENT) METHOD_TRANSIENT (fndecl) = 1;
{
tree handle_class = CLASS_TO_HANDLE_TYPE (this_class);
tree function_type, fndecl;
- unsigned char *sig = (unsigned char*)IDENTIFIER_POINTER (method_sig);
+ const unsigned char *sig = (const unsigned char*)IDENTIFIER_POINTER (method_sig);
push_obstacks (&permanent_obstack, &permanent_obstack);
if (sig[0] != '(')
fatal ("bad method signature");
/* Count the number of Unicode chars encoded in a given Ut8 string. */
+#if 0
int
strLengthUtf8 (str, len)
char *str;
}
return str_length;
}
+#endif
/* Calculate a hash value for a string encoded in Utf8 format.
* This returns the same hash value as specified for java.lang.String.hashCode.
*/
-int32
+static int32
hashUtf8String (str, len)
- char *str;
+ const char *str;
int len;
{
- register unsigned char* ptr = (unsigned char*) str;
- register unsigned char *limit = ptr + len;
+ register const unsigned char* ptr = (const unsigned char*) str;
+ register const unsigned char *limit = ptr + len;
int32 hash = 0;
for (; ptr < limit;)
{
build_utf8_ref (name)
tree name;
{
- char* name_ptr = IDENTIFIER_POINTER(name);
+ const char * name_ptr = IDENTIFIER_POINTER(name);
int name_len = IDENTIFIER_LENGTH(name);
char buf[60];
char *buf_ptr;
- tree ctype, field, str_type, cinit, string;
+ tree ctype, field = NULL_TREE, str_type, cinit, string;
static int utf8_count = 0;
int name_hash;
tree ref = IDENTIFIER_UTF8_REF (name);
TREE_TYPE (string) = str_type;
PUSH_FIELD_VALUE (cinit, "data", string);
FINISH_RECORD_CONSTRUCTOR (cinit);
+ TREE_CONSTANT (cinit) = 1;
/* Build a unique identifier based on buf. */
sprintf(buf, "_Utf%d", ++utf8_count);
buf_ptr = &buf[strlen (buf)];
+ if (name_len > 0 && name_ptr[0] >= '0' && name_ptr[0] <= '9')
+ *buf_ptr++ = '_';
while (--name_len >= 0)
{
- char c = *name_ptr++;
+ unsigned char c = *name_ptr++;
if (c & 0x80)
continue;
- if (!isalpha(c) && !isdigit(c))
+ if (!ISALPHA(c) && !ISDIGIT(c))
c = '_';
*buf_ptr++ = c;
if (buf_ptr >= buf + 50)
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
TREE_READONLY (decl) = 1;
+ TREE_THIS_VOLATILE (decl) = 0;
DECL_INITIAL (decl) = cinit;
TREE_CHAIN (decl) = utf8_decl_list;
layout_decl (decl, 0);
push_obstacks (&permanent_obstack, &permanent_obstack);
decl = build_decl (VAR_DECL, decl_name, class_type_node);
DECL_SIZE (decl) = TYPE_SIZE (class_type_node);
+ DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (class_type_node);
TREE_STATIC (decl) = 1;
TREE_PUBLIC (decl) = 1;
DECL_IGNORED_P (decl) = 1;
}
else
{
- char *name;
+ const char *name;
char buffer[25];
+ if (flag_emit_class_files)
+ {
+ const char *prim_class_name;
+ tree prim_class;
+ if (type == char_type_node)
+ prim_class_name = "java.lang.Character";
+ else if (type == boolean_type_node)
+ prim_class_name = "java.lang.Boolean";
+ else if (type == byte_type_node)
+ prim_class_name = "java.lang.Byte";
+ else if (type == short_type_node)
+ prim_class_name = "java.lang.Short";
+ else if (type == int_type_node)
+ prim_class_name = "java.lang.Integer";
+ else if (type == long_type_node)
+ prim_class_name = "java.lang.Long";
+ else if (type == float_type_node)
+ prim_class_name = "java.lang.Float";
+ else if (type == double_type_node)
+ prim_class_name = "java.lang.Double";
+ else if (type == void_type_node)
+ prim_class_name = "java.lang.Void";
+ else
+ fatal ("internal error - bad type to build_class_ref");
+ prim_class = lookup_class (get_identifier (prim_class_name));
+ return build (COMPONENT_REF, NULL_TREE,
+ prim_class, TYPE_identifier_node);
+ }
decl_name = TYPE_NAME (type);
if (TREE_CODE (decl_name) == TYPE_DECL)
decl_name = DECL_NAME (decl_name);
else
{
/* Compile as:
- * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr
- */
+ * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
static tree fields_ident = NULL_TREE;
static tree info_ident = NULL_TREE;
tree ref = build_class_ref (fclass);
access_flags |= ACC_INTERFACE;
if (CLASS_ABSTRACT (decl))
access_flags |= ACC_ABSTRACT;
+ if (CLASS_STATIC (decl))
+ access_flags |= ACC_STATIC;
return access_flags;
}
if (TREE_CODE (decl) == FUNCTION_DECL)
abort ();
}
-tree
-make_field_value (tree fdecl)
+static tree
+make_field_value (fdecl)
+ tree fdecl;
{
- tree finit, info;
- int bsize, flags;
+ tree finit;
+ int flags;
tree type = TREE_TYPE (fdecl);
int resolved = is_compiled_class (type);
+
START_RECORD_CONSTRUCTOR (finit, field_type_node);
PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl)));
if (resolved)
type = build_class_ref (type);
else
- type = build_utf8_ref (build_java_signature (type));
+ {
+ tree signature = build_java_signature (type);
+
+ type = build_utf8_ref (unmangle_classname
+ (IDENTIFIER_POINTER (signature),
+ IDENTIFIER_LENGTH (signature)));
+ }
PUSH_FIELD_VALUE (finit, "type", type);
+
flags = get_access_flags_from_decl (fdecl);
if (! resolved)
flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */;
+
PUSH_FIELD_VALUE (finit, "accflags", build_int_2 (flags, 0));
- bsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (fdecl))) / BITS_PER_UNIT;
- PUSH_FIELD_VALUE (finit, "bsize", build_int_2 (bsize, 0));
- if (FIELD_STATIC (fdecl))
- {
- tree cfield = TREE_CHAIN (TYPE_FIELDS(field_info_union_node));
- tree faddr = build_address_of (build_static_field_ref (fdecl));
- info = build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
- build_tree_list (cfield, faddr));
- }
- else
- {
- int boffset
- = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (fdecl)) / BITS_PER_UNIT;
- info = build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
- build_tree_list (TYPE_FIELDS(field_info_union_node),
- build_int_2 (boffset, 0)));
- }
- PUSH_FIELD_VALUE (finit, "info", info);
+ PUSH_FIELD_VALUE (finit, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl)));
+
+ PUSH_FIELD_VALUE
+ (finit, "info",
+ build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
+ build_tree_list
+ ((FIELD_STATIC (fdecl)
+ ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
+ : TYPE_FIELDS (field_info_union_node)),
+ (FIELD_STATIC (fdecl)
+ ? build_address_of (build_static_field_ref (fdecl))
+ : byte_position (fdecl)))));
FINISH_RECORD_CONSTRUCTOR (finit);
return finit;
}
-tree
-make_method_value (mdecl, this_class_addr)
+static tree
+make_method_value (mdecl)
tree mdecl;
- tree this_class_addr;
{
tree minit;
tree code;
build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ?
init_identifier_node
: DECL_NAME (mdecl)));
- PUSH_FIELD_VALUE (minit, "signature",
- build_utf8_ref (build_java_signature (TREE_TYPE (mdecl))));
+ {
+ tree signature = build_java_signature (TREE_TYPE (mdecl));
+ PUSH_FIELD_VALUE (minit, "signature",
+ (build_utf8_ref
+ (unmangle_classname
+ (IDENTIFIER_POINTER(signature),
+ IDENTIFIER_LENGTH(signature)))));
+ }
PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0));
PUSH_FIELD_VALUE (minit, "ncode", code);
FINISH_RECORD_CONSTRUCTOR (minit);
return minit;
}
-tree
+static tree
get_dispatch_vector (type)
tree type;
{
tree vtable = TYPE_VTABLE (type);
if (vtable == NULL)
{
- int i;
+ HOST_WIDE_INT i;
tree method;
tree super = CLASSTYPE_SUPER (type);
- int nvirtuals = TREE_INT_CST_LOW (TYPE_NVIRTUALS (type));
+ HOST_WIDE_INT nvirtuals = tree_low_cst (TYPE_NVIRTUALS (type), 0);
vtable = make_tree_vec (nvirtuals);
TYPE_VTABLE (type) = vtable;
if (super != NULL_TREE)
{
tree super_vtable = get_dispatch_vector (super);
- for ( i = TREE_INT_CST_LOW (TYPE_NVIRTUALS (super)); --i >= 0; )
+
+ for (i = tree_low_cst (TYPE_NVIRTUALS (super), 0); --i >= 0; )
TREE_VEC_ELT (vtable, i) = TREE_VEC_ELT (super_vtable, i);
}
+
for (method = TYPE_METHODS (type); method != NULL_TREE;
method = TREE_CHAIN (method))
- {
- if (DECL_VINDEX (method) != NULL_TREE
- && TREE_CODE (DECL_VINDEX (method)) == INTEGER_CST)
- {
- TREE_VEC_ELT (vtable, TREE_INT_CST_LOW (DECL_VINDEX (method)))
- = method;
- }
- }
+ if (DECL_VINDEX (method) != NULL_TREE
+ && host_integerp (DECL_VINDEX (method), 0))
+ TREE_VEC_ELT (vtable, tree_low_cst (DECL_VINDEX (method), 0))
+ = method;
}
+
return vtable;
}
-tree
+static tree
get_dispatch_table (type, this_class_addr)
tree type, this_class_addr;
{
build1 (ADDR_EXPR, nativecode_ptr_type_node, method),
list);
}
- /* Dummy entry for compatibility with G++ -fvtable-thunks. */
- list = tree_cons (integer_zero_node, null_pointer_node, list);
+ /* Dummy entry for compatibility with G++ -fvtable-thunks. When
+ using the Boehm GC we sometimes stash a GC type descriptor
+ there. */
+ list = tree_cons (integer_zero_node, get_boehm_type_descriptor (type),
+ list);
list = tree_cons (integer_zero_node, this_class_addr, list);
return build (CONSTRUCTOR, build_prim_array_type (nativecode_ptr_type_node,
nvirtuals + 2),
tree init = make_field_value (field);
if (FIELD_STATIC (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. */
+ if (initial != NULL_TREE
+ && TREE_TYPE (initial) == string_ptr_type_node)
+ DECL_INITIAL (field) = NULL_TREE;
rest_of_decl_compilation (field, (char*) 0, 1, 1);
+ DECL_INITIAL (field) = initial;
}
else
{
for (method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (type));
method != NULL_TREE; method = TREE_CHAIN (method))
{
- tree init = make_method_value (method, this_class_addr);
+ tree init;
+ if (METHOD_PRIVATE (method)
+ && ! flag_keep_inline_functions
+ && (flag_inline_functions || optimize))
+ continue;
+ init = make_method_value (method);
method_count++;
methods = tree_cons (NULL_TREE, init, methods);
}
DECL_IGNORED_P (methods_decl) = 1;
rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0);
- if (flag_assume_compiled
+ if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
&& ! CLASS_ABSTRACT (type_decl) && ! CLASS_INTERFACE (type_decl))
{
tree dtable = get_dispatch_table (type, this_class_addr);
super = CLASSTYPE_SUPER (type);
if (super == NULL_TREE)
super = null_pointer_node;
- else if (flag_assume_compiled)
+ else if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))))
super = build_class_ref (super);
else
{
int super_index = alloc_class_constant (super);
super = build_int_2 (super_index, 0);
- TREE_TYPE (super) == ptr_type_node;
+ TREE_TYPE (super) = ptr_type_node;
}
/* Build and emit the array of implemented interfaces. */
tree child = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);
tree iclass = BINFO_TYPE (child);
tree index;
- if (flag_assume_compiled)
+ if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (iclass)))))
index = build_class_ref (iclass);
else
{
int int_index = alloc_class_constant (iclass);
index = build_int_2 (int_index, 0);
- TREE_TYPE (index) == ptr_type_node;
+ TREE_TYPE (index) = ptr_type_node;
}
init = tree_cons (NULL_TREE, index, init);
}
constant_pool_constructor = build_constants_constructor ();
START_RECORD_CONSTRUCTOR (temp, object_type_node);
-#if 0
- PUSH_FIELD_VALUE (temp, "dtable", NULL_TREE);
-#else
- PUSH_FIELD_VALUE (temp, "dtable",
+ PUSH_FIELD_VALUE (temp, "vtable",
build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl));
-#endif
- PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
+ if (! flag_hash_synchronization)
+ PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
FINISH_RECORD_CONSTRUCTOR (temp);
START_RECORD_CONSTRUCTOR (cons, class_type_node);
PUSH_SUPER_VALUE (cons, temp);
PUSH_FIELD_VALUE (cons, "next", null_pointer_node);
- PUSH_FIELD_VALUE (cons, "name",
- build_utf8_ref (build_internal_class_name (type)));
+ PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl)));
PUSH_FIELD_VALUE (cons, "accflags",
build_int_2 (get_access_flags_from_decl (type_decl), 0));
- PUSH_FIELD_VALUE (cons, "superclass", super);
+ PUSH_FIELD_VALUE (cons, "superclass",
+ CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor);
PUSH_FIELD_VALUE (cons, "methods",
build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0));
- PUSH_FIELD_VALUE (cons, "dtable_method_count", TYPE_NVIRTUALS (type));
+ PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
PUSH_FIELD_VALUE (cons, "fields",
fields_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0));
PUSH_FIELD_VALUE (cons, "static_field_count",
build_int_2 (static_field_count, 0));
- /* For now, we let Kaffe fill in the dtable. */
- PUSH_FIELD_VALUE (cons, "dtable",
+ PUSH_FIELD_VALUE (cons, "vtable",
dtable_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
PUSH_FIELD_VALUE (cons, "thread", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
+ PUSH_FIELD_VALUE (cons, "ancestors", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
FINISH_RECORD_CONSTRUCTOR (cons);
rest_of_decl_compilation (decl, (char*) 0, 1, 0);
}
+void
+finish_class ()
+{
+ tree method;
+ tree type_methods = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
+ int saw_native_method = 0;
+
+ /* Find out if we have any native methods. We use this information
+ later. */
+ for (method = type_methods;
+ method != NULL_TREE;
+ method = TREE_CHAIN (method))
+ {
+ if (METHOD_NATIVE (method))
+ {
+ saw_native_method = 1;
+ break;
+ }
+ }
+
+ /* Emit deferred inline methods. */
+ for (method = type_methods; method != NULL_TREE; )
+ {
+ if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0)
+ {
+ /* It's a deferred inline method. Decide if we need to emit it. */
+ if (flag_keep_inline_functions
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method))
+ || ! METHOD_PRIVATE (method)
+ || saw_native_method)
+ {
+ temporary_allocation ();
+ output_inline_function (method);
+ permanent_allocation (1);
+ /* Scan the list again to see if there are any earlier
+ methods to emit. */
+ method = type_methods;
+ continue;
+ }
+ }
+ method = TREE_CHAIN (method);
+ }
+
+ current_function_decl = NULL_TREE;
+ make_class_data (current_class);
+ register_class ();
+ rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0);
+}
+
/* Return 2 if CLASS is compiled by this compilation job;
return 1 if CLASS can otherwise be assumed to be compiled;
return 0 if we cannot assume that CLASS is compiled.
if (class == current_class)
return 2;
- seen_in_zip = (TYPE_LANG_SPECIFIC (class) && TYPE_LANG_SPECIFIC (class)->jcf
- && TYPE_LANG_SPECIFIC (class)->jcf->seen_in_zip);
+ seen_in_zip = (TYPE_JCF (class) && TYPE_JCF (class)->seen_in_zip);
if (CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (class) || seen_in_zip)
{
/* The class was seen in the current ZIP file and will be
return 2;
}
- if (flag_assume_compiled)
+ if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class)))))
{
if (!CLASS_LOADED_P (class))
{
/* Append the mangled name of TYPE onto OBSTACK. */
-void
+static void
append_gpp_mangled_type (obstack, type)
struct obstack *obstack;
tree type;
}
else
{
- char *class_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ const char *class_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
append_gpp_mangled_classtype (obstack, class_name);
}
break;
/* Build the mangled (assembly-level) name of the static field FIELD. */
-tree
+static tree
mangle_static_field (field)
tree field;
{
tree this_class, super_class;
{
tree base_decl;
+ /* Don't insert the field if we're just re-laying the class out. */
+ if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class)))
+ return;
push_obstacks (&permanent_obstack, &permanent_obstack);
base_decl = build_decl (FIELD_DECL, NULL_TREE, super_class);
pop_obstacks ();
TREE_CHAIN (base_decl) = TYPE_FIELDS (this_class);
TYPE_FIELDS (this_class) = base_decl;
DECL_SIZE (base_decl) = TYPE_SIZE (super_class);
+ DECL_SIZE_UNIT (base_decl) = TYPE_SIZE_UNIT (super_class);
+}
+
+/* Handle the different manners we may have to lay out a super class. */
+
+static tree
+maybe_layout_super_class (super_class, this_class)
+ tree super_class;
+ tree this_class;
+{
+ if (TREE_CODE (super_class) == RECORD_TYPE)
+ {
+ if (!CLASS_LOADED_P (super_class)
+ && CLASS_FROM_SOURCE_P (super_class))
+ safe_layout_class (super_class);
+ if (!CLASS_LOADED_P (super_class))
+ load_class (super_class, 1);
+ }
+ /* We might have to layout the class before its dependency on
+ the super class gets resolved by java_complete_class */
+ else if (TREE_CODE (super_class) == POINTER_TYPE)
+ {
+ if (TREE_TYPE (super_class) != NULL_TREE)
+ super_class = TREE_TYPE (super_class);
+ else
+ {
+ super_class = do_resolve_class (NULL_TREE, /* FIXME? */
+ super_class, NULL_TREE, this_class);
+ if (!super_class)
+ return NULL_TREE; /* FIXME, NULL_TREE not checked by caller. */
+ super_class = TREE_TYPE (super_class);
+ }
+ }
+ if (!TYPE_SIZE (super_class))
+ safe_layout_class (super_class);
+
+ return super_class;
}
void
layout_class (this_class)
tree this_class;
{
+ static tree list = NULL_TREE;
tree super_class = CLASSTYPE_SUPER (this_class);
- tree handle_type = CLASS_TO_HANDLE_TYPE (this_class);
- tree method_decl, field;
- tree dtable_count;
- int i;
+ tree field;
+
+ list = tree_cons (this_class, NULL_TREE, list);
+ if (CLASS_BEING_LAIDOUT (this_class))
+ {
+ char buffer [1024];
+ tree current;
+
+ sprintf (buffer, " with `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
+ obstack_grow (&temporary_obstack, buffer, strlen (buffer));
+
+ for (current = TREE_CHAIN (list); current;
+ current = TREE_CHAIN (current))
+ {
+ tree decl = TYPE_NAME (TREE_PURPOSE (current));
+ sprintf (buffer, "\n which inherits from `%s' (%s:%d)",
+ IDENTIFIER_POINTER (DECL_NAME (decl)),
+ DECL_SOURCE_FILE (decl),
+ DECL_SOURCE_LINE (decl));
+ obstack_grow (&temporary_obstack, buffer, strlen (buffer));
+ }
+ obstack_1grow (&temporary_obstack, '\0');
+ cyclic_inheritance_report = obstack_finish (&temporary_obstack);
+ TYPE_SIZE (this_class) = error_mark_node;
+ return;
+ }
+ CLASS_BEING_LAIDOUT (this_class) = 1;
if (super_class)
{
- /* Class seen in source are now complete and can be layed out.
- Once layed out, a class seen in the source has its
- CLASS_LOADED_P flag set */
- if (CLASS_FROM_SOURCE_P (super_class) && !CLASS_LOADED_P (super_class))
- safe_layout_class (super_class);
- if (! CLASS_LOADED_P (super_class))
- load_class (super_class, 1);
+ super_class = maybe_layout_super_class (super_class, this_class);
if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
{
TYPE_SIZE (this_class) = error_mark_node;
+ CLASS_BEING_LAIDOUT (this_class) = 0;
+ list = TREE_CHAIN (list);
return;
}
- dtable_count = TYPE_NVIRTUALS (super_class);
-
if (TYPE_SIZE (this_class) == NULL_TREE)
push_super_field (this_class, super_class);
}
- else
- {
- dtable_count = integer_zero_node;
- }
for (field = TYPE_FIELDS (this_class);
field != NULL_TREE; field = TREE_CHAIN (field))
layout_type (this_class);
+ /* Convert the size back to an SI integer value */
+ TYPE_SIZE_UNIT (this_class) =
+ fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class)));
+
+ CLASS_BEING_LAIDOUT (this_class) = 0;
+ list = TREE_CHAIN (list);
+}
+
+void
+layout_class_methods (this_class)
+ tree this_class;
+{
+ tree method_decl, dtable_count;
+ tree super_class, handle_type;
+
+ if (TYPE_NVIRTUALS (this_class))
+ return;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ super_class = CLASSTYPE_SUPER (this_class);
+ handle_type = CLASS_TO_HANDLE_TYPE (this_class);
+
+ if (super_class)
+ {
+ super_class = maybe_layout_super_class (super_class, this_class);
+ if (!TYPE_NVIRTUALS (super_class))
+ layout_class_methods (super_class);
+ dtable_count = TYPE_NVIRTUALS (super_class);
+ }
+ else
+ dtable_count = integer_zero_node;
+
TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
- for (method_decl = TYPE_METHODS (handle_type), i = 0;
- method_decl; method_decl = TREE_CHAIN (method_decl), i++)
+ for (method_decl = TYPE_METHODS (handle_type);
+ method_decl; method_decl = TREE_CHAIN (method_decl))
+ dtable_count = layout_class_method (this_class, super_class,
+ method_decl, dtable_count);
+
+ TYPE_NVIRTUALS (this_class) = dtable_count;
+
+#ifdef JAVA_USE_HANDLES
+ layout_type (handle_type);
+#endif
+ pop_obstacks ();
+}
+
+/* Lay METHOD_DECL out, returning a possibly new value of
+ DTABLE_COUNT. */
+
+tree
+layout_class_method (this_class, super_class, method_decl, dtable_count)
+ tree this_class, super_class, method_decl, dtable_count;
+{
+ const char *ptr;
+ char *asm_name;
+ tree arg, arglist, t;
+ int method_name_needs_escapes = 0;
+ tree method_name = DECL_NAME (method_decl);
+ int method_name_is_wfl =
+ (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION);
+ if (method_name_is_wfl)
+ method_name = java_get_real_method_name (method_decl);
+
+ if (!ID_INIT_P (method_name) && !ID_FINIT_P (method_name))
{
- char *ptr;
- char buf[8];
- char *asm_name;
- tree method_name = DECL_NAME (method_decl);
- int method_name_is_wfl =
- (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION);
- if (method_name_is_wfl)
- method_name = java_get_real_method_name (method_decl);
-#if 1
- /* Remove this once we no longer need old (Kaffe / JDK 1.0) mangling. */
- if (! flag_assume_compiled && METHOD_NATIVE (method_decl))
+ int encoded_len
+ = unicode_mangling_length (IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
+ if (encoded_len > 0)
{
- for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
- *ptr; )
- {
- int ch = *ptr++;
- if (ch == '.')
- ch = '_';
- obstack_1grow (&temporary_obstack, (char) ch);
- }
- obstack_1grow (&temporary_obstack, (char) '_');
- if (method_name == init_identifier_node)
- obstack_grow (&temporary_obstack, "INIT", 4);
- else
- obstack_grow (&temporary_obstack,
- IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
+ method_name_needs_escapes = 1;
+ emit_unicode_mangled_name (&temporary_obstack,
+ IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
}
else
-#endif
{
- int len; tree arg, arglist, t;
- int method_name_needs_escapes = 0;
- if (method_name != init_identifier_node
- && method_name != finit_identifier_node)
+ obstack_grow (&temporary_obstack,
+ IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
+ }
+ }
+
+ obstack_grow (&temporary_obstack, "__", 2);
+ if (ID_FINIT_P (method_name))
+ obstack_grow (&temporary_obstack, "finit", 5);
+ append_gpp_mangled_type (&temporary_obstack, this_class);
+ TREE_PUBLIC (method_decl) = 1;
+
+ t = TREE_TYPE (method_decl);
+ arglist = TYPE_ARG_TYPES (t);
+ if (TREE_CODE (t) == METHOD_TYPE)
+ arglist = TREE_CHAIN (arglist);
+ for (arg = arglist; arg != end_params_node; )
+ {
+ tree a = arglist;
+ tree argtype = TREE_VALUE (arg);
+ int tindex = 1;
+ if (TREE_CODE (argtype) == POINTER_TYPE)
+ {
+ /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
+ while (a != arg && argtype != TREE_VALUE (a))
+ a = TREE_CHAIN (a), tindex++;
+ }
+ else
+ a = arg;
+ if (a != arg)
+ {
+ char buf[12];
+ int nrepeats = 0;
+ do
{
- int encoded_len
- = unicode_mangling_length (IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
- if (encoded_len > 0)
- {
- method_name_needs_escapes = 1;
- emit_unicode_mangled_name (&temporary_obstack,
- IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
- }
- else
- {
- obstack_grow (&temporary_obstack,
- IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
- }
+ arg = TREE_CHAIN (arg); nrepeats++;
}
-
- obstack_grow (&temporary_obstack, "__", 2);
- if (method_name == finit_identifier_node)
- obstack_grow (&temporary_obstack, "finit", 5);
- append_gpp_mangled_type (&temporary_obstack, this_class);
- TREE_PUBLIC (method_decl) = 1;
-
- t = TREE_TYPE (method_decl);
- arglist = TYPE_ARG_TYPES (t);
- if (TREE_CODE (t) == METHOD_TYPE)
- arglist = TREE_CHAIN (arglist);
- for (arg = arglist; arg != NULL_TREE; )
+ while (arg != end_params_node && argtype == TREE_VALUE (arg));
+ if (nrepeats > 1)
{
- tree a = arglist;
- tree argtype = TREE_VALUE (arg);
- int tindex = 1;
- if (TREE_CODE (argtype) == POINTER_TYPE)
- {
- /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
- while (a != arg && argtype != TREE_VALUE (a))
- a = TREE_CHAIN (a), tindex++;
- }
- else
- a = arg;
- if (a != arg)
- {
- char buf[12];
- int nrepeats = 0;
- do
- {
- arg = TREE_CHAIN (arg); nrepeats++;
- }
- while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
- if (nrepeats > 1)
- {
- obstack_1grow (&temporary_obstack, 'N');
- sprintf (buf, "%d", nrepeats);
- obstack_grow (&temporary_obstack, buf, strlen (buf));
- if (nrepeats > 9)
- obstack_1grow (&temporary_obstack, '_');
- }
- else
- obstack_1grow (&temporary_obstack, 'T');
- sprintf (buf, "%d", tindex);
- obstack_grow (&temporary_obstack, buf, strlen (buf));
- if (tindex > 9)
- obstack_1grow (&temporary_obstack, '_');
- }
- else
- {
- append_gpp_mangled_type (&temporary_obstack, argtype);
- arg = TREE_CHAIN (arg);
- }
+ obstack_1grow (&temporary_obstack, 'N');
+ sprintf (buf, "%d", nrepeats);
+ obstack_grow (&temporary_obstack, buf, strlen (buf));
+ if (nrepeats > 9)
+ obstack_1grow (&temporary_obstack, '_');
}
- if (method_name_needs_escapes)
- obstack_1grow (&temporary_obstack, 'U');
+ else
+ obstack_1grow (&temporary_obstack, 'T');
+ sprintf (buf, "%d", tindex);
+ obstack_grow (&temporary_obstack, buf, strlen (buf));
+ if (tindex > 9)
+ obstack_1grow (&temporary_obstack, '_');
}
- obstack_1grow (&temporary_obstack, '\0');
- asm_name = obstack_finish (&temporary_obstack);
- DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
- if (! METHOD_ABSTRACT (method_decl))
- make_function_rtl (method_decl);
- obstack_free (&temporary_obstack, asm_name);
-
- if (method_name == init_identifier_node)
+ else
{
- char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
- for (ptr = p; *ptr; )
- {
- if (*ptr++ == '.')
- p = ptr;
- }
- if (method_name_is_wfl)
- EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p);
- else
- DECL_NAME (method_decl) = get_identifier (p);
- DECL_CONSTRUCTOR_P (method_decl) = 1;
+ append_gpp_mangled_type (&temporary_obstack, argtype);
+ arg = TREE_CHAIN (arg);
}
- else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+ }
+ if (method_name_needs_escapes)
+ obstack_1grow (&temporary_obstack, 'U');
+
+ obstack_1grow (&temporary_obstack, '\0');
+ asm_name = obstack_finish (&temporary_obstack);
+ DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
+ /* We don't generate a RTL for the method if it's abstract, or if
+ it's an interface method that isn't clinit. */
+ if (! METHOD_ABSTRACT (method_decl)
+ || (CLASS_INTERFACE (TYPE_NAME (this_class))
+ && (DECL_CLINIT_P (method_decl))))
+ make_function_rtl (method_decl);
+ obstack_free (&temporary_obstack, asm_name);
+
+ if (ID_INIT_P (method_name))
+ {
+ const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
+ for (ptr = p; *ptr; )
{
- tree method_sig = build_java_argument_signature (TREE_TYPE (method_decl));
- tree super_method = lookup_argument_method (super_class, method_name,
+ if (*ptr++ == '.')
+ p = ptr;
+ }
+ if (method_name_is_wfl)
+ EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p);
+ else
+ DECL_NAME (method_decl) = get_identifier (p);
+ DECL_CONSTRUCTOR_P (method_decl) = 1;
+ build_java_argument_signature (TREE_TYPE (method_decl));
+ }
+ else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+ {
+ tree method_sig =
+ build_java_argument_signature (TREE_TYPE (method_decl));
+ tree super_method = lookup_argument_method (super_class, method_name,
method_sig);
- if (super_method != NULL_TREE)
- {
- DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
- if (DECL_VINDEX (method_decl) == NULL_TREE)
- error_with_decl (method_decl,
- "non-static method '%s' overrides static method");
+ if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method))
+ {
+ DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
+ if (DECL_VINDEX (method_decl) == NULL_TREE
+ && !CLASS_FROM_SOURCE_P (this_class))
+ error_with_decl (method_decl,
+ "non-static method '%s' overrides static method");
#if 0
- else if (TREE_TYPE (TREE_TYPE (method_decl))
- != TREE_TYPE (TREE_TYPE (super_method)))
- {
- error_with_decl (method_decl,
- "Method `%s' redefined with different return type");
- error_with_decl (super_method,
- "Overridden decl is here");
- }
-#endif
- }
- else if (! METHOD_FINAL (method_decl)
- && ! CLASS_FINAL (TYPE_NAME (this_class)))
+ else if (TREE_TYPE (TREE_TYPE (method_decl))
+ != TREE_TYPE (TREE_TYPE (super_method)))
{
- DECL_VINDEX (method_decl) = dtable_count;
- dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
+ error_with_decl (method_decl,
+ "Method `%s' redefined with different return type");
+ error_with_decl (super_method,
+ "Overridden decl is here");
}
+#endif
+ }
+ else if (! METHOD_FINAL (method_decl)
+ && ! METHOD_PRIVATE (method_decl)
+ && ! CLASS_FINAL (TYPE_NAME (this_class))
+ && dtable_count)
+ {
+ DECL_VINDEX (method_decl) = dtable_count;
+ dtable_count = fold (build (PLUS_EXPR, integer_type_node,
+ dtable_count, integer_one_node));
}
}
- TYPE_NVIRTUALS (this_class) = dtable_count;
-#ifdef JAVA_USE_HANDLES
- layout_type (handle_type);
-#endif
+ return dtable_count;
}
static tree registered_class = NULL_TREE;
void
emit_register_classes ()
{
- tree decl = getdecls ();
-
- extern tree get_file_function_name PROTO((int));
+ extern tree get_file_function_name PARAMS ((int));
tree init_name = get_file_function_name ('I');
- tree init_type = build_function_type (void_type_node, NULL_TREE);
+ tree init_type = build_function_type (void_type_node, end_params_node);
tree init_decl;
tree t;
- start_sequence ();
init_decl = build_decl (FUNCTION_DECL, init_name, init_type);
DECL_ASSEMBLER_NAME (init_decl) = init_name;
TREE_STATIC (init_decl) = 1;
poplevel (1, 0, 1);
{
/* Force generation, even with -O3 or deeper. Gross hack. FIXME */
- extern int flag_inline_functions;
int saved_flag = flag_inline_functions;
flag_inline_functions = 0;
rest_of_compilation (init_decl);