[multiple changes]

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.
A step forward truly mixing .class and .java during package
compilation. Includes a Per's patch.

From-SVN: r23834
parent 333a9f0a
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> Tue Nov 24 12:57:13 1998 Per Bothner <bothner@cygnus.com>
* expr.c (java_lang_expand_expr): Add missing emit_queue. * expr.c (java_lang_expand_expr): Add missing emit_queue.
......
...@@ -1323,39 +1323,55 @@ push_super_field (this_class, super_class) ...@@ -1323,39 +1323,55 @@ push_super_field (this_class, super_class)
DECL_SIZE (base_decl) = TYPE_SIZE (super_class); 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 void
layout_class (this_class) layout_class (this_class)
tree this_class; tree this_class;
{ {
tree super_class = CLASSTYPE_SUPER (this_class); tree super_class = CLASSTYPE_SUPER (this_class);
tree handle_type = CLASS_TO_HANDLE_TYPE (this_class); tree field;
tree method_decl, field;
tree dtable_count;
int i;
if (super_class) if (super_class)
{ {
/* Class seen in source are now complete and can be layed out. super_class = maybe_layout_super_class (super_class);
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);
if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK) if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
{ {
TYPE_SIZE (this_class) = error_mark_node; TYPE_SIZE (this_class) = error_mark_node;
return; return;
} }
dtable_count = TYPE_NVIRTUALS (super_class);
if (TYPE_SIZE (this_class) == NULL_TREE) if (TYPE_SIZE (this_class) == NULL_TREE)
push_super_field (this_class, super_class); push_super_field (this_class, super_class);
} }
else
{
dtable_count = integer_zero_node;
}
for (field = TYPE_FIELDS (this_class); for (field = TYPE_FIELDS (this_class);
field != NULL_TREE; field = TREE_CHAIN (field)) field != NULL_TREE; field = TREE_CHAIN (field))
...@@ -1368,178 +1384,217 @@ layout_class (this_class) ...@@ -1368,178 +1384,217 @@ layout_class (this_class)
} }
layout_type (this_class); 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; if (super_class)
method_decl; method_decl = TREE_CHAIN (method_decl), i++)
{ {
char *ptr; super_class = maybe_layout_super_class (super_class);
char buf[8]; if (!TYPE_NVIRTUALS (super_class))
char *asm_name; layout_class_methods (super_class);
tree method_name = DECL_NAME (method_decl); dtable_count = TYPE_NVIRTUALS (super_class);
int method_name_is_wfl = }
(TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION); else
if (method_name_is_wfl) dtable_count = integer_zero_node;
method_name = java_get_real_method_name (method_decl);
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 #if 1
/* Remove this once we no longer need old (Kaffe / JDK 1.0) mangling. */ /* Remove this once we no longer need old (Kaffe / JDK 1.0) mangling. */
if (! flag_assume_compiled && METHOD_NATIVE (method_decl)) 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))); int encoded_len
*ptr; ) = unicode_mangling_length (IDENTIFIER_POINTER (method_name),
IDENTIFIER_LENGTH (method_name));
if (encoded_len > 0)
{ {
int ch = *ptr++; method_name_needs_escapes = 1;
if (ch == '.') emit_unicode_mangled_name (&temporary_obstack,
ch = '_'; IDENTIFIER_POINTER (method_name),
obstack_1grow (&temporary_obstack, (char) ch); IDENTIFIER_LENGTH (method_name));
} }
obstack_1grow (&temporary_obstack, (char) '_');
if (method_name == init_identifier_node)
obstack_grow (&temporary_obstack, "INIT", 4);
else else
obstack_grow (&temporary_obstack, {
IDENTIFIER_POINTER (method_name), obstack_grow (&temporary_obstack,
IDENTIFIER_LENGTH (method_name)); 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; tree a = arglist;
int method_name_needs_escapes = 0; tree argtype = TREE_VALUE (arg);
if (method_name != init_identifier_node int tindex = 1;
&& method_name != finit_identifier_node) if (TREE_CODE (argtype) == POINTER_TYPE)
{ {
int encoded_len /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
= unicode_mangling_length (IDENTIFIER_POINTER (method_name), while (a != arg && argtype != TREE_VALUE (a))
IDENTIFIER_LENGTH (method_name)); a = TREE_CHAIN (a), tindex++;
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));
}
} }
else
obstack_grow (&temporary_obstack, "__", 2); a = arg;
if (method_name == finit_identifier_node) if (a != arg)
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; )
{ {
tree a = arglist; char buf[12];
tree argtype = TREE_VALUE (arg); int nrepeats = 0;
int tindex = 1; do
if (TREE_CODE (argtype) == POINTER_TYPE)
{ {
/* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */ arg = TREE_CHAIN (arg); nrepeats++;
while (a != arg && argtype != TREE_VALUE (a))
a = TREE_CHAIN (a), tindex++;
} }
else while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
a = arg; if (nrepeats > 1)
if (a != arg)
{ {
char buf[12]; obstack_1grow (&temporary_obstack, 'N');
int nrepeats = 0; sprintf (buf, "%d", nrepeats);
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)); obstack_grow (&temporary_obstack, buf, strlen (buf));
if (tindex > 9) if (nrepeats > 9)
obstack_1grow (&temporary_obstack, '_'); obstack_1grow (&temporary_obstack, '_');
} }
else else
{ obstack_1grow (&temporary_obstack, 'T');
append_gpp_mangled_type (&temporary_obstack, argtype); sprintf (buf, "%d", tindex);
arg = TREE_CHAIN (arg); obstack_grow (&temporary_obstack, buf, strlen (buf));
} if (tindex > 9)
obstack_1grow (&temporary_obstack, '_');
} }
if (method_name_needs_escapes) else
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; )
{ {
if (*ptr++ == '.') append_gpp_mangled_type (&temporary_obstack, argtype);
p = ptr; 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)); if (*ptr++ == '.')
tree super_method = lookup_argument_method (super_class, method_name, 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); method_sig);
if (super_method != NULL_TREE) if (super_method != NULL_TREE)
{ {
DECL_VINDEX (method_decl) = DECL_VINDEX (super_method); DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
if (DECL_VINDEX (method_decl) == NULL_TREE) if (DECL_VINDEX (method_decl) == NULL_TREE)
error_with_decl (method_decl, error_with_decl (method_decl,
"non-static method '%s' overrides static method"); "non-static method '%s' overrides static method");
#if 0 #if 0
else if (TREE_TYPE (TREE_TYPE (method_decl)) else if (TREE_TYPE (TREE_TYPE (method_decl))
!= TREE_TYPE (TREE_TYPE (super_method))) != TREE_TYPE (TREE_TYPE (super_method)))
{ {
error_with_decl (method_decl, error_with_decl (method_decl,
"Method `%s' redefined with different return type"); "Method `%s' redefined with different return type");
error_with_decl (super_method, error_with_decl (super_method,
"Overridden decl is here"); "Overridden decl is here");
} }
#endif #endif
} }
else if (! METHOD_FINAL (method_decl) else if (! METHOD_FINAL (method_decl)
&& ! CLASS_FINAL (TYPE_NAME (this_class))) && ! 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); 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; return dtable_count;
#ifdef JAVA_USE_HANDLES
layout_type (handle_type);
#endif
} }
static tree registered_class = NULL_TREE; static tree registered_class = NULL_TREE;
......
...@@ -910,6 +910,7 @@ expand_java_NEW (type) ...@@ -910,6 +910,7 @@ expand_java_NEW (type)
{ {
if (! CLASS_LOADED_P (type)) if (! CLASS_LOADED_P (type))
load_class (type, 1); load_class (type, 1);
layout_class_methods (type);
push_value (build (CALL_EXPR, promote_type (type), push_value (build (CALL_EXPR, promote_type (type),
build_address_of (alloc_object_node), build_address_of (alloc_object_node),
tree_cons (NULL_TREE, build_class_ref (type), tree_cons (NULL_TREE, build_class_ref (type),
...@@ -1485,6 +1486,7 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1485,6 +1486,7 @@ expand_invoke (opcode, method_ref_index, nargs)
if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK) if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK)
fatal ("failed to find class '%s'", self_name); fatal ("failed to find class '%s'", self_name);
} }
layout_class_methods (self_type);
if (method_name == init_identifier_node) if (method_name == init_identifier_node)
method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type), method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type),
......
...@@ -112,6 +112,9 @@ extern tree main_class; ...@@ -112,6 +112,9 @@ extern tree main_class;
/* The class we are currently processing. */ /* The class we are currently processing. */
extern tree current_class; 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; /* Nonzero if we want to automatically do array bounds checking;
on by default. Use -fno-bounds-check to disable. */ on by default. Use -fno-bounds-check to disable. */
...@@ -483,6 +486,8 @@ extern tree unmangle_classname PROTO ((const char *name, int name_length)); ...@@ -483,6 +486,8 @@ extern tree unmangle_classname PROTO ((const char *name, int name_length));
extern tree parse_signature_string PROTO ((const unsigned char *, int)); extern tree parse_signature_string PROTO ((const unsigned char *, int));
extern tree get_type_from_signature PROTO ((tree)); extern tree get_type_from_signature PROTO ((tree));
extern void layout_class 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 make_class ();
extern tree build_class_ref PROTO ((tree)); extern tree build_class_ref PROTO ((tree));
extern tree build_dtable_decl PROTO ((tree)); extern tree build_dtable_decl PROTO ((tree));
...@@ -835,3 +840,10 @@ extern tree *type_map; ...@@ -835,3 +840,10 @@ extern tree *type_map;
if (java_error_count) \ if (java_error_count) \
return; \ 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))); \
}
...@@ -61,7 +61,10 @@ tree current_class = NULL_TREE; ...@@ -61,7 +61,10 @@ tree current_class = NULL_TREE;
/* The class we started with. */ /* The class we started with. */
tree main_class = NULL_TREE; 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; static tree current_field = NULL_TREE;
/* The METHOD_DECL for the current method. */ /* The METHOD_DECL for the current method. */
...@@ -450,8 +453,7 @@ load_class (class_or_name, verbose) ...@@ -450,8 +453,7 @@ load_class (class_or_name, verbose)
int verbose; int verbose;
{ {
JCF this_jcf, *jcf; JCF this_jcf, *jcf;
tree name = (TREE_CODE (class_or_name) == IDENTIFIER_NODE ? tree name;
class_or_name : DECL_NAME (TYPE_NAME (class_or_name)));
tree save_current_class = current_class; tree save_current_class = current_class;
char *save_input_filename = input_filename; char *save_input_filename = input_filename;
JCF *save_current_jcf = current_jcf; JCF *save_current_jcf = current_jcf;
...@@ -459,6 +461,17 @@ load_class (class_or_name, verbose) ...@@ -459,6 +461,17 @@ load_class (class_or_name, verbose)
if (current_jcf->read_state) if (current_jcf->read_state)
saved_pos = ftell (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); push_obstacks (&permanent_obstack, &permanent_obstack);
/* Search in current zip first. */ /* Search in current zip first. */
...@@ -494,10 +507,12 @@ load_class (class_or_name, verbose) ...@@ -494,10 +507,12 @@ load_class (class_or_name, verbose)
if (current_jcf->java_source) if (current_jcf->java_source)
jcf_parse_source (current_jcf); jcf_parse_source (current_jcf);
else { else {
int saved_lineno = lineno; java_parser_context_save_global ();
java_push_parser_context ();
input_filename = current_jcf->filename; input_filename = current_jcf->filename;
jcf_parse (current_jcf); jcf_parse (current_jcf);
lineno = saved_lineno; java_pop_parser_context (0);
java_parser_context_restore_global ();
} }
if (!current_jcf->seen_in_zip) if (!current_jcf->seen_in_zip)
...@@ -524,13 +539,16 @@ jcf_parse_source (jcf) ...@@ -524,13 +539,16 @@ jcf_parse_source (jcf)
java_push_parser_context (); java_push_parser_context ();
input_filename = current_jcf->filename; input_filename = current_jcf->filename;
file = get_identifier (input_filename); file = get_identifier (input_filename);
if (!(finput = fopen (input_filename, "r"))) if (!HAS_BEEN_ALREADY_PARSED_P (file))
fatal ("input file `%s' just disappeared - jcf_parse_source", {
input_filename); if (!(finput = fopen (input_filename, "r")))
parse_source_file (file); fatal ("input file `%s' just disappeared - jcf_parse_source",
if (fclose (finput)) input_filename);
fatal ("can't close input file `%s' stream - jcf_parse_source", parse_source_file (file);
input_filename); 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_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file));
java_parser_context_restore_global (); java_parser_context_restore_global ();
} }
...@@ -586,6 +604,11 @@ jcf_parse (jcf) ...@@ -586,6 +604,11 @@ jcf_parse (jcf)
push_obstacks (&permanent_obstack, &permanent_obstack); push_obstacks (&permanent_obstack, &permanent_obstack);
layout_class (current_class); 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 (); pop_obstacks ();
} }
...@@ -612,6 +635,8 @@ parse_class_file () ...@@ -612,6 +635,8 @@ parse_class_file ()
char *save_input_filename = input_filename; char *save_input_filename = input_filename;
int save_lineno = lineno; int save_lineno = lineno;
LAYOUT_SEEN_CLASS_METHODS ();
input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class)); input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class));
lineno = 0; lineno = 0;
debug_start_source_file (input_filename); debug_start_source_file (input_filename);
......
...@@ -2342,7 +2342,8 @@ generate_classfile (clas, state) ...@@ -2342,7 +2342,8 @@ generate_classfile (clas, state)
else else
i = 8 + 2 * total_supers; i = 8 + 2 * total_supers;
ptr = append_chunk (NULL, i, state); 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 */ i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
if (clas == object_type_node) if (clas == object_type_node)
{ {
......
...@@ -358,7 +358,12 @@ put_decl_node (node) ...@@ -358,7 +358,12 @@ put_decl_node (node)
put_decl_string (".", 1); put_decl_string (".", 1);
} }
#endif #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) if (TREE_CODE (node) == FUNCTION_DECL && TREE_TYPE (node) != NULL_TREE)
{ {
int i = 0; int i = 0;
......
...@@ -153,12 +153,12 @@ java_allocate_new_line () ...@@ -153,12 +153,12 @@ java_allocate_new_line ()
if (!ctxp->c_line) 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->max = JAVA_LINE_MAX;
ctxp->c_line->line = (unicode_t *)malloc ctxp->c_line->line = (unicode_t *)xmalloc
(sizeof (unicode_t)*ctxp->c_line->max); (sizeof (unicode_t)*ctxp->c_line->max);
ctxp->c_line->unicode_escape_p = 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; ctxp->c_line->white_space_only = 0;
} }
......
...@@ -4675,7 +4675,7 @@ void ...@@ -4675,7 +4675,7 @@ void
java_push_parser_context () java_push_parser_context ()
{ {
struct parser_ctxt *new = 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)); bzero (new, sizeof (struct parser_ctxt));
new->next = ctxp; new->next = ctxp;
...@@ -4716,7 +4716,7 @@ java_parser_context_restore_global () ...@@ -4716,7 +4716,7 @@ java_parser_context_restore_global ()
current_class = ctxp->current_class; current_class = ctxp->current_class;
input_filename = ctxp->filename; input_filename = ctxp->filename;
current_function_decl = ctxp->current_function_decl; current_function_decl = ctxp->current_function_decl;
if (extra_ctxp_pushed_p) if (!ctxp->next && extra_ctxp_pushed_p)
{ {
java_pop_parser_context (0); java_pop_parser_context (0);
extra_ctxp_pushed_p = 0; extra_ctxp_pushed_p = 0;
...@@ -5175,8 +5175,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl) ...@@ -5175,8 +5175,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
TREE_CHAIN (decl) = ctxp->class_list; TREE_CHAIN (decl) = ctxp->class_list;
ctxp->class_list = decl; 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); 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 */ /* Install a new dependency list element */
create_jdep_list (ctxp); create_jdep_list (ctxp);
...@@ -5310,7 +5311,7 @@ create_class (flags, id, super, interfaces) ...@@ -5310,7 +5311,7 @@ create_class (flags, id, super, interfaces)
super_decl_type = TREE_TYPE (super_decl); super_decl_type = TREE_TYPE (super_decl);
} }
else else
super_decl_type = super_decl_type =
register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE); register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE);
} }
else if (TREE_TYPE (decl) != object_type_node) else if (TREE_TYPE (decl) != object_type_node)
...@@ -5689,8 +5690,7 @@ method_header (flags, type, mdecl, throws) ...@@ -5689,8 +5690,7 @@ method_header (flags, type, mdecl, throws)
tree itype; tree itype;
patch_stage = JDEP_METHOD_RETURN; patch_stage = JDEP_METHOD_RETURN;
itype = register_incomplete_type (patch_stage, type, id, NULL_TREE); itype = register_incomplete_type (patch_stage, type, id, NULL_TREE);
TREE_TYPE (meth) = (TREE_CODE (itype) == TREE_LIST ? TREE_TYPE (meth) = GET_REAL_TYPE (itype);
TREE_PURPOSE (itype) : itype);
} }
} }
else else
...@@ -5928,6 +5928,7 @@ method_declarator (id, list) ...@@ -5928,6 +5928,7 @@ method_declarator (id, list)
tree name = EXPR_WFL_NODE (wfl_name); tree name = EXPR_WFL_NODE (wfl_name);
tree already, arg_node; tree already, arg_node;
tree type_wfl = NULL_TREE; tree type_wfl = NULL_TREE;
tree real_type;
/* Obtain a suitable type for resolution, if necessary */ /* Obtain a suitable type for resolution, if necessary */
SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain); SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain);
...@@ -5936,8 +5937,13 @@ method_declarator (id, list) ...@@ -5936,8 +5937,13 @@ method_declarator (id, list)
type = build_array_from_name (type, type_wfl, name, &name); type = build_array_from_name (type, type_wfl, name, &name);
EXPR_WFL_NODE (wfl_name) = name; EXPR_WFL_NODE (wfl_name) = name;
if (TREE_CODE (type) == RECORD_TYPE) real_type = GET_REAL_TYPE (type);
type = promote_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 */ /* Check redefinition */
for (already = arg_types; already; already = TREE_CHAIN (already)) for (already = arg_types; already; already = TREE_CHAIN (already))
...@@ -5963,7 +5969,7 @@ method_declarator (id, list) ...@@ -5963,7 +5969,7 @@ method_declarator (id, list)
} }
/* The argument node: a name and a (possibly) incomplete type */ /* 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) if (jdep)
JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node); JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node);
TREE_CHAIN (arg_node) = arg_types; TREE_CHAIN (arg_node) = arg_types;
...@@ -6081,11 +6087,7 @@ static void ...@@ -6081,11 +6087,7 @@ static void
create_jdep_list (ctxp) create_jdep_list (ctxp)
struct parser_ctxt *ctxp; struct parser_ctxt *ctxp;
{ {
jdeplist *new = malloc (sizeof (jdeplist)); jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist));
if (!new)
fatal ("Can't alloc jdeplist - create_jdep_list");
new->first = new->last = NULL; new->first = new->last = NULL;
new->next = ctxp->classd_list; new->next = ctxp->classd_list;
ctxp->classd_list = new; ctxp->classd_list = new;
...@@ -6105,14 +6107,22 @@ reverse_jdep_list (ctxp) ...@@ -6105,14 +6107,22 @@ reverse_jdep_list (ctxp)
return prev; 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 static tree
obtain_incomplete_type (wfl) obtain_incomplete_type (type_name)
tree wfl; tree type_name;
{ {
tree ptr; tree ptr, name;
tree name = EXPR_WFL_NODE (wfl);
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)) for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
if (TYPE_NAME (TREE_PURPOSE (ptr)) == name) if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
...@@ -6143,10 +6153,8 @@ register_incomplete_type (kind, wfl, decl, ptr) ...@@ -6143,10 +6153,8 @@ register_incomplete_type (kind, wfl, decl, ptr)
int kind; int kind;
tree wfl, decl, ptr; 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 */ if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */
ptr = obtain_incomplete_type (wfl); ptr = obtain_incomplete_type (wfl);
...@@ -6195,6 +6203,10 @@ java_check_circular_reference () ...@@ -6195,6 +6203,10 @@ java_check_circular_reference ()
} }
} }
/* 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 void
safe_layout_class (class) safe_layout_class (class)
tree class; tree class;
...@@ -6220,20 +6232,18 @@ jdep_resolve_class (dep) ...@@ -6220,20 +6232,18 @@ jdep_resolve_class (dep)
{ {
tree decl; tree decl;
if (!JDEP_RESOLVED_P (dep)) if (JDEP_RESOLVED_P (dep))
decl = JDEP_RESOLVED_DECL (dep);
else
{ {
decl = decl = resolve_class (JDEP_TO_RESOLVE (dep),
resolve_class (JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep)); JDEP_DECL (dep), JDEP_WFL (dep));
JDEP_RESOLVED (dep, decl); JDEP_RESOLVED (dep, decl);
} }
else
decl = JDEP_RESOLVED_DECL (dep);
if (!decl) if (!decl)
{ complete_class_report_errors (dep);
complete_class_report_errors (dep);
return NULL_TREE;
}
return decl; return decl;
} }
...@@ -6486,7 +6496,8 @@ do_resolve_class (class_type, decl, cl) ...@@ -6486,7 +6496,8 @@ do_resolve_class (class_type, decl, cl)
} }
/* Resolve NAME and lay it out (if not done and if not the current /* 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 static tree
resolve_and_layout (something, cl) resolve_and_layout (something, cl)
...@@ -6495,20 +6506,49 @@ resolve_and_layout (something, cl) ...@@ -6495,20 +6506,49 @@ resolve_and_layout (something, cl)
{ {
tree decl; tree decl;
if (TREE_CODE (something) == POINTER_TYPE) /* Don't do that on the current class */
something = TREE_TYPE (something); 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) if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
return NULL_TREE; 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) if (TREE_CODE (something) != IDENTIFIER_NODE)
something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ? something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something)); DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
decl = resolve_no_layout (something, cl); if (!(decl = resolve_no_layout (something, cl)))
if (decl && TREE_TYPE (decl) != current_class return NULL_TREE;
&& !CLASS_LOADED_P (TREE_TYPE (decl)))
/* 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)); safe_layout_class (TREE_TYPE (decl));
return decl; return decl;
} }
...@@ -6528,8 +6568,10 @@ resolve_no_layout (name, cl) ...@@ -6528,8 +6568,10 @@ resolve_no_layout (name, cl)
return decl; return decl;
} }
/* Called to report errors. Skip leader '[' in a complex array type /* Called when reporting errors. Skip leader '[' in a complex array
description that failed to be resolved. */ 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 * static char *
purify_type_name (name) purify_type_name (name)
...@@ -6537,6 +6579,7 @@ purify_type_name (name) ...@@ -6537,6 +6579,7 @@ purify_type_name (name)
{ {
while (*name && *name == '[') while (*name && *name == '[')
name++; name++;
return name; return name;
} }
...@@ -6546,25 +6589,31 @@ static void ...@@ -6546,25 +6589,31 @@ static void
complete_class_report_errors (dep) complete_class_report_errors (dep)
jdep *dep; jdep *dep;
{ {
char *name;
if (!JDEP_WFL (dep))
return;
name = IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)));
switch (JDEP_KIND (dep)) switch (JDEP_KIND (dep))
{ {
case JDEP_SUPER: case JDEP_SUPER:
parse_error_context parse_error_context
(JDEP_WFL (dep), "Superclass `%s' of class `%s' not found", (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)))); IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break; break;
case JDEP_FIELD: case JDEP_FIELD:
parse_error_context parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in declaration of field `%s'", (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)))); IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break; break;
case JDEP_METHOD: /* Covers arguments */ case JDEP_METHOD: /* Covers arguments */
parse_error_context parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the " (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"argument `%s' of method `%s'", "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_DECL_WFL (dep))),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep)))); IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep))));
break; break;
...@@ -6572,7 +6621,7 @@ complete_class_report_errors (dep) ...@@ -6572,7 +6621,7 @@ complete_class_report_errors (dep)
parse_error_context parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the " (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"return type of method `%s'", "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)))); IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))));
break; break;
case JDEP_INTERFACE: case JDEP_INTERFACE:
...@@ -6662,8 +6711,11 @@ java_get_real_method_name (method_decl) ...@@ -6662,8 +6711,11 @@ java_get_real_method_name (method_decl)
tree method_name = DECL_NAME (method_decl); tree method_name = DECL_NAME (method_decl);
if (DECL_CONSTRUCTOR_P (method_decl)) if (DECL_CONSTRUCTOR_P (method_decl))
return init_identifier_node; return init_identifier_node;
else if (ctxp /* Don't confuse method only bearing the name of their class as
&& ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name)) 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; return init_identifier_node;
else else
return EXPR_WFL_NODE (method_name); return EXPR_WFL_NODE (method_name);
...@@ -6728,7 +6780,8 @@ java_check_regular_methods (class_decl) ...@@ -6728,7 +6780,8 @@ java_check_regular_methods (class_decl)
if (class == object_type_node) if (class == object_type_node)
return; 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 */ /* Should take interfaces into account. FIXME */
for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method)) for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
...@@ -6877,11 +6930,15 @@ java_check_regular_methods (class_decl) ...@@ -6877,11 +6930,15 @@ java_check_regular_methods (class_decl)
if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl) if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
DECL_NAME (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) 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; int flags;
tree decl; tree decl;
...@@ -6893,6 +6950,7 @@ java_check_regular_methods (class_decl) ...@@ -6893,6 +6950,7 @@ java_check_regular_methods (class_decl)
decl = create_artificial_method (class, flags, void_type_node, decl = create_artificial_method (class, flags, void_type_node,
init_identifier_node, NULL_TREE); init_identifier_node, NULL_TREE);
DECL_CONSTRUCTOR_P (decl) = 1; DECL_CONSTRUCTOR_P (decl) = 1;
layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
} }
} }
...@@ -7013,18 +7071,6 @@ java_check_abstract_methods (interface_decl) ...@@ -7013,18 +7071,6 @@ java_check_abstract_methods (interface_decl)
} }
} }
/* 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 /* Lookup methods in interfaces using their name and partial
signature. Return a matching method only if their types differ. */ signature. Return a matching method only if their types differ. */
...@@ -7598,14 +7644,14 @@ source_start_java_method (fndecl) ...@@ -7598,14 +7644,14 @@ source_start_java_method (fndecl)
tree type = TREE_VALUE (tem); tree type = TREE_VALUE (tem);
tree name = TREE_PURPOSE (tem); tree name = TREE_PURPOSE (tem);
/* If type is incomplete. Layout can't take place /* If type is incomplete. Create an incomplete decl and ask for
now. Create an incomplete decl and ask for the decl to be the decl to be patched later */
patched later */
if (INCOMPLETE_TYPE_P (type)) if (INCOMPLETE_TYPE_P (type))
{ {
jdep *jdep; jdep *jdep;
tree real_type = GET_REAL_TYPE (type); tree real_type = GET_REAL_TYPE (type);
parm_decl = build_decl (PARM_DECL, name, real_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); register_incomplete_type (JDEP_PARM, NULL_TREE, NULL_TREE, type);
jdep = CLASSD_LAST (ctxp->classd_list); jdep = CLASSD_LAST (ctxp->classd_list);
JDEP_MISC (jdep) = name; JDEP_MISC (jdep) = name;
...@@ -7784,18 +7830,27 @@ add_stmt_to_compound (existing, type, stmt) ...@@ -7784,18 +7830,27 @@ add_stmt_to_compound (existing, type, stmt)
/* Hold THIS for the scope of the current public method decl. */ /* Hold THIS for the scope of the current public method decl. */
static tree current_this; static tree current_this;
/* Layout all class found during parsing. Also fixes the order of some /* Layout the methods of all classes loaded in one way on an
lists. */ other. Check methods of source parsed classes. Then reorder the
fields and layout the classes or the type of all source parsed
classes */
void void
java_layout_classes () java_layout_classes ()
{ {
tree current; tree current;
java_check_methods (); /* Layout the methods of all classes seen so far */
/* Error reported by the caller */ LAYOUT_SEEN_CLASS_METHODS ();
if (java_error_count) java_parse_abort_on_error ();
return; 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)) for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
{ {
current_class = TREE_TYPE (TREE_VALUE (current)); current_class = TREE_TYPE (TREE_VALUE (current));
...@@ -7805,8 +7860,8 @@ java_layout_classes () ...@@ -7805,8 +7860,8 @@ java_layout_classes ()
if (TYPE_FIELDS (current_class) && current_class != object_type_node if (TYPE_FIELDS (current_class) && current_class != object_type_node
&& current_class != class_type_node) && current_class != class_type_node)
{ {
/* Always leave the dummy field in front if its already there, /* If the dummy field is there, reverse the right fields and
and layout the class for proper field offets. */ just layout the type for proper fields offset */
if (!DECL_NAME (TYPE_FIELDS (current_class))) if (!DECL_NAME (TYPE_FIELDS (current_class)))
{ {
tree fields = TYPE_FIELDS (current_class); tree fields = TYPE_FIELDS (current_class);
...@@ -7814,7 +7869,8 @@ java_layout_classes () ...@@ -7814,7 +7869,8 @@ java_layout_classes ()
TYPE_SIZE (current_class) = NULL_TREE; TYPE_SIZE (current_class) = NULL_TREE;
layout_type (current_class); 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 else
{ {
TYPE_FIELDS (current_class) = TYPE_FIELDS (current_class) =
...@@ -7823,12 +7879,8 @@ java_layout_classes () ...@@ -7823,12 +7879,8 @@ java_layout_classes ()
layout_class (current_class); layout_class (current_class);
} }
} }
else
/* Do a layout if necessary */ layout_class (current_class);
if (!TYPE_SIZE (current_class)
|| (current_class == object_type_node)
|| current_class == class_type_node)
safe_layout_class (current_class);
/* From now on, the class is considered completely loaded */ /* From now on, the class is considered completely loaded */
CLASS_LOADED_P (current_class) = 1; CLASS_LOADED_P (current_class) = 1;
...@@ -7837,6 +7889,12 @@ java_layout_classes () ...@@ -7837,6 +7889,12 @@ java_layout_classes ()
if (java_error_count) if (java_error_count)
return; 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. */ /* Expand all methods in all registered classes. */
...@@ -8100,9 +8158,8 @@ java_expand_finals () ...@@ -8100,9 +8158,8 @@ java_expand_finals ()
void void
java_expand_classes () java_expand_classes ()
{ {
ctxp = ctxp_for_generation; java_parse_abort_on_error ();
/* If we found error earlier, we don't want to report then twice. */ if (!(ctxp = ctxp_for_generation))
if (java_error_count || !ctxp)
return; return;
java_layout_classes (); java_layout_classes ();
java_parse_abort_on_error (); java_parse_abort_on_error ();
...@@ -8996,7 +9053,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl, super) ...@@ -8996,7 +9053,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl, super)
/* Class to search is NULL if we're searching the current one */ /* Class to search is NULL if we're searching the current one */
if (class_to_search) 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) if (!class_to_search)
{ {
parse_error_context parse_error_context
...@@ -9817,6 +9875,7 @@ java_complete_tree (node) ...@@ -9817,6 +9875,7 @@ java_complete_tree (node)
TREE_OPERAND (node, 0) = cn; TREE_OPERAND (node, 0) = cn;
TREE_TYPE (node) = void_type_node; TREE_TYPE (node) = void_type_node;
CAN_COMPLETE_NORMALLY (node) = 1; CAN_COMPLETE_NORMALLY (node) = 1;
TREE_SIDE_EFFECTS (node) = 1;
break; break;
case DEFAULT_EXPR: case DEFAULT_EXPR:
...@@ -9832,6 +9891,7 @@ java_complete_tree (node) ...@@ -9832,6 +9891,7 @@ java_complete_tree (node)
else else
SWITCH_HAS_DEFAULT (nn) = 1; SWITCH_HAS_DEFAULT (nn) = 1;
TREE_TYPE (node) = void_type_node; TREE_TYPE (node) = void_type_node;
TREE_SIDE_EFFECTS (node) = 1;
CAN_COMPLETE_NORMALLY (node) = 1; CAN_COMPLETE_NORMALLY (node) = 1;
break; break;
......
...@@ -147,10 +147,10 @@ extern tree stabilize_reference PROTO ((tree)); ...@@ -147,10 +147,10 @@ extern tree stabilize_reference PROTO ((tree));
TYPE_NAME (ptr) = name; \ TYPE_NAME (ptr) = name; \
} }
#define INCOMPLETE_TYPE_P(NODE) \ #define INCOMPLETE_TYPE_P(NODE) \
((TREE_CODE (NODE) == TREE_LIST) \ ((TREE_CODE (NODE) == POINTER_TYPE) \
&& (TREE_CODE (TREE_PURPOSE (NODE)) == POINTER_TYPE) \ && !TREE_TYPE (NODE) \
&& (TREE_TYPE (TREE_PURPOSE (NODE)) == NULL_TREE)) && TREE_CODE (TYPE_NAME (NODE)) == IDENTIFIER_NODE)
/* Set the EMIT_LINE_NOTE flag of a EXPR_WLF to 1 if debug information /* 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. */ are requested. Works in the context of a parser rule. */
...@@ -589,13 +589,13 @@ struct parser_ctxt { ...@@ -589,13 +589,13 @@ struct parser_ctxt {
int parser_ccb_indent; /* Keep track of {} indent, parser */ int parser_ccb_indent; /* Keep track of {} indent, parser */
int osb_number; /* Keep track of ['s */ int osb_number; /* Keep track of ['s */
int minus_seen; /* Integral literal overflow */ int minus_seen; /* Integral literal overflow */
int lineno; /* Current lineno */ int lineno; /* Current lineno */
int java_error_flag; /* Report error when true */ int java_error_flag; /* Report error when true */
int deprecated; /* @deprecated tag seen */ int deprecated; /* @deprecated tag seen */
/* This section is defined only if we compile jc1 */ /* This section is defined only if we compile jc1 */
#ifndef JC1_LITE #ifndef JC1_LITE
tree modifier_ctx [11]; /* WFL of modifiers */ tree modifier_ctx [11]; /* WFL of modifiers */
tree current_class; /* Current class */ tree current_class; /* Current class */
tree current_function_decl; /* Current function decl, save/restore */ tree current_function_decl; /* Current function decl, save/restore */
...@@ -609,30 +609,34 @@ struct parser_ctxt { ...@@ -609,30 +609,34 @@ struct parser_ctxt {
tree package; /* Defined package ID */ tree package; /* Defined package ID */
/* Those tow list are saved accross file traversal */
tree incomplete_class; /* List of non-complete classes */ tree incomplete_class; /* List of non-complete classes */
tree current_parsed_class; /* Class currently parsed */ tree gclass_list; /* All classes seen from source code */
tree current_parsed_class_un; /* Curr. parsed class unqualified name */
/* These two lists won't survive file traversal */
tree class_list; /* List of classes in a CU */ 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 */ 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 non_static_initialized; /* List of non static initialized fields */
tree static_initialized; /* List of static non final initialized */ tree static_initialized; /* List of static non final initialized */
tree import_list; /* List of import */ tree import_list; /* List of import */
tree import_demand_list; /* List of import on demand */ tree import_demand_list; /* List of import on demand */
tree current_loop; /* List of the currently nested loops/switches */ tree current_loop; /* List of the currently nested
tree current_labeled_block; /* List of currently nested loops/switches */
labeled blocks. */ 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 int explicit_constructor_p; /* True when processing an explicit
explicit constructor. This flag is constructor. This flag is used to trap
used to trap illegal argument usage illegal argument usage during an
during an explicit constructor explicit constructor invocation. */
invocation. */
#endif /* JC1_LITE */ #endif /* JC1_LITE */
}; };
...@@ -803,7 +807,6 @@ void safe_layout_class PROTO ((tree)); ...@@ -803,7 +807,6 @@ void safe_layout_class PROTO ((tree));
void java_complete_class PROTO ((void)); void java_complete_class PROTO ((void));
void java_check_circular_reference PROTO ((void)); void java_check_circular_reference PROTO ((void));
void java_check_final PROTO ((void)); void java_check_final PROTO ((void));
void java_check_methods PROTO ((void));
void java_layout_classes PROTO ((void)); void java_layout_classes PROTO ((void));
tree java_method_add_stmt PROTO ((tree, tree)); tree java_method_add_stmt PROTO ((tree, tree));
char *java_get_line_col PROTO ((char *, int, int)); char *java_get_line_col PROTO ((char *, int, int));
......
...@@ -2070,7 +2070,7 @@ void ...@@ -2070,7 +2070,7 @@ void
java_push_parser_context () java_push_parser_context ()
{ {
struct parser_ctxt *new = 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)); bzero (new, sizeof (struct parser_ctxt));
new->next = ctxp; new->next = ctxp;
...@@ -2111,7 +2111,7 @@ java_parser_context_restore_global () ...@@ -2111,7 +2111,7 @@ java_parser_context_restore_global ()
current_class = ctxp->current_class; current_class = ctxp->current_class;
input_filename = ctxp->filename; input_filename = ctxp->filename;
current_function_decl = ctxp->current_function_decl; current_function_decl = ctxp->current_function_decl;
if (extra_ctxp_pushed_p) if (!ctxp->next && extra_ctxp_pushed_p)
{ {
java_pop_parser_context (0); java_pop_parser_context (0);
extra_ctxp_pushed_p = 0; extra_ctxp_pushed_p = 0;
...@@ -2570,8 +2570,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl) ...@@ -2570,8 +2570,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
TREE_CHAIN (decl) = ctxp->class_list; TREE_CHAIN (decl) = ctxp->class_list;
ctxp->class_list = decl; 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); 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 */ /* Install a new dependency list element */
create_jdep_list (ctxp); create_jdep_list (ctxp);
...@@ -3084,8 +3085,7 @@ method_header (flags, type, mdecl, throws) ...@@ -3084,8 +3085,7 @@ method_header (flags, type, mdecl, throws)
tree itype; tree itype;
patch_stage = JDEP_METHOD_RETURN; patch_stage = JDEP_METHOD_RETURN;
itype = register_incomplete_type (patch_stage, type, id, NULL_TREE); itype = register_incomplete_type (patch_stage, type, id, NULL_TREE);
TREE_TYPE (meth) = (TREE_CODE (itype) == TREE_LIST ? TREE_TYPE (meth) = GET_REAL_TYPE (itype);
TREE_PURPOSE (itype) : itype);
} }
} }
else else
...@@ -3323,6 +3323,7 @@ method_declarator (id, list) ...@@ -3323,6 +3323,7 @@ method_declarator (id, list)
tree name = EXPR_WFL_NODE (wfl_name); tree name = EXPR_WFL_NODE (wfl_name);
tree already, arg_node; tree already, arg_node;
tree type_wfl = NULL_TREE; tree type_wfl = NULL_TREE;
tree real_type;
/* Obtain a suitable type for resolution, if necessary */ /* Obtain a suitable type for resolution, if necessary */
SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain); SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain);
...@@ -3331,8 +3332,13 @@ method_declarator (id, list) ...@@ -3331,8 +3332,13 @@ method_declarator (id, list)
type = build_array_from_name (type, type_wfl, name, &name); type = build_array_from_name (type, type_wfl, name, &name);
EXPR_WFL_NODE (wfl_name) = name; EXPR_WFL_NODE (wfl_name) = name;
if (TREE_CODE (type) == RECORD_TYPE) real_type = GET_REAL_TYPE (type);
type = promote_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 */ /* Check redefinition */
for (already = arg_types; already; already = TREE_CHAIN (already)) for (already = arg_types; already; already = TREE_CHAIN (already))
...@@ -3358,7 +3364,7 @@ method_declarator (id, list) ...@@ -3358,7 +3364,7 @@ method_declarator (id, list)
} }
/* The argument node: a name and a (possibly) incomplete type */ /* 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) if (jdep)
JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node); JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node);
TREE_CHAIN (arg_node) = arg_types; TREE_CHAIN (arg_node) = arg_types;
...@@ -3476,11 +3482,7 @@ static void ...@@ -3476,11 +3482,7 @@ static void
create_jdep_list (ctxp) create_jdep_list (ctxp)
struct parser_ctxt *ctxp; struct parser_ctxt *ctxp;
{ {
jdeplist *new = malloc (sizeof (jdeplist)); jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist));
if (!new)
fatal ("Can't alloc jdeplist - create_jdep_list");
new->first = new->last = NULL; new->first = new->last = NULL;
new->next = ctxp->classd_list; new->next = ctxp->classd_list;
ctxp->classd_list = new; ctxp->classd_list = new;
...@@ -3500,14 +3502,22 @@ reverse_jdep_list (ctxp) ...@@ -3500,14 +3502,22 @@ reverse_jdep_list (ctxp)
return prev; 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 static tree
obtain_incomplete_type (wfl) obtain_incomplete_type (type_name)
tree wfl; tree type_name;
{ {
tree ptr; tree ptr, name;
tree name = EXPR_WFL_NODE (wfl);
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)) for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
if (TYPE_NAME (TREE_PURPOSE (ptr)) == name) if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
...@@ -3538,10 +3548,8 @@ register_incomplete_type (kind, wfl, decl, ptr) ...@@ -3538,10 +3548,8 @@ register_incomplete_type (kind, wfl, decl, ptr)
int kind; int kind;
tree wfl, decl, ptr; 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 */ if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */
ptr = obtain_incomplete_type (wfl); ptr = obtain_incomplete_type (wfl);
...@@ -3590,6 +3598,10 @@ java_check_circular_reference () ...@@ -3590,6 +3598,10 @@ java_check_circular_reference ()
} }
} }
/* 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 void
safe_layout_class (class) safe_layout_class (class)
tree class; tree class;
...@@ -3615,20 +3627,18 @@ jdep_resolve_class (dep) ...@@ -3615,20 +3627,18 @@ jdep_resolve_class (dep)
{ {
tree decl; tree decl;
if (!JDEP_RESOLVED_P (dep)) if (JDEP_RESOLVED_P (dep))
decl = JDEP_RESOLVED_DECL (dep);
else
{ {
decl = decl = resolve_class (JDEP_TO_RESOLVE (dep),
resolve_class (JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep)); JDEP_DECL (dep), JDEP_WFL (dep));
JDEP_RESOLVED (dep, decl); JDEP_RESOLVED (dep, decl);
} }
else
decl = JDEP_RESOLVED_DECL (dep);
if (!decl) if (!decl)
{ complete_class_report_errors (dep);
complete_class_report_errors (dep);
return NULL_TREE;
}
return decl; return decl;
} }
...@@ -3881,7 +3891,8 @@ do_resolve_class (class_type, decl, cl) ...@@ -3881,7 +3891,8 @@ do_resolve_class (class_type, decl, cl)
} }
/* Resolve NAME and lay it out (if not done and if not the current /* 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 static tree
resolve_and_layout (something, cl) resolve_and_layout (something, cl)
...@@ -3890,20 +3901,49 @@ resolve_and_layout (something, cl) ...@@ -3890,20 +3901,49 @@ resolve_and_layout (something, cl)
{ {
tree decl; tree decl;
if (TREE_CODE (something) == POINTER_TYPE) /* Don't do that on the current class */
something = TREE_TYPE (something); 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) if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
return NULL_TREE; 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) if (TREE_CODE (something) != IDENTIFIER_NODE)
something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ? something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something)); DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
decl = resolve_no_layout (something, cl); if (!(decl = resolve_no_layout (something, cl)))
if (decl && TREE_TYPE (decl) != current_class return NULL_TREE;
&& !CLASS_LOADED_P (TREE_TYPE (decl)))
/* 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)); safe_layout_class (TREE_TYPE (decl));
return decl; return decl;
} }
...@@ -3923,8 +3963,8 @@ resolve_no_layout (name, cl) ...@@ -3923,8 +3963,8 @@ resolve_no_layout (name, cl)
return decl; return decl;
} }
/* Called to report errors. Skip leader '[' in a complex array type /* Called when reporting errors. Skip leader '[' in a complex array
description that failed to be resolved. */ type description that failed to be resolved. */
static char * static char *
purify_type_name (name) purify_type_name (name)
...@@ -3941,25 +3981,31 @@ static void ...@@ -3941,25 +3981,31 @@ static void
complete_class_report_errors (dep) complete_class_report_errors (dep)
jdep *dep; jdep *dep;
{ {
char *name;
if (!JDEP_WFL (dep))
return;
name = IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)));
switch (JDEP_KIND (dep)) switch (JDEP_KIND (dep))
{ {
case JDEP_SUPER: case JDEP_SUPER:
parse_error_context parse_error_context
(JDEP_WFL (dep), "Superclass `%s' of class `%s' not found", (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)))); IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break; break;
case JDEP_FIELD: case JDEP_FIELD:
parse_error_context parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in declaration of field `%s'", (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)))); IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
break; break;
case JDEP_METHOD: /* Covers arguments */ case JDEP_METHOD: /* Covers arguments */
parse_error_context parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the " (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"argument `%s' of method `%s'", "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_DECL_WFL (dep))),
IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep)))); IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep))));
break; break;
...@@ -3967,7 +4013,7 @@ complete_class_report_errors (dep) ...@@ -3967,7 +4013,7 @@ complete_class_report_errors (dep)
parse_error_context parse_error_context
(JDEP_WFL (dep), "Type `%s' not found in the declaration of the " (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
"return type of method `%s'", "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)))); IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))));
break; break;
case JDEP_INTERFACE: case JDEP_INTERFACE:
...@@ -4057,8 +4103,11 @@ java_get_real_method_name (method_decl) ...@@ -4057,8 +4103,11 @@ java_get_real_method_name (method_decl)
tree method_name = DECL_NAME (method_decl); tree method_name = DECL_NAME (method_decl);
if (DECL_CONSTRUCTOR_P (method_decl)) if (DECL_CONSTRUCTOR_P (method_decl))
return init_identifier_node; return init_identifier_node;
else if (ctxp /* Don't confuse method only bearing the name of their class as
&& ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name)) 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; return init_identifier_node;
else else
return EXPR_WFL_NODE (method_name); return EXPR_WFL_NODE (method_name);
...@@ -4123,7 +4172,8 @@ java_check_regular_methods (class_decl) ...@@ -4123,7 +4172,8 @@ java_check_regular_methods (class_decl)
if (class == object_type_node) if (class == object_type_node)
return; 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 */ /* Should take interfaces into account. FIXME */
for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method)) for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
...@@ -4272,11 +4322,15 @@ java_check_regular_methods (class_decl) ...@@ -4272,11 +4322,15 @@ java_check_regular_methods (class_decl)
if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl) if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
DECL_NAME (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) 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; int flags;
tree decl; tree decl;
...@@ -4288,6 +4342,7 @@ java_check_regular_methods (class_decl) ...@@ -4288,6 +4342,7 @@ java_check_regular_methods (class_decl)
decl = create_artificial_method (class, flags, void_type_node, decl = create_artificial_method (class, flags, void_type_node,
init_identifier_node, NULL_TREE); init_identifier_node, NULL_TREE);
DECL_CONSTRUCTOR_P (decl) = 1; DECL_CONSTRUCTOR_P (decl) = 1;
layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
} }
} }
...@@ -4408,18 +4463,6 @@ java_check_abstract_methods (interface_decl) ...@@ -4408,18 +4463,6 @@ java_check_abstract_methods (interface_decl)
} }
} }
/* 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 /* Lookup methods in interfaces using their name and partial
signature. Return a matching method only if their types differ. */ signature. Return a matching method only if their types differ. */
...@@ -4993,14 +5036,14 @@ source_start_java_method (fndecl) ...@@ -4993,14 +5036,14 @@ source_start_java_method (fndecl)
tree type = TREE_VALUE (tem); tree type = TREE_VALUE (tem);
tree name = TREE_PURPOSE (tem); tree name = TREE_PURPOSE (tem);
/* If type is incomplete. Layout can't take place /* If type is incomplete. Create an incomplete decl and ask for
now. Create an incomplete decl and ask for the decl to be the decl to be patched later */
patched later */
if (INCOMPLETE_TYPE_P (type)) if (INCOMPLETE_TYPE_P (type))
{ {
jdep *jdep; jdep *jdep;
tree real_type = GET_REAL_TYPE (type); tree real_type = GET_REAL_TYPE (type);
parm_decl = build_decl (PARM_DECL, name, real_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); register_incomplete_type (JDEP_PARM, NULL_TREE, NULL_TREE, type);
jdep = CLASSD_LAST (ctxp->classd_list); jdep = CLASSD_LAST (ctxp->classd_list);
JDEP_MISC (jdep) = name; JDEP_MISC (jdep) = name;
...@@ -5179,18 +5222,27 @@ add_stmt_to_compound (existing, type, stmt) ...@@ -5179,18 +5222,27 @@ add_stmt_to_compound (existing, type, stmt)
/* Hold THIS for the scope of the current public method decl. */ /* Hold THIS for the scope of the current public method decl. */
static tree current_this; static tree current_this;
/* Layout all class found during parsing. Also fixes the order of some /* Layout the methods of all classes loaded in one way on an
lists. */ other. Check methods of source parsed classes. Then reorder the
fields and layout the classes or the type of all source parsed
classes */
void void
java_layout_classes () java_layout_classes ()
{ {
tree current; tree current;
java_check_methods (); /* Layout the methods of all classes seen so far */
/* Error reported by the caller */ LAYOUT_SEEN_CLASS_METHODS ();
if (java_error_count) java_parse_abort_on_error ();
return; 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)) for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
{ {
current_class = TREE_TYPE (TREE_VALUE (current)); current_class = TREE_TYPE (TREE_VALUE (current));
...@@ -5200,8 +5252,8 @@ java_layout_classes () ...@@ -5200,8 +5252,8 @@ java_layout_classes ()
if (TYPE_FIELDS (current_class) && current_class != object_type_node if (TYPE_FIELDS (current_class) && current_class != object_type_node
&& current_class != class_type_node) && current_class != class_type_node)
{ {
/* Always leave the dummy field in front if its already there, /* If the dummy field is there, reverse the right fields and
and layout the class for proper field offets. */ just layout the type for proper fields offset */
if (!DECL_NAME (TYPE_FIELDS (current_class))) if (!DECL_NAME (TYPE_FIELDS (current_class)))
{ {
tree fields = TYPE_FIELDS (current_class); tree fields = TYPE_FIELDS (current_class);
...@@ -5209,7 +5261,8 @@ java_layout_classes () ...@@ -5209,7 +5261,8 @@ java_layout_classes ()
TYPE_SIZE (current_class) = NULL_TREE; TYPE_SIZE (current_class) = NULL_TREE;
layout_type (current_class); 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 else
{ {
TYPE_FIELDS (current_class) = TYPE_FIELDS (current_class) =
...@@ -5218,12 +5271,8 @@ java_layout_classes () ...@@ -5218,12 +5271,8 @@ java_layout_classes ()
layout_class (current_class); layout_class (current_class);
} }
} }
else
/* Do a layout if necessary */ layout_class (current_class);
if (!TYPE_SIZE (current_class)
|| (current_class == object_type_node)
|| current_class == class_type_node)
safe_layout_class (current_class);
/* From now on, the class is considered completely loaded */ /* From now on, the class is considered completely loaded */
CLASS_LOADED_P (current_class) = 1; CLASS_LOADED_P (current_class) = 1;
...@@ -5232,6 +5281,12 @@ java_layout_classes () ...@@ -5232,6 +5281,12 @@ java_layout_classes ()
if (java_error_count) if (java_error_count)
return; 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. */ /* Expand all methods in all registered classes. */
...@@ -5495,9 +5550,8 @@ java_expand_finals () ...@@ -5495,9 +5550,8 @@ java_expand_finals ()
void void
java_expand_classes () java_expand_classes ()
{ {
ctxp = ctxp_for_generation; java_parse_abort_on_error ();
/* If we found error earlier, we don't want to report then twice. */ if (!(ctxp = ctxp_for_generation))
if (java_error_count || !ctxp)
return; return;
java_layout_classes (); java_layout_classes ();
java_parse_abort_on_error (); java_parse_abort_on_error ();
...@@ -6391,7 +6445,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl, super) ...@@ -6391,7 +6445,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl, super)
/* Class to search is NULL if we're searching the current one */ /* Class to search is NULL if we're searching the current one */
if (class_to_search) 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) if (!class_to_search)
{ {
parse_error_context parse_error_context
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment