[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
This commit is contained in:
Alexandre Petit-Bianco 1998-11-24 09:57:41 -08:00
parent 333a9f0aaf
commit 23a79c6192
11 changed files with 670 additions and 383 deletions

View File

@ -1,3 +1,72 @@
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.

View File

@ -1323,39 +1323,55 @@ push_super_field (this_class, 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
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))
@ -1368,178 +1384,217 @@ layout_class (this_class)
}
layout_type (this_class);
}
void
layout_class_methods (this_class)
tree this_class;
{
tree method_decl, dtable_count;
tree super_class, handle_type;
if (TYPE_NVIRTUALS (this_class))
return;
push_obstacks (&permanent_obstack, &permanent_obstack);
super_class = CLASSTYPE_SUPER (this_class);
handle_type = CLASS_TO_HANDLE_TYPE (this_class);
if (super_class)
{
super_class = maybe_layout_super_class (super_class);
if (!TYPE_NVIRTUALS (super_class))
layout_class_methods (super_class);
dtable_count = TYPE_NVIRTUALS (super_class);
}
else
dtable_count = integer_zero_node;
TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
for (method_decl = TYPE_METHODS (handle_type), i = 0;
method_decl; method_decl = TREE_CHAIN (method_decl), i++)
{
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))
{
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)
{
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));
}
}
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);
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; )
{
tree a = arglist;
tree argtype = TREE_VALUE (arg);
int tindex = 1;
if (TREE_CODE (argtype) == POINTER_TYPE)
{
/* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
while (a != arg && argtype != TREE_VALUE (a))
a = TREE_CHAIN (a), tindex++;
}
else
a = arg;
if (a != arg)
{
char buf[12];
int nrepeats = 0;
do
{
arg = TREE_CHAIN (arg); nrepeats++;
}
while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
if (nrepeats > 1)
{
obstack_1grow (&temporary_obstack, 'N');
sprintf (buf, "%d", nrepeats);
obstack_grow (&temporary_obstack, buf, strlen (buf));
if (nrepeats > 9)
obstack_1grow (&temporary_obstack, '_');
}
else
obstack_1grow (&temporary_obstack, 'T');
sprintf (buf, "%d", tindex);
obstack_grow (&temporary_obstack, buf, strlen (buf));
if (tindex > 9)
obstack_1grow (&temporary_obstack, '_');
}
else
{
append_gpp_mangled_type (&temporary_obstack, argtype);
arg = TREE_CHAIN (arg);
}
}
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; )
{
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 0
else if (TREE_TYPE (TREE_TYPE (method_decl))
!= TREE_TYPE (TREE_TYPE (super_method)))
{
error_with_decl (method_decl,
"Method `%s' redefined with different return type");
error_with_decl (super_method,
"Overridden decl is here");
}
#endif
}
else if (! METHOD_FINAL (method_decl)
&& ! CLASS_FINAL (TYPE_NAME (this_class)))
{
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
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))
{
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)
{
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));
}
}
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; )
{
tree a = arglist;
tree argtype = TREE_VALUE (arg);
int tindex = 1;
if (TREE_CODE (argtype) == POINTER_TYPE)
{
/* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
while (a != arg && argtype != TREE_VALUE (a))
a = TREE_CHAIN (a), tindex++;
}
else
a = arg;
if (a != arg)
{
char buf[12];
int nrepeats = 0;
do
{
arg = TREE_CHAIN (arg); nrepeats++;
}
while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
if (nrepeats > 1)
{
obstack_1grow (&temporary_obstack, 'N');
sprintf (buf, "%d", nrepeats);
obstack_grow (&temporary_obstack, buf, strlen (buf));
if (nrepeats > 9)
obstack_1grow (&temporary_obstack, '_');
}
else
obstack_1grow (&temporary_obstack, 'T');
sprintf (buf, "%d", tindex);
obstack_grow (&temporary_obstack, buf, strlen (buf));
if (tindex > 9)
obstack_1grow (&temporary_obstack, '_');
}
else
{
append_gpp_mangled_type (&temporary_obstack, argtype);
arg = TREE_CHAIN (arg);
}
}
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; )
{
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 0
else if (TREE_TYPE (TREE_TYPE (method_decl))
!= TREE_TYPE (TREE_TYPE (super_method)))
{
error_with_decl (method_decl,
"Method `%s' redefined with different return type");
error_with_decl (super_method,
"Overridden decl is here");
}
#endif
}
else if (! METHOD_FINAL (method_decl)
&& ! CLASS_FINAL (TYPE_NAME (this_class))
&& dtable_count)
{
DECL_VINDEX (method_decl) = dtable_count;
dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
}
}
return dtable_count;
}
static tree registered_class = NULL_TREE;

View File

@ -910,6 +910,7 @@ expand_java_NEW (type)
{
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),
@ -1485,6 +1486,7 @@ expand_invoke (opcode, method_ref_index, nargs)
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),

View File

@ -112,6 +112,9 @@ extern tree main_class;
/* 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. */
@ -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 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));
@ -835,3 +840,10 @@ extern tree *type_map;
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))); \
}

View File

@ -61,7 +61,10 @@ tree current_class = NULL_TREE;
/* 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. */
@ -450,8 +453,7 @@ load_class (class_or_name, verbose)
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;
@ -459,6 +461,17 @@ load_class (class_or_name, verbose)
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. */
@ -494,10 +507,12 @@ load_class (class_or_name, verbose)
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)
@ -524,13 +539,16 @@ jcf_parse_source (jcf)
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 ();
}
@ -586,6 +604,11 @@ jcf_parse (jcf)
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 ();
}
@ -612,6 +635,8 @@ parse_class_file ()
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);

View File

@ -2342,7 +2342,8 @@ generate_classfile (clas, state)
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)
{

View File

@ -358,7 +358,12 @@ put_decl_node (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;

View File

@ -153,12 +153,12 @@ java_allocate_new_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->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;
}

View File

@ -4675,7 +4675,7 @@ void
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;
@ -4716,7 +4716,7 @@ java_parser_context_restore_global ()
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;
@ -5175,8 +5175,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
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);
@ -5310,7 +5311,7 @@ create_class (flags, id, super, interfaces)
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)
@ -5689,8 +5690,7 @@ method_header (flags, type, mdecl, throws)
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
@ -5928,6 +5928,7 @@ method_declarator (id, list)
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);
@ -5936,8 +5937,13 @@ method_declarator (id, list)
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))
@ -5963,7 +5969,7 @@ method_declarator (id, list)
}
/* 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;
@ -6081,11 +6087,7 @@ static void
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;
@ -6105,14 +6107,22 @@ reverse_jdep_list (ctxp)
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)
@ -6143,10 +6153,8 @@ register_incomplete_type (kind, wfl, decl, ptr)
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);
@ -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
safe_layout_class (class)
tree class;
@ -6220,20 +6232,18 @@ jdep_resolve_class (dep)
{
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;
}
@ -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
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)
@ -6495,20 +6506,49 @@ 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;
}
@ -6528,8 +6568,10 @@ resolve_no_layout (name, cl)
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)
@ -6537,6 +6579,7 @@ purify_type_name (name)
{
while (*name && *name == '[')
name++;
return name;
}
@ -6546,25 +6589,31 @@ static void
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;
@ -6572,7 +6621,7 @@ complete_class_report_errors (dep)
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:
@ -6662,8 +6711,11 @@ java_get_real_method_name (method_decl)
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);
@ -6728,7 +6780,8 @@ java_check_regular_methods (class_decl)
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))
@ -6877,11 +6930,15 @@ java_check_regular_methods (class_decl)
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;
@ -6893,6 +6950,7 @@ java_check_regular_methods (class_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);
}
}
@ -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
signature. Return a matching method only if their types differ. */
@ -7598,14 +7644,14 @@ source_start_java_method (fndecl)
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;
@ -7784,18 +7830,27 @@ add_stmt_to_compound (existing, type, stmt)
/* 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));
@ -7805,8 +7860,8 @@ java_layout_classes ()
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);
@ -7814,7 +7869,8 @@ java_layout_classes ()
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) =
@ -7823,12 +7879,8 @@ java_layout_classes ()
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;
@ -7837,6 +7889,12 @@ java_layout_classes ()
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. */
@ -8100,9 +8158,8 @@ java_expand_finals ()
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 ();
@ -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 */
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
@ -9817,6 +9875,7 @@ java_complete_tree (node)
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:
@ -9832,6 +9891,7 @@ java_complete_tree (node)
else
SWITCH_HAS_DEFAULT (nn) = 1;
TREE_TYPE (node) = void_type_node;
TREE_SIDE_EFFECTS (node) = 1;
CAN_COMPLETE_NORMALLY (node) = 1;
break;

View File

@ -147,10 +147,10 @@ extern tree stabilize_reference PROTO ((tree));
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. */
@ -589,13 +589,13 @@ struct parser_ctxt {
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 */
@ -609,30 +609,34 @@ struct parser_ctxt {
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 */
};
@ -803,7 +807,6 @@ void safe_layout_class PROTO ((tree));
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));

View File

@ -2070,7 +2070,7 @@ void
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;
@ -2111,7 +2111,7 @@ java_parser_context_restore_global ()
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;
@ -2570,8 +2570,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
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);
@ -3084,8 +3085,7 @@ method_header (flags, type, mdecl, throws)
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
@ -3323,6 +3323,7 @@ method_declarator (id, list)
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);
@ -3331,8 +3332,13 @@ method_declarator (id, list)
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))
@ -3358,7 +3364,7 @@ method_declarator (id, list)
}
/* 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;
@ -3476,11 +3482,7 @@ static void
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;
@ -3500,14 +3502,22 @@ reverse_jdep_list (ctxp)
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)
@ -3538,10 +3548,8 @@ register_incomplete_type (kind, wfl, decl, ptr)
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);
@ -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
safe_layout_class (class)
tree class;
@ -3615,20 +3627,18 @@ jdep_resolve_class (dep)
{
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;
}
@ -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
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)
@ -3890,20 +3901,49 @@ 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;
}
@ -3923,8 +3963,8 @@ resolve_no_layout (name, cl)
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)
@ -3941,25 +3981,31 @@ static void
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;
@ -3967,7 +4013,7 @@ complete_class_report_errors (dep)
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:
@ -4057,8 +4103,11 @@ java_get_real_method_name (method_decl)
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);
@ -4123,7 +4172,8 @@ java_check_regular_methods (class_decl)
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))
@ -4272,11 +4322,15 @@ java_check_regular_methods (class_decl)
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;
@ -4288,6 +4342,7 @@ java_check_regular_methods (class_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);
}
}
@ -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
signature. Return a matching method only if their types differ. */
@ -4993,14 +5036,14 @@ source_start_java_method (fndecl)
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;
@ -5179,18 +5222,27 @@ add_stmt_to_compound (existing, type, stmt)
/* 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));
@ -5200,8 +5252,8 @@ java_layout_classes ()
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);
@ -5209,7 +5261,8 @@ java_layout_classes ()
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) =
@ -5218,12 +5271,8 @@ java_layout_classes ()
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;
@ -5232,6 +5281,12 @@ java_layout_classes ()
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. */
@ -5495,9 +5550,8 @@ java_expand_finals ()
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 ();
@ -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 */
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