[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:
parent
333a9f0aaf
commit
23a79c6192
@ -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.
|
||||
|
415
gcc/java/class.c
415
gcc/java/class.c
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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))); \
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
226
gcc/java/parse.c
226
gcc/java/parse.c
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
219
gcc/java/parse.y
219
gcc/java/parse.y
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user