+Tue Nov 24 17:06:38 1998 Per Bothner <bothner@cygnus.com>
+
+ * (generate_classfile): Always write class access flag with
+ ACC_SUPER set.
+
+Tue Nov 24 16:34:33 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
+
+ * class.c (maybe_layout_super_class): New function.
+ (layout_class): Reorganized. Loop on class methods dispatched into
+ a new function. Call maybe_layout_super_class.
+ (layout_class_methods, layout_class_method): New functions.
+ * expr.c (expand_java_NEW): Call layout_class_methods on loaded
+ class.
+ (expand_invoke): Likewise.
+ * java-tree.h (all_class_list): New global variable declared.
+ (layout_class_methods, layout_class_method): New function
+ prototypes.
+ (LAYOUT_SEEN_CLASS_METHODS): New macro.
+ * jcf-parse.c (all_class_list): New global variable.
+ (load_class): Extended what class_or_name can be. Use parser
+ context mechanism to save globals before calling jcf_parse.
+ (jcf_parse_source): Don't parse twice if HAS_BEEN_ALREADY_PARSED_P
+ is set on the file name.
+ (jcf_parse): Layout class methods when Object is loaded, otherwise
+ record class in all_class_list for delayed method layout.
+ (parse_class_file): Use LAYOUT_SEEN_CLASS_METHODS.
+ * lang.c (put_decl_node): Decode <init> into the decl context
+ class name.
+ * lex.c (java_allocate_new_line): Use xmalloc.
+ * parse.h (INCOMPLETE_TYPE_P): Redefined to work with incomplete
+ pointers, not TREE_LIST elements.
+ (struct parser_ctxt): Fixed comment indentations, added comments
+ and reordered some fields.
+ (java_check_methods): Function prototype removed.
+ * parse.y (java_push_parser_context): Use xmalloc.
+ (java_parser_context_restore_global): Pop extra pushed ctxp only
+ when there's nothing next.
+ (maybe_create_class_interface_decl): Fixed comment, add new
+ created class decl to all_class_list.
+ (method_header): Use GET_REAL_TYPE on argument's types.
+ (method_declarator): Use GET_REAL_TYPE, change type to the real
+ type in TREE_LIST dependency node. Build argument list with the
+ real type.
+ (create_jdep_list): Use xmalloc. Removed allocation error message.
+ (obtain_incomplete_type): Fixed leading comment. Broadened
+ incoming argument meaning.
+ (register_incomplete_type): Use xmalloc. Removed allocation error
+ message.
+ (safe_layout_class): Fixed leading comment.
+ (jdep_resolve_class): Reversed if statement condition and switch
+ if and else bodies.
+ (resolve_and_layout): Fixed leading comment. Broadened incoming
+ argument meaning.
+ (complete_class_report_errors): New local variable name, for
+ clarity. purify_type_name used for all error cases.
+ (java_get_real_method_name): Stricter check on constructors.
+ (java_check_regular_methods): Reverse methods list only if not
+ already laid out. Layout artificial constructor.
+ (java_check_methods): Deleted.
+ (source_start_java_method): Obtain incomplete type for patchable
+ method arguments.
+ (java_layout_classes): Fixed leading comment. Use
+ LAYOUT_SEEN_CLASS_METHODS, use a loop to check methods. Added else
+ statement to layout operation, reuse LAYOUT_SEEN_CLASS_METHODS
+ before returning. Fixed comments.
+ (java_expand_classes): Check for errors up front.
+ (patch_method_invocation): Class to search is resolved and laid
+ out.
+
Tue Nov 24 12:57:13 1998 Per Bothner <bothner@cygnus.com>
* expr.c (java_lang_expand_expr): Add missing emit_queue.
DECL_SIZE (base_decl) = TYPE_SIZE (super_class);
}
+/* Handle the different manners we may have to lay out a super class. */
+
+static tree
+maybe_layout_super_class (super_class)
+ tree super_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) == TREE_LIST)
+ {
+ tree name = TYPE_NAME (TREE_PURPOSE (super_class));
+ load_class (name, 1);
+ super_class = IDENTIFIER_CLASS_VALUE (name);
+ if (!super_class)
+ return;
+ 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;
{
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;
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);
if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
{
TYPE_SIZE (this_class) = error_mark_node;
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);
+}
- TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
+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);
- for (method_decl = TYPE_METHODS (handle_type), i = 0;
- method_decl; method_decl = TREE_CHAIN (method_decl), i++)
+ if (super_class)
{
- 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);
+ super_class = maybe_layout_super_class (super_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);
+ 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;
+{
+ 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))
+ /* Remove this once we no longer need old (Kaffe / JDK 1.0) mangling. */
+ if (! flag_assume_compiled && METHOD_NATIVE (method_decl))
+ {
+ 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));
+ }
+ 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)
{
- for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
- *ptr; )
+ int encoded_len
+ = unicode_mangling_length (IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
+ if (encoded_len > 0)
{
- int ch = *ptr++;
- if (ch == '.')
- ch = '_';
- obstack_1grow (&temporary_obstack, (char) ch);
+ method_name_needs_escapes = 1;
+ emit_unicode_mangled_name (&temporary_obstack,
+ IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
}
- 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));
+ {
+ obstack_grow (&temporary_obstack,
+ IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
+ }
}
- else
-#endif
+
+ 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; )
{
- int len; tree arg, arglist, t;
- int method_name_needs_escapes = 0;
- if (method_name != init_identifier_node
- && method_name != finit_identifier_node)
+ tree a = arglist;
+ tree argtype = TREE_VALUE (arg);
+ int tindex = 1;
+ if (TREE_CODE (argtype) == POINTER_TYPE)
{
- 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));
- }
+ /* 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++;
}
-
- 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; )
+ else
+ a = arg;
+ if (a != arg)
{
- tree a = arglist;
- tree argtype = TREE_VALUE (arg);
- int tindex = 1;
- if (TREE_CODE (argtype) == POINTER_TYPE)
+ char buf[12];
+ int nrepeats = 0;
+ do
{
- /* 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++;
+ arg = TREE_CHAIN (arg); nrepeats++;
}
- else
- a = arg;
- if (a != arg)
+ while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
+ if (nrepeats > 1)
{
- 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_1grow (&temporary_obstack, 'N');
+ sprintf (buf, "%d", nrepeats);
obstack_grow (&temporary_obstack, buf, strlen (buf));
- if (tindex > 9)
+ if (nrepeats > 9)
obstack_1grow (&temporary_obstack, '_');
}
else
- {
- append_gpp_mangled_type (&temporary_obstack, argtype);
- arg = TREE_CHAIN (arg);
- }
+ obstack_1grow (&temporary_obstack, 'T');
+ sprintf (buf, "%d", tindex);
+ obstack_grow (&temporary_obstack, buf, strlen (buf));
+ if (tindex > 9)
+ obstack_1grow (&temporary_obstack, '_');
}
- 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);
- if (! METHOD_ABSTRACT (method_decl))
- make_function_rtl (method_decl);
- obstack_free (&temporary_obstack, asm_name);
-
- if (method_name == init_identifier_node)
- {
- char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
- for (ptr = p; *ptr; )
+ else
{
- if (*ptr++ == '.')
- p = ptr;
+ append_gpp_mangled_type (&temporary_obstack, argtype);
+ arg = TREE_CHAIN (arg);
}
- 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;
}
- 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);
+ if (! METHOD_ABSTRACT (method_decl))
+ make_function_rtl (method_decl);
+ obstack_free (&temporary_obstack, asm_name);
+
+ if (method_name == init_identifier_node)
+ {
+ 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;
+ }
+ 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)
+ {
+ 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 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");
- }
+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)))
- {
- DECL_VINDEX (method_decl) = dtable_count;
- dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
- }
+ }
+ else if (! METHOD_FINAL (method_decl)
+ && ! CLASS_FINAL (TYPE_NAME (this_class))
+ && dtable_count)
+ {
+ DECL_VINDEX (method_decl) = dtable_count;
+ dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
}
}
- TYPE_NVIRTUALS (this_class) = dtable_count;
-
-#ifdef JAVA_USE_HANDLES
- layout_type (handle_type);
-#endif
+ return dtable_count;
}
static tree registered_class = NULL_TREE;
{
if (! CLASS_LOADED_P (type))
load_class (type, 1);
+ layout_class_methods (type);
push_value (build (CALL_EXPR, promote_type (type),
build_address_of (alloc_object_node),
tree_cons (NULL_TREE, build_class_ref (type),
if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK)
fatal ("failed to find class '%s'", self_name);
}
+ layout_class_methods (self_type);
if (method_name == init_identifier_node)
method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type),
/* The class we are currently processing. */
extern tree current_class;
+/* List of all class DECLs seen so far. */
+extern tree all_class_list;
+
/* Nonzero if we want to automatically do array bounds checking;
on by default. Use -fno-bounds-check to disable. */
extern tree parse_signature_string PROTO ((const unsigned char *, int));
extern tree get_type_from_signature PROTO ((tree));
extern void layout_class PROTO ((tree));
+extern tree layout_class_method PROTO ((tree, tree, tree, tree));
+extern void layout_class_methods PROTO ((tree));
extern tree make_class ();
extern tree build_class_ref PROTO ((tree));
extern tree build_dtable_decl PROTO ((tree));
if (java_error_count) \
return; \
}
+
+#define LAYOUT_SEEN_CLASS_METHODS() \
+ { \
+ tree current; \
+ for (current = all_class_list; current; current = TREE_CHAIN (current)) \
+ layout_class_methods (TREE_TYPE (TREE_VALUE (current))); \
+ }
/* The class we started with. */
tree main_class = NULL_TREE;
-/* The FIELD_DECL for the current field. */
+/* List of all class DECL seen so far. */
+tree all_class_list = NULL_TREE;
+
+/* The FIELD_DECL for the current field. */
static tree current_field = NULL_TREE;
/* The METHOD_DECL for the current method. */
int verbose;
{
JCF this_jcf, *jcf;
- tree name = (TREE_CODE (class_or_name) == IDENTIFIER_NODE ?
- class_or_name : DECL_NAME (TYPE_NAME (class_or_name)));
+ tree name;
tree save_current_class = current_class;
char *save_input_filename = input_filename;
JCF *save_current_jcf = current_jcf;
if (current_jcf->read_state)
saved_pos = ftell (current_jcf->read_state);
+ /* class_or_name can be the name of the class we want to load */
+ if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
+ name = class_or_name;
+ /* In some cases, it's a dependency that we process earlier that
+ we though */
+ else if (TREE_CODE (class_or_name) == TREE_LIST)
+ name = TYPE_NAME (TREE_PURPOSE (class_or_name));
+ /* Or it's a type in the making */
+ else
+ name = DECL_NAME (TYPE_NAME (class_or_name));
+
push_obstacks (&permanent_obstack, &permanent_obstack);
/* Search in current zip first. */
if (current_jcf->java_source)
jcf_parse_source (current_jcf);
else {
- int saved_lineno = lineno;
+ java_parser_context_save_global ();
+ java_push_parser_context ();
input_filename = current_jcf->filename;
jcf_parse (current_jcf);
- lineno = saved_lineno;
+ java_pop_parser_context (0);
+ java_parser_context_restore_global ();
}
if (!current_jcf->seen_in_zip)
java_push_parser_context ();
input_filename = current_jcf->filename;
file = get_identifier (input_filename);
- if (!(finput = fopen (input_filename, "r")))
- fatal ("input file `%s' just disappeared - jcf_parse_source",
- input_filename);
- parse_source_file (file);
- if (fclose (finput))
- fatal ("can't close input file `%s' stream - jcf_parse_source",
- input_filename);
+ if (!HAS_BEEN_ALREADY_PARSED_P (file))
+ {
+ if (!(finput = fopen (input_filename, "r")))
+ fatal ("input file `%s' just disappeared - jcf_parse_source",
+ input_filename);
+ parse_source_file (file);
+ if (fclose (finput))
+ fatal ("can't close input file `%s' stream - jcf_parse_source",
+ input_filename);
+ }
java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file));
java_parser_context_restore_global ();
}
push_obstacks (&permanent_obstack, &permanent_obstack);
layout_class (current_class);
+ if (current_class == object_type_node)
+ layout_class_methods (object_type_node);
+ else
+ all_class_list = tree_cons (NULL_TREE,
+ TYPE_NAME (current_class), all_class_list );
pop_obstacks ();
}
char *save_input_filename = input_filename;
int save_lineno = lineno;
+ LAYOUT_SEEN_CLASS_METHODS ();
+
input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class));
lineno = 0;
debug_start_source_file (input_filename);
else
i = 8 + 2 * total_supers;
ptr = append_chunk (NULL, i, state);
- i = get_access_flags (TYPE_NAME (clas)); PUT2 (i); /* acces_flags */
+ i = get_access_flags (TYPE_NAME (clas)) | ACC_SUPER;
+ PUT2 (i); /* acces_flags */
i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
if (clas == object_type_node)
{
put_decl_string (".", 1);
}
#endif
- put_decl_node (DECL_NAME (node));
+ if (TREE_CODE (node) == FUNCTION_DECL
+ && DECL_NAME (node) == init_identifier_node
+ && !DECL_ARTIFICIAL (node) && current_class)
+ put_decl_node (TYPE_NAME (current_class));
+ else
+ put_decl_node (DECL_NAME (node));
if (TREE_CODE (node) == FUNCTION_DECL && TREE_TYPE (node) != NULL_TREE)
{
int i = 0;
if (!ctxp->c_line)
{
- ctxp->c_line = (struct java_line *)malloc (sizeof (struct java_line));
+ ctxp->c_line = (struct java_line *)xmalloc (sizeof (struct java_line));
ctxp->c_line->max = JAVA_LINE_MAX;
- ctxp->c_line->line = (unicode_t *)malloc
- (sizeof (unicode_t)*ctxp->c_line->max);
+ ctxp->c_line->line = (unicode_t *)xmalloc
+ (sizeof (unicode_t)*ctxp->c_line->max);
ctxp->c_line->unicode_escape_p =
- (char *)malloc (sizeof (char)*ctxp->c_line->max);
+ (char *)xmalloc (sizeof (char)*ctxp->c_line->max);
ctxp->c_line->white_space_only = 0;
}
java_push_parser_context ()
{
struct parser_ctxt *new =
- (struct parser_ctxt *)malloc(sizeof (struct parser_ctxt));
+ (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
bzero (new, sizeof (struct parser_ctxt));
new->next = ctxp;
current_class = ctxp->current_class;
input_filename = ctxp->filename;
current_function_decl = ctxp->current_function_decl;
- if (extra_ctxp_pushed_p)
+ if (!ctxp->next && extra_ctxp_pushed_p)
{
java_pop_parser_context (0);
extra_ctxp_pushed_p = 0;
TREE_CHAIN (decl) = ctxp->class_list;
ctxp->class_list = decl;
- /* Create a new node in the global list */
+ /* Create a new nodes in the global lists */
ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
+ all_class_list = tree_cons (NULL_TREE, decl, all_class_list);
/* Install a new dependency list element */
create_jdep_list (ctxp);
super_decl_type = TREE_TYPE (super_decl);
}
else
- super_decl_type =
+ super_decl_type =
register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE);
}
else if (TREE_TYPE (decl) != object_type_node)
tree itype;
patch_stage = JDEP_METHOD_RETURN;
itype = register_incomplete_type (patch_stage, type, id, NULL_TREE);
- TREE_TYPE (meth) = (TREE_CODE (itype) == TREE_LIST ?
- TREE_PURPOSE (itype) : itype);
+ TREE_TYPE (meth) = GET_REAL_TYPE (itype);
}
}
else
tree name = EXPR_WFL_NODE (wfl_name);
tree already, arg_node;
tree type_wfl = NULL_TREE;
+ tree real_type;
/* Obtain a suitable type for resolution, if necessary */
SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain);
type = build_array_from_name (type, type_wfl, name, &name);
EXPR_WFL_NODE (wfl_name) = name;
- if (TREE_CODE (type) == RECORD_TYPE)
- type = promote_type (type);
+ real_type = GET_REAL_TYPE (type);
+ if (TREE_CODE (real_type) == RECORD_TYPE)
+ {
+ real_type = promote_type (real_type);
+ if (TREE_CODE (type) == TREE_LIST)
+ TREE_PURPOSE (type) = real_type;
+ }
/* Check redefinition */
for (already = arg_types; already; already = TREE_CHAIN (already))
}
/* The argument node: a name and a (possibly) incomplete type */
- arg_node = build_tree_list (name, type);
+ arg_node = build_tree_list (name, real_type);
if (jdep)
JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node);
TREE_CHAIN (arg_node) = arg_types;
create_jdep_list (ctxp)
struct parser_ctxt *ctxp;
{
- jdeplist *new = malloc (sizeof (jdeplist));
-
- if (!new)
- fatal ("Can't alloc jdeplist - create_jdep_list");
-
+ jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist));
new->first = new->last = NULL;
new->next = ctxp->classd_list;
ctxp->classd_list = new;
return prev;
}
-/* Create a fake pointer based on the ID stored in the WFL */
+/* Create a fake pointer based on the ID stored in
+ TYPE_NAME. TYPE_NAME can be a WFL or a incomplete type asking to be
+ registered again. */
static tree
-obtain_incomplete_type (wfl)
- tree wfl;
+obtain_incomplete_type (type_name)
+ tree type_name;
{
- tree ptr;
- tree name = EXPR_WFL_NODE (wfl);
+ tree ptr, name;
+
+ if (TREE_CODE (type_name) == EXPR_WITH_FILE_LOCATION)
+ name = EXPR_WFL_NODE (type_name);
+ else if (INCOMPLETE_TYPE_P (type_name))
+ name = TYPE_NAME (type_name);
+ else
+ fatal ("invalid type name - obtain_incomplete_type");
for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
int kind;
tree wfl, decl, ptr;
{
- jdep *new = malloc (sizeof (jdep));
+ jdep *new = (jdep *)xmalloc (sizeof (jdep));
- if (!new)
- fatal ("Can't allocate new jdep - register_incomplete_type");
if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */
ptr = obtain_incomplete_type (wfl);
}
}
+/* safe_layout_class just makes sure that we can load a class without
+ disrupting the current_class, input_file, lineno, etc, information
+ about the class processed currently. */
+
void
safe_layout_class (class)
tree class;
{
tree decl;
- if (!JDEP_RESOLVED_P (dep))
+ if (JDEP_RESOLVED_P (dep))
+ decl = JDEP_RESOLVED_DECL (dep);
+ else
{
- decl =
- resolve_class (JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep));
+ decl = resolve_class (JDEP_TO_RESOLVE (dep),
+ JDEP_DECL (dep), JDEP_WFL (dep));
JDEP_RESOLVED (dep, decl);
}
- else
- decl = JDEP_RESOLVED_DECL (dep);
-
+
if (!decl)
- {
- complete_class_report_errors (dep);
- return NULL_TREE;
- }
+ complete_class_report_errors (dep);
+
return decl;
}
}
/* Resolve NAME and lay it out (if not done and if not the current
- parsed class). Return a decl node. */
+ parsed class). Return a decl node. This function is meant to be
+ called when type resolution is necessary during the walk pass. */
static tree
resolve_and_layout (something, cl)
{
tree decl;
- if (TREE_CODE (something) == POINTER_TYPE)
- something = TREE_TYPE (something);
+ /* Don't do that on the current class */
+ if (something == current_class)
+ return TYPE_NAME (current_class);
+ /* Don't do anything for void and other primitive types */
if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
return NULL_TREE;
+ /* Pointer types can be reall pointer types or fake pointers. When
+ finding a real pointer, recheck for primitive types */
+ if (TREE_CODE (something) == POINTER_TYPE)
+ {
+ if (TREE_TYPE (something))
+ {
+ something = TREE_TYPE (something);
+ if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
+ return NULL_TREE;
+ }
+ else
+ something = TYPE_NAME (something);
+ }
+
+ /* Don't do anything for arrays of primitive types */
+ if (TREE_CODE (something) == RECORD_TYPE && TYPE_ARRAY_P (something)
+ && JPRIMITIVE_TYPE_P (TYPE_ARRAY_ELEMENT (something)))
+ return NULL_TREE;
+
+ /* If something is not and IDENTIFIER_NODE, it can be a a TYPE_DECL
+ or a real TYPE */
if (TREE_CODE (something) != IDENTIFIER_NODE)
something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
- decl = resolve_no_layout (something, cl);
- if (decl && TREE_TYPE (decl) != current_class
- && !CLASS_LOADED_P (TREE_TYPE (decl)))
+ if (!(decl = resolve_no_layout (something, cl)))
+ return NULL_TREE;
+
+ /* Resolve and layout if necessary */
+ layout_class_methods (TREE_TYPE (decl));
+ if (CLASS_FROM_SOURCE_P (TREE_TYPE (decl)))
+ CHECK_METHODS (decl);
+ if (TREE_TYPE (decl) != current_class && !CLASS_LOADED_P (TREE_TYPE (decl)))
safe_layout_class (TREE_TYPE (decl));
+
return decl;
}
return decl;
}
-/* Called to report errors. Skip leader '[' in a complex array type
- description that failed to be resolved. */
+/* Called when reporting errors. Skip leader '[' in a complex array
+ type description that failed to be resolved. Append a matching
+ number of [] at the end of a newly allocated string that contains
+ the type's name part. */
static char *
purify_type_name (name)
{
while (*name && *name == '[')
name++;
+
return name;
}
complete_class_report_errors (dep)
jdep *dep;
{
+ char *name;
+
+ if (!JDEP_WFL (dep))
+ return;
+
+ name = IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)));
switch (JDEP_KIND (dep))
{
case JDEP_SUPER:
parse_error_context
(JDEP_WFL (dep), "Superclass `%s' of class `%s' not found",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break;
case JDEP_FIELD:
parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in declaration of field `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break;
case JDEP_METHOD: /* Covers arguments */
parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"argument `%s' of method `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep))));
break;
parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"return type of method `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))));
break;
case JDEP_INTERFACE:
tree method_name = DECL_NAME (method_decl);
if (DECL_CONSTRUCTOR_P (method_decl))
return init_identifier_node;
- else if (ctxp
- && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name))
+ /* Don't confuse method only bearing the name of their class as
+ constructors */
+ else if (ctxp && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name)
+ && get_access_flags_from_decl (method_decl) <= ACC_PROTECTED
+ && TREE_TYPE (TREE_TYPE (method_decl)) == void_type_node)
return init_identifier_node;
else
return EXPR_WFL_NODE (method_name);
if (class == object_type_node)
return;
- TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+ if (!TYPE_NVIRTUALS (class))
+ TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
/* Should take interfaces into account. FIXME */
for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
DECL_NAME (found) = saved_found_wfl;
- TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+ if (!TYPE_NVIRTUALS (class))
+ TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
if (!saw_constructor)
{
- /* No constructor seen, we craft one, at line 0 */
+ /* No constructor seen, we craft one, at line 0. Since this
+ operation takes place after we laid methods out
+ (layout_class_methods), we prepare the its DECL
+ appropriately. */
int flags;
tree decl;
decl = create_artificial_method (class, flags, void_type_node,
init_identifier_node, NULL_TREE);
DECL_CONSTRUCTOR_P (decl) = 1;
+ layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
}
}
}
}
-/* Check the method on all the defined classes. Process all the
- classes that we compiled from source code for this CU. */
-
-void
-java_check_methods ()
-{
- tree current;
- for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
- if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
- CHECK_METHODS (TREE_VALUE (current));
-}
-
/* Lookup methods in interfaces using their name and partial
signature. Return a matching method only if their types differ. */
tree type = TREE_VALUE (tem);
tree name = TREE_PURPOSE (tem);
- /* If type is incomplete. Layout can't take place
- now. Create an incomplete decl and ask for the decl to be
- patched later */
+ /* If type is incomplete. Create an incomplete decl and ask for
+ the decl to be patched later */
if (INCOMPLETE_TYPE_P (type))
{
jdep *jdep;
tree real_type = GET_REAL_TYPE (type);
parm_decl = build_decl (PARM_DECL, name, real_type);
+ type = obtain_incomplete_type (type);
register_incomplete_type (JDEP_PARM, NULL_TREE, NULL_TREE, type);
jdep = CLASSD_LAST (ctxp->classd_list);
JDEP_MISC (jdep) = name;
/* Hold THIS for the scope of the current public method decl. */
static tree current_this;
-/* Layout all class found during parsing. Also fixes the order of some
- lists. */
+/* Layout the methods of all classes loaded in one way on an
+ other. Check methods of source parsed classes. Then reorder the
+ fields and layout the classes or the type of all source parsed
+ classes */
void
java_layout_classes ()
{
tree current;
- java_check_methods ();
- /* Error reported by the caller */
- if (java_error_count)
- return;
+ /* Layout the methods of all classes seen so far */
+ LAYOUT_SEEN_CLASS_METHODS ();
+ java_parse_abort_on_error ();
+ all_class_list = NULL_TREE;
+
+ /* Then check the methods of all parsed classes */
+ for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+ if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
+ CHECK_METHODS (TREE_VALUE (current));
+ java_parse_abort_on_error ();
+
for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (TREE_VALUE (current));
if (TYPE_FIELDS (current_class) && current_class != object_type_node
&& current_class != class_type_node)
{
- /* Always leave the dummy field in front if its already there,
- and layout the class for proper field offets. */
+ /* If the dummy field is there, reverse the right fields and
+ just layout the type for proper fields offset */
if (!DECL_NAME (TYPE_FIELDS (current_class)))
{
tree fields = TYPE_FIELDS (current_class);
TYPE_SIZE (current_class) = NULL_TREE;
layout_type (current_class);
}
- /* It's time to layout the class */
+ /* We don't have a dummy field, we need to layout the class,
+ after having reversed the fields */
else
{
TYPE_FIELDS (current_class) =
layout_class (current_class);
}
}
-
- /* Do a layout if necessary */
- if (!TYPE_SIZE (current_class)
- || (current_class == object_type_node)
- || current_class == class_type_node)
- safe_layout_class (current_class);
+ else
+ layout_class (current_class);
/* From now on, the class is considered completely loaded */
CLASS_LOADED_P (current_class) = 1;
if (java_error_count)
return;
}
+
+ /* We might have reloaded classes durign the process of laying out
+ classes for code generation. We must layout the methods of those
+ late additions, as constructor checks might use them */
+ LAYOUT_SEEN_CLASS_METHODS ();
+ java_parse_abort_on_error ();
}
/* Expand all methods in all registered classes. */
void
java_expand_classes ()
{
- ctxp = ctxp_for_generation;
- /* If we found error earlier, we don't want to report then twice. */
- if (java_error_count || !ctxp)
+ java_parse_abort_on_error ();
+ if (!(ctxp = ctxp_for_generation))
return;
java_layout_classes ();
java_parse_abort_on_error ();
/* Class to search is NULL if we're searching the current one */
if (class_to_search)
{
- class_to_search = resolve_no_layout (class_to_search, NULL_TREE);
+ class_to_search = resolve_and_layout (class_to_search,
+ NULL_TREE);
if (!class_to_search)
{
parse_error_context
TREE_OPERAND (node, 0) = cn;
TREE_TYPE (node) = void_type_node;
CAN_COMPLETE_NORMALLY (node) = 1;
+ TREE_SIDE_EFFECTS (node) = 1;
break;
case DEFAULT_EXPR:
else
SWITCH_HAS_DEFAULT (nn) = 1;
TREE_TYPE (node) = void_type_node;
+ TREE_SIDE_EFFECTS (node) = 1;
CAN_COMPLETE_NORMALLY (node) = 1;
break;
TYPE_NAME (ptr) = name; \
}
-#define INCOMPLETE_TYPE_P(NODE) \
- ((TREE_CODE (NODE) == TREE_LIST) \
- && (TREE_CODE (TREE_PURPOSE (NODE)) == POINTER_TYPE) \
- && (TREE_TYPE (TREE_PURPOSE (NODE)) == NULL_TREE))
+#define INCOMPLETE_TYPE_P(NODE) \
+ ((TREE_CODE (NODE) == POINTER_TYPE) \
+ && !TREE_TYPE (NODE) \
+ && TREE_CODE (TYPE_NAME (NODE)) == IDENTIFIER_NODE)
/* Set the EMIT_LINE_NOTE flag of a EXPR_WLF to 1 if debug information
are requested. Works in the context of a parser rule. */
int parser_ccb_indent; /* Keep track of {} indent, parser */
int osb_number; /* Keep track of ['s */
int minus_seen; /* Integral literal overflow */
- int lineno; /* Current lineno */
- int java_error_flag; /* Report error when true */
+ int lineno; /* Current lineno */
+ int java_error_flag; /* Report error when true */
int deprecated; /* @deprecated tag seen */
/* This section is defined only if we compile jc1 */
#ifndef JC1_LITE
- tree modifier_ctx [11]; /* WFL of modifiers */
+ tree modifier_ctx [11]; /* WFL of modifiers */
tree current_class; /* Current class */
tree current_function_decl; /* Current function decl, save/restore */
tree package; /* Defined package ID */
+ /* Those tow list are saved accross file traversal */
tree incomplete_class; /* List of non-complete classes */
- tree current_parsed_class; /* Class currently parsed */
- tree current_parsed_class_un; /* Curr. parsed class unqualified name */
+ tree gclass_list; /* All classes seen from source code */
+
+ /* These two lists won't survive file traversal */
tree class_list; /* List of classes in a CU */
- tree gclass_list; /* All classes seen so far. */
jdeplist *classd_list; /* Classe dependencies in a CU */
+ tree current_parsed_class; /* Class currently parsed */
+ tree current_parsed_class_un; /* Curr. parsed class unqualified name */
+
tree non_static_initialized; /* List of non static initialized fields */
tree static_initialized; /* List of static non final initialized */
tree import_list; /* List of import */
tree import_demand_list; /* List of import on demand */
- tree current_loop; /* List of the currently nested loops/switches */
- tree current_labeled_block; /* List of currently nested
- labeled blocks. */
+ tree current_loop; /* List of the currently nested
+ loops/switches */
+ tree current_labeled_block; /* List of currently nested
+ labeled blocks. */
- int pending_block; /* Pending block to close */
+ int pending_block; /* Pending block to close */
- int explicit_constructor_p; /* True when processing an
- explicit constructor. This flag is
- used to trap illegal argument usage
- during an explicit constructor
- invocation. */
+ int explicit_constructor_p; /* True when processing an explicit
+ constructor. This flag is used to trap
+ illegal argument usage during an
+ explicit constructor invocation. */
#endif /* JC1_LITE */
};
void java_complete_class PROTO ((void));
void java_check_circular_reference PROTO ((void));
void java_check_final PROTO ((void));
-void java_check_methods PROTO ((void));
void java_layout_classes PROTO ((void));
tree java_method_add_stmt PROTO ((tree, tree));
char *java_get_line_col PROTO ((char *, int, int));
java_push_parser_context ()
{
struct parser_ctxt *new =
- (struct parser_ctxt *)malloc(sizeof (struct parser_ctxt));
+ (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
bzero (new, sizeof (struct parser_ctxt));
new->next = ctxp;
current_class = ctxp->current_class;
input_filename = ctxp->filename;
current_function_decl = ctxp->current_function_decl;
- if (extra_ctxp_pushed_p)
+ if (!ctxp->next && extra_ctxp_pushed_p)
{
java_pop_parser_context (0);
extra_ctxp_pushed_p = 0;
TREE_CHAIN (decl) = ctxp->class_list;
ctxp->class_list = decl;
- /* Create a new node in the global list */
+ /* Create a new nodes in the global lists */
ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
+ all_class_list = tree_cons (NULL_TREE, decl, all_class_list);
/* Install a new dependency list element */
create_jdep_list (ctxp);
tree itype;
patch_stage = JDEP_METHOD_RETURN;
itype = register_incomplete_type (patch_stage, type, id, NULL_TREE);
- TREE_TYPE (meth) = (TREE_CODE (itype) == TREE_LIST ?
- TREE_PURPOSE (itype) : itype);
+ TREE_TYPE (meth) = GET_REAL_TYPE (itype);
}
}
else
tree name = EXPR_WFL_NODE (wfl_name);
tree already, arg_node;
tree type_wfl = NULL_TREE;
+ tree real_type;
/* Obtain a suitable type for resolution, if necessary */
SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain);
type = build_array_from_name (type, type_wfl, name, &name);
EXPR_WFL_NODE (wfl_name) = name;
- if (TREE_CODE (type) == RECORD_TYPE)
- type = promote_type (type);
+ real_type = GET_REAL_TYPE (type);
+ if (TREE_CODE (real_type) == RECORD_TYPE)
+ {
+ real_type = promote_type (real_type);
+ if (TREE_CODE (type) == TREE_LIST)
+ TREE_PURPOSE (type) = real_type;
+ }
/* Check redefinition */
for (already = arg_types; already; already = TREE_CHAIN (already))
}
/* The argument node: a name and a (possibly) incomplete type */
- arg_node = build_tree_list (name, type);
+ arg_node = build_tree_list (name, real_type);
if (jdep)
JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node);
TREE_CHAIN (arg_node) = arg_types;
create_jdep_list (ctxp)
struct parser_ctxt *ctxp;
{
- jdeplist *new = malloc (sizeof (jdeplist));
-
- if (!new)
- fatal ("Can't alloc jdeplist - create_jdep_list");
-
+ jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist));
new->first = new->last = NULL;
new->next = ctxp->classd_list;
ctxp->classd_list = new;
return prev;
}
-/* Create a fake pointer based on the ID stored in the WFL */
+/* Create a fake pointer based on the ID stored in
+ TYPE_NAME. TYPE_NAME can be a WFL or a incomplete type asking to be
+ registered again. */
static tree
-obtain_incomplete_type (wfl)
- tree wfl;
+obtain_incomplete_type (type_name)
+ tree type_name;
{
- tree ptr;
- tree name = EXPR_WFL_NODE (wfl);
+ tree ptr, name;
+
+ if (TREE_CODE (type_name) == EXPR_WITH_FILE_LOCATION)
+ name = EXPR_WFL_NODE (type_name);
+ else if (INCOMPLETE_TYPE_P (type_name))
+ name = TYPE_NAME (type_name);
+ else
+ fatal ("invalid type name - obtain_incomplete_type");
for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
int kind;
tree wfl, decl, ptr;
{
- jdep *new = malloc (sizeof (jdep));
+ jdep *new = (jdep *)xmalloc (sizeof (jdep));
- if (!new)
- fatal ("Can't allocate new jdep - register_incomplete_type");
if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */
ptr = obtain_incomplete_type (wfl);
}
}
+/* safe_layout_class just makes sure that we can load a class without
+ disrupting the current_class, input_file, lineno, etc, information
+ about the class processed currently. */
+
void
safe_layout_class (class)
tree class;
{
tree decl;
- if (!JDEP_RESOLVED_P (dep))
+ if (JDEP_RESOLVED_P (dep))
+ decl = JDEP_RESOLVED_DECL (dep);
+ else
{
- decl =
- resolve_class (JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep));
+ decl = resolve_class (JDEP_TO_RESOLVE (dep),
+ JDEP_DECL (dep), JDEP_WFL (dep));
JDEP_RESOLVED (dep, decl);
}
- else
- decl = JDEP_RESOLVED_DECL (dep);
-
+
if (!decl)
- {
- complete_class_report_errors (dep);
- return NULL_TREE;
- }
+ complete_class_report_errors (dep);
+
return decl;
}
}
/* Resolve NAME and lay it out (if not done and if not the current
- parsed class). Return a decl node. */
+ parsed class). Return a decl node. This function is meant to be
+ called when type resolution is necessary during the walk pass. */
static tree
resolve_and_layout (something, cl)
{
tree decl;
- if (TREE_CODE (something) == POINTER_TYPE)
- something = TREE_TYPE (something);
+ /* Don't do that on the current class */
+ if (something == current_class)
+ return TYPE_NAME (current_class);
+ /* Don't do anything for void and other primitive types */
if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
return NULL_TREE;
+ /* Pointer types can be reall pointer types or fake pointers. When
+ finding a real pointer, recheck for primitive types */
+ if (TREE_CODE (something) == POINTER_TYPE)
+ {
+ if (TREE_TYPE (something))
+ {
+ something = TREE_TYPE (something);
+ if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
+ return NULL_TREE;
+ }
+ else
+ something = TYPE_NAME (something);
+ }
+
+ /* Don't do anything for arrays of primitive types */
+ if (TREE_CODE (something) == RECORD_TYPE && TYPE_ARRAY_P (something)
+ && JPRIMITIVE_TYPE_P (TYPE_ARRAY_ELEMENT (something)))
+ return NULL_TREE;
+
+ /* If something is not and IDENTIFIER_NODE, it can be a a TYPE_DECL
+ or a real TYPE */
if (TREE_CODE (something) != IDENTIFIER_NODE)
something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
- decl = resolve_no_layout (something, cl);
- if (decl && TREE_TYPE (decl) != current_class
- && !CLASS_LOADED_P (TREE_TYPE (decl)))
+ if (!(decl = resolve_no_layout (something, cl)))
+ return NULL_TREE;
+
+ /* Resolve and layout if necessary */
+ layout_class_methods (TREE_TYPE (decl));
+ if (CLASS_FROM_SOURCE_P (TREE_TYPE (decl)))
+ CHECK_METHODS (decl);
+ if (TREE_TYPE (decl) != current_class && !CLASS_LOADED_P (TREE_TYPE (decl)))
safe_layout_class (TREE_TYPE (decl));
+
return decl;
}
return decl;
}
-/* Called to report errors. Skip leader '[' in a complex array type
- description that failed to be resolved. */
+/* Called when reporting errors. Skip leader '[' in a complex array
+ type description that failed to be resolved. */
static char *
purify_type_name (name)
complete_class_report_errors (dep)
jdep *dep;
{
+ char *name;
+
+ if (!JDEP_WFL (dep))
+ return;
+
+ name = IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)));
switch (JDEP_KIND (dep))
{
case JDEP_SUPER:
parse_error_context
(JDEP_WFL (dep), "Superclass `%s' of class `%s' not found",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break;
case JDEP_FIELD:
parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in declaration of field `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break;
case JDEP_METHOD: /* Covers arguments */
parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"argument `%s' of method `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep))));
break;
parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"return type of method `%s'",
- IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+ purify_type_name (name),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))));
break;
case JDEP_INTERFACE:
tree method_name = DECL_NAME (method_decl);
if (DECL_CONSTRUCTOR_P (method_decl))
return init_identifier_node;
- else if (ctxp
- && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name))
+ /* Don't confuse method only bearing the name of their class as
+ constructors */
+ else if (ctxp && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name)
+ && get_access_flags_from_decl (method_decl) <= ACC_PROTECTED
+ && TREE_TYPE (TREE_TYPE (method_decl)) == void_type_node)
return init_identifier_node;
else
return EXPR_WFL_NODE (method_name);
if (class == object_type_node)
return;
- TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+ if (!TYPE_NVIRTUALS (class))
+ TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
/* Should take interfaces into account. FIXME */
for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
DECL_NAME (found) = saved_found_wfl;
- TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+ if (!TYPE_NVIRTUALS (class))
+ TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
if (!saw_constructor)
{
- /* No constructor seen, we craft one, at line 0 */
+ /* No constructor seen, we craft one, at line 0. Since this
+ operation takes place after we laid methods out
+ (layout_class_methods), we prepare the its DECL
+ appropriately. */
int flags;
tree decl;
decl = create_artificial_method (class, flags, void_type_node,
init_identifier_node, NULL_TREE);
DECL_CONSTRUCTOR_P (decl) = 1;
+ layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
}
}
}
}
-/* Check the method on all the defined classes. Process all the
- classes that we compiled from source code for this CU. */
-
-void
-java_check_methods ()
-{
- tree current;
- for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
- if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
- CHECK_METHODS (TREE_VALUE (current));
-}
-
/* Lookup methods in interfaces using their name and partial
signature. Return a matching method only if their types differ. */
tree type = TREE_VALUE (tem);
tree name = TREE_PURPOSE (tem);
- /* If type is incomplete. Layout can't take place
- now. Create an incomplete decl and ask for the decl to be
- patched later */
+ /* If type is incomplete. Create an incomplete decl and ask for
+ the decl to be patched later */
if (INCOMPLETE_TYPE_P (type))
{
jdep *jdep;
tree real_type = GET_REAL_TYPE (type);
parm_decl = build_decl (PARM_DECL, name, real_type);
+ type = obtain_incomplete_type (type);
register_incomplete_type (JDEP_PARM, NULL_TREE, NULL_TREE, type);
jdep = CLASSD_LAST (ctxp->classd_list);
JDEP_MISC (jdep) = name;
/* Hold THIS for the scope of the current public method decl. */
static tree current_this;
-/* Layout all class found during parsing. Also fixes the order of some
- lists. */
+/* Layout the methods of all classes loaded in one way on an
+ other. Check methods of source parsed classes. Then reorder the
+ fields and layout the classes or the type of all source parsed
+ classes */
void
java_layout_classes ()
{
tree current;
- java_check_methods ();
- /* Error reported by the caller */
- if (java_error_count)
- return;
+ /* Layout the methods of all classes seen so far */
+ LAYOUT_SEEN_CLASS_METHODS ();
+ java_parse_abort_on_error ();
+ all_class_list = NULL_TREE;
+
+ /* Then check the methods of all parsed classes */
+ for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+ if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
+ CHECK_METHODS (TREE_VALUE (current));
+ java_parse_abort_on_error ();
+
for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (TREE_VALUE (current));
if (TYPE_FIELDS (current_class) && current_class != object_type_node
&& current_class != class_type_node)
{
- /* Always leave the dummy field in front if its already there,
- and layout the class for proper field offets. */
+ /* If the dummy field is there, reverse the right fields and
+ just layout the type for proper fields offset */
if (!DECL_NAME (TYPE_FIELDS (current_class)))
{
tree fields = TYPE_FIELDS (current_class);
TYPE_SIZE (current_class) = NULL_TREE;
layout_type (current_class);
}
- /* It's time to layout the class */
+ /* We don't have a dummy field, we need to layout the class,
+ after having reversed the fields */
else
{
TYPE_FIELDS (current_class) =
layout_class (current_class);
}
}
-
- /* Do a layout if necessary */
- if (!TYPE_SIZE (current_class)
- || (current_class == object_type_node)
- || current_class == class_type_node)
- safe_layout_class (current_class);
+ else
+ layout_class (current_class);
/* From now on, the class is considered completely loaded */
CLASS_LOADED_P (current_class) = 1;
if (java_error_count)
return;
}
+
+ /* We might have reloaded classes durign the process of laying out
+ classes for code generation. We must layout the methods of those
+ late additions, as constructor checks might use them */
+ LAYOUT_SEEN_CLASS_METHODS ();
+ java_parse_abort_on_error ();
}
/* Expand all methods in all registered classes. */
void
java_expand_classes ()
{
- ctxp = ctxp_for_generation;
- /* If we found error earlier, we don't want to report then twice. */
- if (java_error_count || !ctxp)
+ java_parse_abort_on_error ();
+ if (!(ctxp = ctxp_for_generation))
return;
java_layout_classes ();
java_parse_abort_on_error ();
/* Class to search is NULL if we're searching the current one */
if (class_to_search)
{
- class_to_search = resolve_no_layout (class_to_search, NULL_TREE);
+ class_to_search = resolve_and_layout (class_to_search,
+ NULL_TREE);
if (!class_to_search)
{
parse_error_context