Commit 5e942c50 by Alexandre Petit-Bianco Committed by Alexandre Petit-Bianco

class.c (is_compiled_class): Call safe_layout_class for class compiled from source.

Tue Nov 10 12:34:03 1998  Alexandre Petit-Bianco  <apbianco@cygnus.com>
	* class.c (is_compiled_class): Call safe_layout_class for class
 	compiled from source.
	* conver.h (convert_to_integer, convert_to_real,
 	convert_to_pointer): Added prototypes.
	* decl.c (init_decl_processing): Non longer push the decls of
 	`methodtable', `constants', `Class', `Field', `dispatchTable'
 	`jexception' and `Method'.
	* expr.c (build_invokeinterface): New function.
	(expand_invoke): static variable CLASS_IDENT now in
 	build_invokeinterface. Use build_invokeinterface.
	(expand_java_field_op): Moved code to inline
 	java.lang.PRIMTYPE.TYPE into a function.
	(build_primtype_type_ref): New function.
	* java-tree.def (INSTANCEOF_EXPR): New tree code.
	* java-tree.h (CLASS_METHOD_CHECKED_P, METHOD_DEPRECATED,
 	FIELD_DEPRECATED, CLASS_DEPRECATED): New flag macros.
	(DECL_CONSTRUCTOR_P): Fixed typo in comment.
	(DECL_LOCAL_STATIC_VALUE): New macro.
	(build_invokeinterface, build_primtype_type_ref): New function
 	prototypes.
	(java_parse_abort_on_error): Macro rewritten.
	* jcf-parse.c (current_method): Add comment to declaration.
	(parse_zip_file_entries, process_zip_dir, void parse_source_file):
 	Function prototypes fixed.
	(jcf_parse_source): push/pop parser context. save/restore global.
	(parse_source_file): Fixed leading comment. Now take a
 	IDENTIFIER_NODE as an argument. Doesn't check methods, layout
 	classes and pop the parser context anymore.
	(yyparse): Push parser context, save globals, parse the source
 	file, restore globals and pop the parser context when processing a
 	source file.
	* jcf.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG define.
	* lex.c (java_parse_doc_section): New function.
	(java_lex): Call java_parse_doc_section when appropriate. Build an
 	operator around INSTANCEOF_TK.
	* lex.h (java_lineterminator, java_sprint_unicode,
 	java_unicode_2_utf8, java_lex_error, java_store_unicode):
 	Prototypes rewritten.
	(java_parse_escape_sequence, java_letter_or_digit_p,
 	java_parse_doc_section, java_parse_end_comment, java_get_unicode,
 	java_read_unicode, java_store_unicode, java_read_char,
 	java_allocate_new_line, java_unget_unicode, java_sneak_unicode):
 	Added function prototypes.
	* parse.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG
 	define.
	(JNULLP_TYPE_P, CHECK_METHODS, CHECK_DEPRECATED, REGISTER_IMPORT):
 	New macros
	(struct parser_ctxt): New fields: deprecated,
 	current_parsed_class_un, gclass_list.
	(fix_method_argument_names, issue_warning_error_from_context,
 	resolve_package, lookup_package_type): New function prototypes.
	(resolve_expression_name): Fixed function prototype.
	(find_applicable_accessible_methods_list): Fixed indentation, added
	extra argument in prototype.
	(check_final_assignment, build_null_of_type, check_deprecation,
 	check_method_redefinition, reset_method_name,
 	java_check_regular_methods, java_check_abstract_methods,
 	maybe_build_primttype_type_ref): New function prototype.
	* parse.y (conver.h): Include.
	(INSTANCEOF_TK): Tagged <operator>.
	(single_type_import_declaration): Use REGISTER_IMPORT macro.
	(relational_expression:): Build binop for instanceof.
	(java_push_parser_context): Remember ctxp->gclass_list across
 	contexts.
	(java_pop_parser_context): Simply return if no context
 	exists. Remember gclass_list across contexts.
	(issue_warning_error_from_context): New function.
	(parse_error_context): Don't setup ctxp->elc here. Call
 	issue_warning_error_from_context instead.
	(parse_warning_context): Likewise.
	(maybe_create_class_interface_decl): Removed DECL_ARTIFICIAL
 	setup. Link new class/interface to ctxp->gclass_list.
	(add_superinterfaces): Register interface as incomplete if not
 	loaded.
	(create_class): Remember class unqualified name in
 	ctxp->current_parsed_class_un. Check class deprecation.
	(register_fields): Check field deprecation. Remember static final
 	field value in DECL_LOCAL_STATIC_VALUE. Changed comment in part
 	processing INIT.
	(method_header): New local variable ORIG_ARG. Use unqualified
 	current class name for check on constructor errors. Promote return
 	type if of record type. Argument list fix moved in
 	fix_method_argument_names, called here. Check method deprecation.
	(fix_method_argument_names): New function.
	(method_declarator): Promote record typed arguments.
	(safe_layout_class): Check class methods before layout.
	(java_complete_class): Compute field layout when patched.
	(do_resolve_class): Try to load class after having it renamed
 	after the package name.
	(get_printable_method_name): Use DECL_CONTEXT.
	(reset_method_name): New function.
	(check_method_redefinition): Use reset_method_name.
	(java_check_regular_methods): New local variable
 	SAVED_FOUND_WFL. Temporarily reinstall overriding/hiding method
 	names for error report. Check for compile-time error when method
 	found has default (package) access.
	(java_check_abstract_methods): Now takes an interface DECL node as
 	an argument. Also reinstall real name on unchecked
 	overriding/hiding methods for error report.
	(java_check_methods): Fixed leading comment. Get classes to verify
 	from ctxp->gclass_list. Use CHECK_METHODS macro and set
 	CLASS_METHOD_CHECKED_P on class verification.
	(lookup_java_method2): Get real method name if necessary.
	(find_in_imports): Don't check package class access here.
	(resolve_package, lookup_package_type): New functions.
	(java_layout_classes): Fixed leading comment. Take classes to be
 	laid out from ctxp->gclass_list.
	(java_complete_expand_methods): Don't expand native and abstract
 	methods.
	(java_expand_classes): New function.
	(resolve_expression_name): Use additional argument ORIG.  Retrieve
 	values of static final field of primitive types.
	(resolve_field_access): Handles static final field of promotive
 	type.
	(resolve_qualified_expression_name): Handle STRING_CST as
 	primaries and package name resolution. Check deprecation on found
 	decls. Set where_found and type_found on non static field resolved
 	during qualification. Layout non primitive field decl types.
	(check_deprecation): New function.
	(maybe_access_field): Simplified.
	(patch_method_invocation_stmt): Local variable CLASS_TYPE
 	removed. Reverse method's argument when primary is a type. Don't
 	use CLASS_TYPE to report problems, use IDENTIFIER_WFL
 	instead. Include abstract class in the list of class searchable
 	for constructors. Use DECL_CONTEXT of found method for access
 	checks. Check method deprecation.
	(patch_invoke): Pay extra care to NEW_CLASS_EXPR type call when
 	converting arguments. Handle INVOKE_INTERFACE.
	(lookup_method_invoke): Search constructor using existing
 	infrastructure (don't rely on lookup_java_constructor anymore).
	(find_applicable_accessible_methods_list): Extra argument flag
 	LC. Now include constructor in the search.
	(qualify_ambiguous_name): Conditional expression are primaries.
	(not_initialized_as_it_should_p): static final are always
 	initialized.
	(java_complete_tree): Pass extra NULL argument to
 	resolve_expression_name. Stricter test to carry on patching
 	assignments. New case for INSTANCEOF_EXPR.
	(complete_function_arguments): Inline PRIMTYPE.TYPE read access.
	(check_final_assignment, maybe_build_primttype_type_ref): New
 	functions.
	(patch_assignment): Detect resolved static finals and carry normal
 	assignment error check on them. Inline PRIMTYPE.TYPE read access.
	(try_builtin_assignconv): Access constant 0 on all primitive
 	types.
	(valid_builtin_assignconv_identity_widening_p): Accept identical
 	types. Accept all promoted type on int type.
	(valid_ref_assignconv_cast_p): Accept a null pointer to be
 	assigned to a reference.
	(valid_method_invocation_conversion_p): Accept to check null
 	pointers.
	(build_binop): Merge declaration and initialization of local
 	variable BINOP.
	(patch_binop): New case for INSTANCEOF_EXPR. NE_EXPR to accept all
 	numeric types. Improved validity test for qualify operators on
 	references.
	(patch_unaryop): Broadened rejection test for PREDECREMENT_EXPR
 	and PREINCREMENT_EXPR. Also detect resolved static finals of a
 	primitive type and issue the appropriate error message.
	(resolve_type_during_patch): Mark class loaded when resolved.
	(patch_cast): Allow null to be cased to reference types.
	(build_null_of_type): New function.
	(patch_array_ref): Handle array on references correctly.
	(patch_return): Removed unused local variable MODIFY. Force
 	boolean to be returned as integers. Allows null to be returned by
 	a function returning a reference.
	* typeck.c (convert_to_integer, convert_to_real,
 	convert_to_pointer): Prototypes moved to convert.h
	(lookup_argument_method): Use method real name, if necessary.
This improves method checking, gets rid of a cross file type
dependency bug and does a more robust job at laying out classes when
necessary. It unifies the regular methods and constructors lookup. It
implements the `instanceof' operator and interface method
invocations. It also fixes random bugs.

From-SVN: r23599
parent fbd2bdda
Tue Nov 10 12:34:03 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
* class.c (is_compiled_class): Call safe_layout_class for class
compiled from source.
* conver.h (convert_to_integer, convert_to_real,
convert_to_pointer): Added prototypes.
* decl.c (init_decl_processing): Non longer push the decls of
`methodtable', `constants', `Class', `Field', `dispatchTable'
`jexception' and `Method'.
* expr.c (build_invokeinterface): New function.
(expand_invoke): static variable CLASS_IDENT now in
build_invokeinterface. Use build_invokeinterface.
(expand_java_field_op): Moved code to inline
java.lang.PRIMTYPE.TYPE into a function.
(build_primtype_type_ref): New function.
* java-tree.def (INSTANCEOF_EXPR): New tree code.
* java-tree.h (CLASS_METHOD_CHECKED_P, METHOD_DEPRECATED,
FIELD_DEPRECATED, CLASS_DEPRECATED): New flag macros.
(DECL_CONSTRUCTOR_P): Fixed typo in comment.
(DECL_LOCAL_STATIC_VALUE): New macro.
(build_invokeinterface, build_primtype_type_ref): New function
prototypes.
(java_parse_abort_on_error): Macro rewritten.
* jcf-parse.c (current_method): Add comment to declaration.
(parse_zip_file_entries, process_zip_dir, void parse_source_file):
Function prototypes fixed.
(jcf_parse_source): push/pop parser context. save/restore global.
(parse_source_file): Fixed leading comment. Now take a
IDENTIFIER_NODE as an argument. Doesn't check methods, layout
classes and pop the parser context anymore.
(yyparse): Push parser context, save globals, parse the source
file, restore globals and pop the parser context when processing a
source file.
* jcf.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG define.
* lex.c (java_parse_doc_section): New function.
(java_lex): Call java_parse_doc_section when appropriate. Build an
operator around INSTANCEOF_TK.
* lex.h (java_lineterminator, java_sprint_unicode,
java_unicode_2_utf8, java_lex_error, java_store_unicode):
Prototypes rewritten.
(java_parse_escape_sequence, java_letter_or_digit_p,
java_parse_doc_section, java_parse_end_comment, java_get_unicode,
java_read_unicode, java_store_unicode, java_read_char,
java_allocate_new_line, java_unget_unicode, java_sneak_unicode):
Added function prototypes.
* parse.h (VERBOSE_SKELETON): Replaces SOURCE_FRONTEND_DEBUG
define.
(JNULLP_TYPE_P, CHECK_METHODS, CHECK_DEPRECATED, REGISTER_IMPORT):
New macros
(struct parser_ctxt): New fields: deprecated,
current_parsed_class_un, gclass_list.
(fix_method_argument_names, issue_warning_error_from_context,
resolve_package, lookup_package_type): New function prototypes.
(resolve_expression_name): Fixed function prototype.
(find_applicable_accessible_methods_list): Fixed indentation, added
extra argument in prototype.
(check_final_assignment, build_null_of_type, check_deprecation,
check_method_redefinition, reset_method_name,
java_check_regular_methods, java_check_abstract_methods,
maybe_build_primttype_type_ref): New function prototype.
* parse.y (conver.h): Include.
(INSTANCEOF_TK): Tagged <operator>.
(single_type_import_declaration): Use REGISTER_IMPORT macro.
(relational_expression:): Build binop for instanceof.
(java_push_parser_context): Remember ctxp->gclass_list across
contexts.
(java_pop_parser_context): Simply return if no context
exists. Remember gclass_list across contexts.
(issue_warning_error_from_context): New function.
(parse_error_context): Don't setup ctxp->elc here. Call
issue_warning_error_from_context instead.
(parse_warning_context): Likewise.
(maybe_create_class_interface_decl): Removed DECL_ARTIFICIAL
setup. Link new class/interface to ctxp->gclass_list.
(add_superinterfaces): Register interface as incomplete if not
loaded.
(create_class): Remember class unqualified name in
ctxp->current_parsed_class_un. Check class deprecation.
(register_fields): Check field deprecation. Remember static final
field value in DECL_LOCAL_STATIC_VALUE. Changed comment in part
processing INIT.
(method_header): New local variable ORIG_ARG. Use unqualified
current class name for check on constructor errors. Promote return
type if of record type. Argument list fix moved in
fix_method_argument_names, called here. Check method deprecation.
(fix_method_argument_names): New function.
(method_declarator): Promote record typed arguments.
(safe_layout_class): Check class methods before layout.
(java_complete_class): Compute field layout when patched.
(do_resolve_class): Try to load class after having it renamed
after the package name.
(get_printable_method_name): Use DECL_CONTEXT.
(reset_method_name): New function.
(check_method_redefinition): Use reset_method_name.
(java_check_regular_methods): New local variable
SAVED_FOUND_WFL. Temporarily reinstall overriding/hiding method
names for error report. Check for compile-time error when method
found has default (package) access.
(java_check_abstract_methods): Now takes an interface DECL node as
an argument. Also reinstall real name on unchecked
overriding/hiding methods for error report.
(java_check_methods): Fixed leading comment. Get classes to verify
from ctxp->gclass_list. Use CHECK_METHODS macro and set
CLASS_METHOD_CHECKED_P on class verification.
(lookup_java_method2): Get real method name if necessary.
(find_in_imports): Don't check package class access here.
(resolve_package, lookup_package_type): New functions.
(java_layout_classes): Fixed leading comment. Take classes to be
laid out from ctxp->gclass_list.
(java_complete_expand_methods): Don't expand native and abstract
methods.
(java_expand_classes): New function.
(resolve_expression_name): Use additional argument ORIG. Retrieve
values of static final field of primitive types.
(resolve_field_access): Handles static final field of promotive
type.
(resolve_qualified_expression_name): Handle STRING_CST as
primaries and package name resolution. Check deprecation on found
decls. Set where_found and type_found on non static field resolved
during qualification. Layout non primitive field decl types.
(check_deprecation): New function.
(maybe_access_field): Simplified.
(patch_method_invocation_stmt): Local variable CLASS_TYPE
removed. Reverse method's argument when primary is a type. Don't
use CLASS_TYPE to report problems, use IDENTIFIER_WFL
instead. Include abstract class in the list of class searchable
for constructors. Use DECL_CONTEXT of found method for access
checks. Check method deprecation.
(patch_invoke): Pay extra care to NEW_CLASS_EXPR type call when
converting arguments. Handle INVOKE_INTERFACE.
(lookup_method_invoke): Search constructor using existing
infrastructure (don't rely on lookup_java_constructor anymore).
(find_applicable_accessible_methods_list): Extra argument flag
LC. Now include constructor in the search.
(qualify_ambiguous_name): Conditional expression are primaries.
(not_initialized_as_it_should_p): static final are always
initialized.
(java_complete_tree): Pass extra NULL argument to
resolve_expression_name. Stricter test to carry on patching
assignments. New case for INSTANCEOF_EXPR.
(complete_function_arguments): Inline PRIMTYPE.TYPE read access.
(check_final_assignment, maybe_build_primttype_type_ref): New
functions.
(patch_assignment): Detect resolved static finals and carry normal
assignment error check on them. Inline PRIMTYPE.TYPE read access.
(try_builtin_assignconv): Access constant 0 on all primitive
types.
(valid_builtin_assignconv_identity_widening_p): Accept identical
types. Accept all promoted type on int type.
(valid_ref_assignconv_cast_p): Accept a null pointer to be
assigned to a reference.
(valid_method_invocation_conversion_p): Accept to check null
pointers.
(build_binop): Merge declaration and initialization of local
variable BINOP.
(patch_binop): New case for INSTANCEOF_EXPR. NE_EXPR to accept all
numeric types. Improved validity test for qualify operators on
references.
(patch_unaryop): Broadened rejection test for PREDECREMENT_EXPR
and PREINCREMENT_EXPR. Also detect resolved static finals of a
primitive type and issue the appropriate error message.
(resolve_type_during_patch): Mark class loaded when resolved.
(patch_cast): Allow null to be cased to reference types.
(build_null_of_type): New function.
(patch_array_ref): Handle array on references correctly.
(patch_return): Removed unused local variable MODIFY. Force
boolean to be returned as integers. Allows null to be returned by
a function returning a reference.
* typeck.c (convert_to_integer, convert_to_real,
convert_to_pointer): Prototypes moved to convert.h
(lookup_argument_method): Use method real name, if necessary.
1998-10-30 Tom Tromey <tromey@cygnus.com>
* class.c (build_class_ref): Changed name of primitive classes to
......
......@@ -1153,7 +1153,12 @@ is_compiled_class (class)
if (flag_assume_compiled)
{
if (!CLASS_LOADED_P (class))
load_class (class, 1);
{
if (CLASS_FROM_SOURCE_P (class))
safe_layout_class (class);
else
load_class (class, 1);
}
return 1;
}
......
/* Definition of conversion functions.
Copyright (C) 1993 Free Software Foundation, Inc.
......@@ -22,3 +23,6 @@ Boston, MA 02111-1307, USA. */
extern tree convert_to_boolean PROTO ((tree, tree));
extern tree convert_to_char PROTO ((tree, tree));
extern tree convert_to_integer PROTO ((tree type, tree expr));
extern tree convert_to_real PROTO ((tree type, tree expr));
extern tree convert_to_pointer PROTO ((tree type, tree expr));
......@@ -527,8 +527,7 @@ init_decl_processing ()
methodtable_type = make_node (RECORD_TYPE);
layout_type (methodtable_type);
pushdecl (build_decl (TYPE_DECL, get_identifier ("methodtable"),
methodtable_type));
build_decl (TYPE_DECL, get_identifier ("methodtable"), methodtable_type);
methodtable_ptr_type = build_pointer_type (methodtable_type);
TYPE_identifier_node = get_identifier ("TYPE");
......@@ -554,8 +553,7 @@ init_decl_processing ()
PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node);
PUSH_FIELD (constants_type_node, field, "data", ptr_type_node);
FINISH_RECORD (constants_type_node);
pushdecl (build_decl (TYPE_DECL, get_identifier ("constants"),
constants_type_node));
build_decl (TYPE_DECL, get_identifier ("constants"), constants_type_node);
access_flags_type_node = unsigned_short_type_node;
......@@ -606,7 +604,7 @@ init_decl_processing ()
FIELD_PRIVATE (t) = 1;
push_super_field (class_type_node, object_type_node);
FINISH_RECORD (class_type_node);
pushdecl (build_decl (TYPE_DECL, get_identifier ("Class"), class_type_node));
build_decl (TYPE_DECL, get_identifier ("Class"), class_type_node);
field_info_union_node = make_node (UNION_TYPE);
PUSH_FIELD (field_info_union_node, field, "boffset", int_type_node);
......@@ -623,7 +621,7 @@ init_decl_processing ()
PUSH_FIELD (field_type_node, field, "info", field_info_union_node);
FINISH_RECORD (field_type_node);
CLASS_LOADED_P (field_type_node) = 1;
pushdecl (build_decl (TYPE_DECL, get_identifier ("Field"), field_type_node));
build_decl (TYPE_DECL, get_identifier ("Field"), field_type_node);
one_elt_array_domain_type = build_index_type (integer_one_node);
nativecode_ptr_array_type_node
......@@ -632,7 +630,7 @@ init_decl_processing ()
PUSH_FIELD (dtable_type, field, "class", class_ptr_type);
PUSH_FIELD (dtable_type, field, "methods", nativecode_ptr_array_type_node);
FINISH_RECORD (dtable_type);
pushdecl (build_decl (TYPE_DECL, get_identifier ("dispatchTable"), dtable_type));
build_decl (TYPE_DECL, get_identifier ("dispatchTable"), dtable_type);
#define jint_type int_type_node
#define jint_ptr_type ptr_type_node
......@@ -643,7 +641,7 @@ init_decl_processing ()
PUSH_FIELD (jexception_type, field, "handler_pc", ptr_type_node);
PUSH_FIELD (jexception_type, field, "catch_type", class_ptr_type);
FINISH_RECORD (jexception_type);
pushdecl (build_decl (TYPE_DECL, get_identifier ("jexception"), field_type_node));
build_decl (TYPE_DECL, get_identifier ("jexception"), field_type_node);
jexception_ptr_type = build_pointer_type (jexception_type);
lineNumberEntry_type = make_node (RECORD_TYPE);
......@@ -665,7 +663,7 @@ init_decl_processing ()
PUSH_FIELD (method_type_node, field, "ncode", nativecode_ptr_type_node);
FINISH_RECORD (method_type_node);
CLASS_LOADED_P (method_type_node) = 1;
pushdecl (build_decl (TYPE_DECL, get_identifier ("Method"), method_type_node));
build_decl (TYPE_DECL, get_identifier ("Method"), method_type_node);
t = tree_cons (NULL_TREE, class_ptr_type,
build_tree_list (NULL_TREE, int_type_node));
......
......@@ -1431,6 +1431,32 @@ build_invokevirtual (dtable, method)
return func;
}
tree
build_invokeinterface (dtable, method_name, method_signature)
tree dtable, method_name, method_signature;
{
static tree class_ident = NULL_TREE;
tree lookup_arg;
/* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will
ensure that the selected method exists, is public and not
abstract nor static. */
if (class_ident == NULL_TREE)
class_ident = get_identifier ("class");
dtable = build1 (INDIRECT_REF, dtable_type, dtable);
dtable = build (COMPONENT_REF, class_ptr_type, dtable,
lookup_field (&dtable_type, class_ident));
lookup_arg = build_tree_list (NULL_TREE, build_utf8_ref (method_signature));
lookup_arg = tree_cons (NULL_TREE, dtable,
tree_cons (NULL_TREE, build_utf8_ref (method_name),
lookup_arg));
return build (CALL_EXPR, ptr_type_node,
build_address_of (soft_lookupinterfacemethod_node),
lookup_arg, NULL_TREE);
}
/* Expand one of the invoke_* opcodes.
OCPODE is the specific opcode.
METHOD_REF_INDEX is an index into the constant pool.
......@@ -1449,8 +1475,6 @@ expand_invoke (opcode, method_ref_index, nargs)
char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
tree call, func, method, arg_list, method_type;
static tree class_ident = NULL_TREE;
if (! CLASS_LOADED_P (self_type))
{
load_class (self_type, 1);
......@@ -1522,30 +1546,7 @@ expand_invoke (opcode, method_ref_index, nargs)
if (opcode == OPCODE_invokevirtual)
func = build_invokevirtual (dtable, method);
else
{
/* We expand invokeinterface here.
_Jv_LookupInterfaceMethod() will ensure that the selected
method exists, is public and not abstract nor static. */
tree lookup_arg;
if (class_ident == NULL_TREE)
class_ident = get_identifier ("class");
dtable = build1 (INDIRECT_REF, dtable_type, dtable);
dtable = build (COMPONENT_REF, class_ptr_type, dtable,
lookup_field (&dtable_type, class_ident));
lookup_arg = build_tree_list (NULL_TREE,
build_utf8_ref (method_signature));
lookup_arg = tree_cons (NULL_TREE, dtable,
tree_cons (NULL_TREE,
build_utf8_ref (method_name),
lookup_arg));
func = build (CALL_EXPR,
ptr_type_node,
build_address_of (soft_lookupinterfacemethod_node),
lookup_arg, NULL_TREE);
}
func = build_invokeinterface (dtable, method_name, method_signature);
}
func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
......@@ -1615,29 +1616,10 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
&& field_type == class_ptr_type
&& strncmp (self_name, "java.lang.", 10) == 0)
{
char *class_name = self_name+10;
tree typ;
if (strcmp(class_name, "Byte") == 0)
typ = byte_type_node;
else if (strcmp(class_name, "Short") == 0)
typ = short_type_node;
else if (strcmp(class_name, "Integer") == 0)
typ = int_type_node;
else if (strcmp(class_name, "Long") == 0)
typ = long_type_node;
else if (strcmp(class_name, "Float") == 0)
typ = float_type_node;
else if (strcmp(class_name, "Boolean") == 0)
typ = boolean_type_node;
else if (strcmp(class_name, "Char") == 0)
typ = char_type_node;
else if (strcmp(class_name, "Void") == 0)
typ = void_type_node;
else
typ = NULL_TREE;
if (typ != NULL_TREE)
tree typ = build_primtype_type_ref (self_name);
if (typ)
{
push_value (build_class_ref (typ));
push_value (typ);
return;
}
}
......@@ -1672,6 +1654,36 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
push_value (field_ref);
}
tree
build_primtype_type_ref (self_name)
char *self_name;
{
char *class_name = self_name+10;
tree typ;
if (strncmp(class_name, "Byte", 4) == 0)
typ = byte_type_node;
else if (strncmp(class_name, "Short", 5) == 0)
typ = short_type_node;
else if (strncmp(class_name, "Integer", 7) == 0)
typ = int_type_node;
else if (strncmp(class_name, "Long", 4) == 0)
typ = long_type_node;
else if (strncmp(class_name, "Float", 5) == 0)
typ = float_type_node;
else if (strncmp(class_name, "Boolean", 7) == 0)
typ = boolean_type_node;
else if (strncmp(class_name, "Char", 4) == 0)
typ = char_type_node;
else if (strncmp(class_name, "Void", 4) == 0)
typ = void_type_node;
else
typ = NULL_TREE;
if (typ != NULL_TREE)
return build_class_ref (typ);
else
return NULL_TREE;
}
void
load_type_state (label)
tree label;
......
......@@ -70,3 +70,10 @@ DEFTREECODE (THROW_EXPR, "throw", '1', 1)
Operand 1 is the then-value
Operand 2 is the else-value. */
DEFTREECODE (CONDITIONAL_EXPR, "?:", 'e', 3)
/* instanceof operator.
Operand 0 is the expression that is getting tested
Operand 1 is the class used for the test. */
DEFTREECODE (INSTANCEOF_EXPR, "instanceof", 'e', 2)
......@@ -56,6 +56,7 @@ struct JCF;
IS_CRAFTED_STRING_BUFFER_P (in CALL_EXPR)
Usage of TYPE_LANG_FLAG_?:
0: CLASS_METHOD_CHECKED_P (in RECORD_TYPE)
1: TYPE_ARRAY_P (in RECORD_TYPE).
2: CLASS_LOADED_P (in RECORD_TYPE).
3: CLASS_FROM_SOURCE_P (in RECORD_TYPE).
......@@ -64,6 +65,9 @@ struct JCF;
6: CLASS_HAS_FINIT_P (in RECORD_TYPE)
Usage of DECL_LANG_FLAG_?:
0: METHOD_DEPRECATED (in FUNCTION_DECL).
FIELD_DEPRECATED (in FIELD_DECL).
CLASS_DEPRECATED (in TYPE_DECL).
1: METHOD_PUBLIC (in FUNCTION_DECL).
FIELD_PUBLIC (in FIELD_DECL).
CLASS_PUBLIC (in TYPE_DECL).
......@@ -85,7 +89,7 @@ struct JCF;
LABEL_CHANGED (in LABEL_DECL)
CLASS_SUPER (in TYPE_DECL, ACC_SUPER flag)
INITIALIZED_P (in FIELD_DECL, VAR_DECL, PARM_DECL)
7: DECL_CONSTRUCTOR_P (in FUNCTION_DECL)
7: DECL_CONSTRUCTOR_P (in FUNCTION_DECL).
*/
/* True if the class whose TYPE_BINFO this is has a superclass.
......@@ -396,6 +400,9 @@ struct lang_identifier
slot_number in decl_map. */
#define DECL_LOCAL_SLOT_CHAIN(NODE) \
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->slot_chain)
/* For a static field seen from the parser, it holds its associated
value, the one returned when the field is looked up. */
#define DECL_LOCAL_STATIC_VALUE(NODE) DECL_LOCAL_SLOT_CHAIN (NODE)
/* DECL_LANG_SPECIFIC for FUNCTION_DECLs. */
struct lang_decl
......@@ -501,6 +508,7 @@ extern tree lookup_name PROTO ((tree));
extern tree build_known_method_ref PROTO ((tree, tree, tree, tree, tree));
extern tree build_class_init PROTO ((tree, tree));
extern tree build_invokevirtual PROTO ((tree, tree));
extern tree build_invokeinterface PROTO ((tree, tree, tree));
extern tree invoke_build_dtable PROTO ((int, tree));
extern tree build_field_ref PROTO ((tree, tree, tree));
extern void pushdecl_force_head PROTO ((tree));
......@@ -533,6 +541,7 @@ extern int alloc_name_constant PROTO ((int, tree));
extern void emit_register_classes PROTO (());
extern void lang_init_source PROTO ((int));
extern void write_classfile PROTO ((tree));
extern tree build_primtype_type_ref PROTO ((char *));
/* Access flags etc for a method (a FUNCTION_DECL): */
......@@ -570,6 +579,13 @@ extern void write_classfile PROTO ((tree));
#define CLASS_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL)
#define CLASS_SUPER(DECL) DECL_LANG_FLAG_6 (DECL)
/* @deprecated marker flag on methods, fields and classes */
#define METHOD_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL)
#define FIELD_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL)
#define CLASS_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL)
#define DECL_DEPRECATED(DECL) DECL_LANG_FLAG_0 (DECL)
/* The number of virtual methods in this class's dispatch table.
Does not include initial two dummy entries (one points to the
Class object, and the other is for G++ -fvtable-thunks compatibility). */
......@@ -657,6 +673,9 @@ extern tree *type_map;
/* FIXME this use of TREE_TYPE conflicts with something or other. */
#define TYPE_ARRAY_ELEMENT(ATYPE) TREE_TYPE(ATYPE)
/* True if methods in class TYPE have been checked. */
#define CLASS_METHOD_CHECKED_P(TYPE) TYPE_LANG_FLAG_0 (TYPE)
/* True if class TYPE has been loaded. */
#define CLASS_LOADED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE)
......@@ -795,13 +814,12 @@ extern tree *type_map;
/* Make the current function where this macro is invoked report error
messages and and return, if any */
#define java_parse_abort_on_error() \
{ \
extern int java_error_count; \
if (java_error_count) \
{ \
java_report_errors (); \
java_pop_parser_context (0); \
return; \
} \
#define java_parse_abort_on_error() \
{ \
extern int java_error_count; \
if (java_error_count) \
{ \
java_report_errors (); \
return; \
} \
}
......@@ -64,15 +64,14 @@ tree main_class = NULL_TREE;
/* The FIELD_DECL for the current field. */
static tree current_field = NULL_TREE;
/* The METHOD_DECL for the current method. */
static tree current_method = NULL_TREE;
/* Declarations of some functions used here. */
static tree give_name_to_class PROTO ((JCF *jcf, int index));
void parse_zip_file_entries (void);
void process_zip_dir();
/* Source file compilation declarations */
static void parse_source_file ();
void parse_zip_file_entries PROTO (());
void process_zip_dir PROTO (());
static void parse_source_file PROTO ((tree));
/* Handle "SourceFile" attribute. */
......@@ -506,14 +505,17 @@ int
jcf_parse_source (jcf)
JCF *jcf;
{
tree filename = get_identifier (input_filename);
java_parser_context_save_global ();
tree file;
java_parser_context_save_global ();
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 (IS_A_COMMAND_LINE_FILENAME_P (filename));
parse_source_file (file);
java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file));
java_parser_context_restore_global ();
}
......@@ -658,22 +660,16 @@ parse_class_file ()
lineno = save_lineno;
}
/* Parse a source file, as pointed by the current JCF. If PARSE_ONLY
is non zero, we're not parsing a file found on the command line and
we skip things related to code generation. */
/* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
static void
parse_source_file (parse_only)
int parse_only;
parse_source_file (file)
tree file;
{
int remember_for_generation;
tree filename = get_identifier (input_filename);
/* Mark the file as parsed */
HAS_BEEN_ALREADY_PARSED_P (filename) = 1;
HAS_BEEN_ALREADY_PARSED_P (file) = 1;
lang_init_source (1); /* Error msgs have no method prototypes */
java_push_parser_context ();
java_init_lex (); /* Initialize the parser */
java_parse_abort_on_error ();
java_parse (); /* Parse and build partial tree nodes. */
......@@ -682,17 +678,6 @@ parse_source_file (parse_only)
java_parse_abort_on_error ();
java_check_circular_reference (); /* Check on circular references */
java_parse_abort_on_error ();
java_check_methods (); /* Check the methods */
java_parse_abort_on_error ();
java_layout_classes ();
java_parse_abort_on_error ();
/* If only parsing, make sure that the currently parsed file isn't
also present in the argument list. If it's the case, remember
that we should generate it. */
remember_for_generation = !parse_only
|| IS_A_COMMAND_LINE_FILENAME_P (filename);
java_pop_parser_context (remember_for_generation);
}
int
......@@ -775,7 +760,11 @@ yyparse ()
parse_class_file ();
break;
case JCF_SOURCE:
parse_source_file (0); /* Parse and generate */
java_push_parser_context ();
java_parser_context_save_global ();
parse_source_file (name);
java_parser_context_restore_global ();
java_pop_parser_context (1);
break;
}
}
......
......@@ -706,7 +706,6 @@ emit_iinc (var, value, state)
static void
emit_load_or_store (var, opcode, state)
tree var;
int opcode;
struct jcf_partial *state;
{
tree type = TREE_TYPE (var);
......
......@@ -248,7 +248,7 @@ extern int jcf_unexpected_eof PROTO ((JCF*, int));
/* Debug macros, for the front end */
extern int quiet_flag;
#ifdef SOURCE_FRONTEND_DEBUG
#ifdef VERBOSE_SKELETON
#undef SOURCE_FRONTEND_DEBUG
#define SOURCE_FRONTEND_DEBUG(X) \
{if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} }
......
......@@ -22,11 +22,14 @@ Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc. */
DEFINE_LANG_NAME ("Java")
/* This is the contribution to the `lang_options' array in gcc.c for
java. */
/* CYGNUS LOCAL - the format of this file has been changed to
allow cc1 to implement --help. nickc/--help */
DEFINE_LANG_NAME ("Java")
{ "-fbounds-check", "" },
{ "-fno-bounds-check", "Disable automatic array bounds checking" },
{ "-fassume-compiled", "Make is_compiled_class return 1"},
......
......@@ -368,6 +368,62 @@ java_parse_end_comment ()
}
}
/* Parse the documentation section. Keywords must be at the beginning
of a documentation comment line (ignoring white space and any `*'
character). Parsed keyword(s): @DEPRECATED. */
static int
java_parse_doc_section (c)
unicode_t c;
{
int valid_tag = 0, seen_star;
while (JAVA_WHITE_SPACE_P (c) || (c == '*') || c == '\n')
{
switch (c)
{
case '*':
seen_star = 1;
break;
case '\n': /* ULT */
valid_tag = 1;
break;
default:
seen_star = 0;
}
c = java_get_unicode();
}
if (c == UEOF)
java_lex_error ("Comment not terminated at end of input", 0);
if (seen_star && (c == '/'))
return 1; /* Goto step1 in caller */
/* We're parsing @deprecated */
if (valid_tag && (c == '@'))
{
char tag [10];
int tag_index = 0;
while (tag_index < 10 && c != UEOF && c != ' ' && c != '\n')
{
c = java_get_unicode ();
tag [tag_index++] = c;
}
if (c == UEOF)
java_lex_error ("Comment not terminated at end of input", 0);
java_unget_unicode ();
tag [tag_index] = '\0';
if (!strcmp (tag, "deprecated"))
ctxp->deprecated = 1;
}
return 0;
}
/* This function to be used only by JAVA_ID_CHAR_P (), otherwise it
will return a wrong result. */
static int
......@@ -494,62 +550,8 @@ java_lex (java_lval)
{
if ((c = java_get_unicode ()) == '/')
goto step1; /* Empy documentation comment */
else
/* Parsing the documentation section. We're looking
for the @depracated pseudo keyword. the @deprecated
tag must be at the beginning of a doc comment line
(ignoring white space and any * character) */
{
int valid_tag = 0, seen_star;
while (JAVA_WHITE_SPACE_P (c) || (c == '*') || c == '\n')
{
switch (c)
{
case '*':
seen_star = 1;
break;
case '\n': /* ULT */
valid_tag = 1;
break;
default:
seen_star = 0;
}
c = java_get_unicode();
}
if (c == UEOF)
java_lex_error
("Comment not terminated at end of input", 0);
if (seen_star && (c == '/'))
goto step1; /* End of documentation */
if (valid_tag && (c == '@'))
{
char deprecated [10];
int deprecated_index = 0;
for (deprecated_index = 0, c = java_get_unicode ();
deprecated_index < 10 && c != UEOF;
c = java_get_unicode ())
deprecated [deprecated_index++] = c;
if (c == UEOF)
java_lex_error
("Comment not terminated at end of input", 0);
java_unget_unicode ();
deprecated [deprecated_index] = '\0';
if (!strcmp (deprecated, "deprecated"))
{
/* Set global flag to be checked by class. FIXME */
warning ("deprecated implementation found");
}
}
}
else if (java_parse_doc_section (c))
goto step1;
}
else
java_unget_unicode ();
......@@ -1206,6 +1208,7 @@ java_lex (java_lval)
case TRY_TK:
case CATCH_TK:
case THROW_TK:
case INSTANCEOF_TK:
BUILD_OPERATOR (kw->token);
default:
......
......@@ -35,13 +35,6 @@ extern int lineno;
/* A Unicode character, as read from the input file */
typedef unsigned short unicode_t;
/* Function declaration */
static int java_lineterminator ();
static char *java_sprint_unicode ();
static void java_unicode_2_utf8 ();
static void java_lex_error ();
static void java_store_unicode ();
/* Debug macro to print-out what we match */
#ifdef JAVA_LEX_DEBUG
#ifdef JAVA_LEX_DEBUG_CHAR
......@@ -511,4 +504,23 @@ static tree build_wfl_node ();
#define JAVA_READ_BUFFER 256
#define UEOF (unicode_t)0xffff
/* Function declaration */
static int java_lineterminator PROTO ((unicode_t));
static char *java_sprint_unicode PROTO ((struct java_line *, int));
static void java_unicode_2_utf8 PROTO ((unicode_t));
static void java_lex_error PROTO ((char *, int));
static int java_is_eol PROTO ((FILE *, int));
static void java_store_unicode PROTO ((struct java_line *, unicode_t, int));
static unicode_t java_parse_escape_sequence PROTO (());
static int java_letter_or_digit_p PROTO ((unicode_t));
static int java_parse_doc_section PROTO ((unicode_t));
static void java_parse_end_comment PROTO (());
static unicode_t java_get_unicode PROTO (());
static unicode_t java_read_unicode PROTO ((int, int *));
static void java_store_unicode PROTO ((struct java_line *, unicode_t, int));
static unicode_t java_read_char PROTO (());
static void java_allocate_new_line PROTO (());
static void java_unget_unicode PROTO (());
static unicode_t java_sneak_unicode PROTO (());
#endif
......@@ -70,7 +70,6 @@ void
emit_unicode_mangled_name (obstack, name, len)
struct obstack *obstack;
char *name;
int len;
{
unsigned char *ptr;
unsigned char *limit = (unsigned char *)name + len;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -47,7 +47,7 @@ extern tree stabilize_reference PROTO ((tree));
#define RULE( rule )
#endif
#ifdef SOURCE_FRONTEND_DEBUG
#ifdef VERBOSE_SKELETON
#undef SOURCE_FRONTEND_DEBUG
#define SOURCE_FRONTEND_DEBUG(X) \
{if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} }
......@@ -182,6 +182,8 @@ extern tree stabilize_reference PROTO ((tree));
|| (TREE_CODE (TYPE) == POINTER_TYPE \
&& TREE_CODE (TREE_TYPE (TYPE)) == \
RECORD_TYPE)))
#define JNULLP_TYPE_P(TYPE) ((TYPE) && (TREE_CODE (TYPE) == POINTER_TYPE) \
&& (TYPE) == TREE_TYPE (null_pointer_node))
/* Other predicate */
#define DECL_P(NODE) (NODE && (TREE_CODE (NODE) == PARM_DECL \
......@@ -523,6 +525,32 @@ static jdeplist *reverse_jdep_list ();
*ret_decl = NULL_TREE; \
return error_mark_node; \
}
/* Convenient macro to check. Assumes that CLASS is a CLASS_DECL. */
#define CHECK_METHODS(CLASS) \
{ \
if (CLASS_INTERFACE ((CLASS))) \
java_check_abstract_methods ((CLASS)); \
else \
java_check_regular_methods ((CLASS)); \
}
/* Using and reseting the @deprecated tag flag */
#define CHECK_DEPRECATED(DECL) \
{ \
if (ctxp->deprecated) \
DECL_DEPRECATED (DECL) = 1; \
ctxp->deprecated = 0; \
}
/* Register an impor */
#define REGISTER_IMPORT(WHOLE, NAME) \
{ \
IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P ((NAME)) = 1; \
node = build_tree_list ((WHOLE), (NAME)); \
TREE_CHAIN (node) = ctxp->import_list; \
ctxp->import_list = node; \
}
/* Parser context data structure. */
struct parser_ctxt {
......@@ -542,6 +570,7 @@ struct parser_ctxt {
int minus_seen; /* Integral literal overflow */
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
......@@ -561,7 +590,9 @@ struct parser_ctxt {
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 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 non_static_initialized; /* List of non static initialized fields */
......@@ -604,9 +635,11 @@ static void check_modifiers_consistency PROTO ((int));
static tree lookup_cl PROTO ((tree));
static tree lookup_java_method2 PROTO ((tree, tree, int));
static tree method_header PROTO ((int, tree, tree, tree));
static void fix_method_argument_names PROTO ((tree ,tree));
static tree method_declarator PROTO ((tree, tree));
static void parse_error_context VPROTO ((tree cl, char *msg, ...));
static void parse_warning_context VPROTO ((tree cl, char *msg, ...));
static void issue_warning_error_from_context PROTO ((tree, char *msg));
static tree parse_jdk1_1_error PROTO ((char *));
static void complete_class_report_errors PROTO ((jdep *));
static int process_imports PROTO ((void));
......@@ -614,6 +647,8 @@ static void read_import_dir PROTO ((tree));
static int find_in_imports_on_demand PROTO ((tree));
static int find_in_imports PROTO ((tree));
static int check_pkg_class_access PROTO ((tree, tree));
static tree resolve_package PROTO ((tree, tree *));
static tree lookup_package_type PROTO ((char *, int));
static tree resolve_class PROTO ((tree, tree, tree));
static tree do_resolve_class PROTO ((tree, tree, tree));
static void declare_local_variables PROTO ((int, tree, tree));
......@@ -623,7 +658,7 @@ static void expand_start_java_method PROTO ((tree));
static tree find_name_in_single_imports PROTO ((tree));
static void check_abstract_method_header PROTO ((tree));
static tree lookup_java_interface_method2 PROTO ((tree, tree));
static tree resolve_expression_name PROTO ((tree));
static tree resolve_expression_name PROTO ((tree, tree *));
static tree maybe_create_class_interface_decl PROTO ((tree, tree, tree));
static int check_class_interface_creation PROTO ((int, int, tree,
tree, tree, tree));
......@@ -633,7 +668,8 @@ static int breakdown_qualified PROTO ((tree *, tree *, tree));
static tree resolve_and_layout PROTO ((tree, tree));
static tree resolve_no_layout PROTO ((tree, tree));
static int invocation_mode PROTO ((tree, int));
static tree find_applicable_accessible_methods_list PROTO ((tree, tree, tree));
static tree find_applicable_accessible_methods_list PROTO ((int, tree,
tree, tree));
static tree find_most_specific_methods_list PROTO ((tree));
static int argument_types_convertible PROTO ((tree, tree));
static tree patch_invoke PROTO ((tree, tree, tree, int));
......@@ -654,12 +690,14 @@ static tree build_method_invocation PROTO ((tree, tree));
static tree build_new_invocation PROTO ((tree, tree));
static tree build_assignment PROTO ((int, int, tree, tree));
static tree build_binop PROTO ((enum tree_code, int, tree, tree));
static int check_final_assignment PROTO ((tree ,tree));
static tree patch_assignment PROTO ((tree, tree, tree ));
static tree patch_binop PROTO ((tree, tree, tree));
static tree build_unaryop PROTO ((int, int, tree));
static tree build_incdec PROTO ((int, int, tree, int));
static tree patch_unaryop PROTO ((tree, tree));
static tree build_cast PROTO ((int, tree, tree));
static tree build_null_of_type PROTO ((tree));
static tree patch_cast PROTO ((tree, tree));
static int valid_ref_assignconv_cast_p PROTO ((tree, tree, int));
static int valid_builtin_assignconv_identity_widening_p PROTO ((tree, tree));
......@@ -689,6 +727,7 @@ static tree maybe_access_field PROTO ((tree, tree, tree));
static int complete_function_arguments PROTO ((tree));
static int check_for_static_method_reference PROTO ((tree, tree, tree, tree, tree));
static int not_accessible_p PROTO ((tree, tree, int));
static void check_deprecation PROTO ((tree, tree));
static int class_in_current_package PROTO ((tree));
static tree build_if_else_statement PROTO ((int, tree, tree, tree));
static tree patch_if_else_statement PROTO ((tree));
......@@ -735,6 +774,11 @@ static tree create_artificial_method PROTO ((tree, int, tree, tree, tree));
static void start_artificial_method_body PROTO ((tree));
static void end_artificial_method_body PROTO ((tree));
static tree generate_field_initialization_code PROTO ((tree));
static int check_method_redefinition PROTO ((tree, tree));
static int reset_method_name PROTO ((tree));
static void java_check_regular_methods PROTO ((tree));
static void java_check_abstract_methods PROTO ((tree));
static tree maybe_build_primttype_type_ref PROTO ((tree, tree));
void safe_layout_class PROTO ((tree));
void java_complete_class PROTO ((void));
......
......@@ -67,6 +67,7 @@ definitions and other extensions. */
#include "lex.h"
#include "parse.h"
#include "zipfile.h"
#include "convert.h"
/* Number of error found so far. */
int java_error_count;
......@@ -248,7 +249,7 @@ static tree wfl_to_string = NULL_TREE;
%token <operator> BOOL_AND_TK AND_TK BOOL_OR_TK OR_TK INCR_TK PLUS_TK
%token <operator> DECR_TK MINUS_TK MULT_TK DIV_TK XOR_TK REM_TK NEQ_TK
%token <operator> NEG_TK REL_QM_TK REL_CL_TK NOT_TK LT_TK
%token <operator> OP_TK OSB_TK DOT_TK THROW_TK
%token <operator> OP_TK OSB_TK DOT_TK THROW_TK INSTANCEOF_TK
%type <operator> THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK
%type <operator> CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK
......@@ -409,14 +410,11 @@ single_type_import_declaration:
($2, "Ambiguous class: `%s' and `%s'",
IDENTIFIER_POINTER (name),
IDENTIFIER_POINTER (err));
else
REGISTER_IMPORT ($2, last_name)
}
else
{
IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (last_name) = 1;
node = build_tree_list ($2, last_name);
TREE_CHAIN (node) = ctxp->import_list;
ctxp->import_list = node;
}
REGISTER_IMPORT ($2, last_name);
}
| IMPORT_TK error
{yyerror ("Missing name"); RECOVER;}
......@@ -1936,6 +1934,7 @@ relational_expression:
$1, $3);
}
| relational_expression INSTANCEOF_TK reference_type
{ $$ = build_binop (INSTANCEOF_EXPR, $2.location, $1, $3); }
| relational_expression LT_TK error
{yyerror ("Missing term"); RECOVER;}
| relational_expression GT_TK error
......@@ -2098,7 +2097,10 @@ java_push_parser_context ()
new->next = ctxp;
ctxp = new;
if (ctxp->next)
ctxp->incomplete_class = ctxp->next->incomplete_class;
{
ctxp->incomplete_class = ctxp->next->incomplete_class;
ctxp->gclass_list = ctxp->next->gclass_list;
}
}
/* If the first file of a file list was a class file, no context
......@@ -2142,12 +2144,17 @@ java_pop_parser_context (generate)
int generate;
{
tree current;
struct parser_ctxt *toFree = ctxp;
struct parser_ctxt *next = ctxp->next;
struct parser_ctxt *toFree, *next;
if (!ctxp)
return;
toFree = ctxp;
next = ctxp->next;
if (next)
{
next->incomplete_class = ctxp->incomplete_class;
next->gclass_list = ctxp->gclass_list;
lineno = ctxp->lineno;
finput = ctxp->finput;
current_class = ctxp->current_class;
......@@ -2259,6 +2266,24 @@ parse_error (msg)
java_error (msg);
}
static void
issue_warning_error_from_context (cl, msg)
tree cl;
char *msg;
{
char *saved;
ctxp->elc.line = EXPR_WFL_LINENO (cl);
ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl));
/* We have a CL, that's a good reason for using it if it contains data */
saved = ctxp->filename;
if (TREE_CODE (cl) == EXPR_WITH_FILE_LOCATION && EXPR_WFL_FILENAME_NODE (cl))
ctxp->filename = EXPR_WFL_FILENAME (cl);
parse_error (msg);
ctxp->filename = saved;
}
/* Issue an error message at a current source line CL */
static void
......@@ -2269,6 +2294,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...))
char *msg;
#endif
char buffer [4096];
char *saved;
va_list ap;
VA_START (ap, msg);
......@@ -2279,10 +2305,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...))
vsprintf (buffer, msg, ap);
force_error = 1;
ctxp->elc.line = EXPR_WFL_LINENO (cl);
ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl));
parse_error (buffer);
issue_warning_error_from_context (cl, buffer);
force_error = 0;
}
......@@ -2296,6 +2319,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...))
char *msg;
#endif
char buffer [4096];
char *saved;
va_list ap;
VA_START (ap, msg);
......@@ -2306,10 +2330,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...))
vsprintf (buffer, msg, ap);
force_error = do_warning = 1;
ctxp->elc.line = EXPR_WFL_LINENO (cl);
ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl));
parse_error (buffer);
issue_warning_error_from_context (cl, buffer);
do_warning = force_error = 0;
}
......@@ -2562,9 +2583,7 @@ static tree
maybe_create_class_interface_decl (decl, qualified_name, cl)
tree decl, qualified_name, cl;
{
if (decl)
DECL_ARTIFICIAL (decl) = 1; /* FIXME */
else
if (!decl)
decl = push_class (make_class (), qualified_name);
/* Take care of the file and line business */
......@@ -2579,6 +2598,10 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
/* Link the declaration to the already seen ones */
TREE_CHAIN (decl) = ctxp->class_list;
ctxp->class_list = decl;
/* Create a new node in the global list */
ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
/* Install a new dependency list element */
create_jdep_list (ctxp);
......@@ -2602,10 +2625,11 @@ add_superinterfaces (decl, interface_list)
for (node = interface_list; node; node = TREE_CHAIN (node))
{
tree current = TREE_PURPOSE (node), interface_decl;
if ((interface_decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current))))
tree idecl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (current));
if (idecl && CLASS_LOADED_P (TREE_TYPE (idecl)))
{
if (!parser_check_super_interface (interface_decl, decl, current))
parser_add_interface (decl, interface_decl, current);
if (!parser_check_super_interface (idecl, decl, current))
parser_add_interface (decl, idecl, current);
}
else
register_incomplete_type (JDEP_INTERFACE,
......@@ -2673,6 +2697,7 @@ create_class (flags, id, super, interfaces)
class_id = parser_qualified_classname (id);
decl = IDENTIFIER_CLASS_VALUE (class_id);
ctxp->current_parsed_class_un = EXPR_WFL_NODE (id);
EXPR_WFL_NODE (id) = class_id;
/* Basic check: scope, redefinition, modifiers */
......@@ -2725,6 +2750,9 @@ create_class (flags, id, super, interfaces)
CLASS_COMPLETE_P (decl) = 1;
add_superinterfaces (decl, interfaces);
/* Eventually sets the @deprecated tag flag */
CHECK_DEPRECATED (decl);
return decl;
}
......@@ -2854,9 +2882,10 @@ register_fields (flags, type, variable_list)
}
/* Set lineno to the line the field was found and create a
declaration for it */
declaration for it. Eventually sets the @deprecated tag flag. */
lineno = EXPR_WFL_LINENO (cl);
field_decl = add_field (class_type, current_name, type, flags);
CHECK_DEPRECATED (field_decl);
/* Check if we must chain. */
if (must_chain)
......@@ -2873,12 +2902,16 @@ register_fields (flags, type, variable_list)
/* The field is declared static */
if (flags & ACC_STATIC)
{
/* FIXME */
if (flags & ACC_FINAL)
;
/* Otherwise, the field should be initialized in
<clinit>. This field is remembered so we can
generate <clinit> later. */
{
if (DECL_LANG_SPECIFIC (field_decl) == NULL)
DECL_LANG_SPECIFIC (field_decl) = (struct lang_decl *)
permalloc (sizeof (struct lang_decl_var));
DECL_LOCAL_STATIC_VALUE (field_decl) =
TREE_OPERAND (init, 1);
}
/* Otherwise, the field should be initialized in <clinit>.
This field is remembered so we can generate <clinit> later */
else
{
INITIALIZED_P (field_decl) = 1;
......@@ -2886,10 +2919,9 @@ register_fields (flags, type, variable_list)
ctxp->static_initialized = init;
}
}
/* A non-static field declared with an immediate
initialization is to be initialized in <init>, if
any. This field is remembered to be processed at the
time of the generation of <init>. */
/* A non-static field declared with an immediate initialization is
to be initialized in <init>, if any. This field is remembered
to be processed at the time of the generation of <init>. */
else
{
INITIALIZED_P (field_decl) = 1;
......@@ -2986,7 +3018,7 @@ method_header (flags, type, mdecl, throws)
tree meth = TREE_VALUE (mdecl);
tree id = TREE_PURPOSE (mdecl);
tree this_class = TREE_TYPE (ctxp->current_parsed_class);
tree meth_name, returned_type, current;
tree meth_name, returned_type, current, orig_arg;
int saved_lineno;
int constructor_ok = 0;
......@@ -3014,7 +3046,7 @@ method_header (flags, type, mdecl, throws)
int ec = java_error_count;
/* 8.6: Constructor declarations: we might be trying to define a
method without specifying a return type. */
if (EXPR_WFL_NODE (id) != DECL_NAME (ctxp->current_parsed_class))
if (EXPR_WFL_NODE (id) != ctxp->current_parsed_class_un)
parse_error_context
(id, "Invalid method declaration, return type required");
/* 8.6.3: Constructor modifiers */
......@@ -3077,7 +3109,11 @@ method_header (flags, type, mdecl, throws)
}
}
else
TREE_TYPE (meth) = type;
{
if (TREE_CODE (type) == RECORD_TYPE)
type = promote_type (type);
TREE_TYPE (meth) = type;
}
saved_lineno = lineno;
/* When defining an abstract or interface method, the curly
......@@ -3086,6 +3122,9 @@ method_header (flags, type, mdecl, throws)
lineno = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 :
EXPR_WFL_LINENO (id));
/* Remember the original argument list */
orig_arg = TYPE_ARG_TYPES (meth);
if (patch_stage) /* includes ret type and/or all args */
{
jdep *jdep;
......@@ -3101,28 +3140,15 @@ method_header (flags, type, mdecl, throws)
register_incomplete_type (JDEP_METHOD_END, NULL_TREE, meth, NULL_TREE);
}
else
{
tree signature = build_java_signature (meth);
tree arg, orig_arg;
/* Save original argument list, including argument's names */
orig_arg = TYPE_ARG_TYPES (meth);
/* Add the method to its class */
meth = add_method (this_class, flags, meth_name, signature);
/* Fix the method argument list so we have the argument name
information */
arg = TYPE_ARG_TYPES (TREE_TYPE (meth));
if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE)
{
TREE_PURPOSE (arg) = this_identifier_node;
arg = TREE_CHAIN (arg);
}
while (orig_arg)
{
TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg);
orig_arg = TREE_CHAIN (orig_arg);
arg = TREE_CHAIN (arg);
}
}
meth = add_method (this_class, flags, meth_name,
build_java_signature (meth));
/* Fix the method argument list so we have the argument name
information */
fix_method_argument_names (orig_arg, meth);
/* Register the parameter number and re-install the current line
number */
DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1;
lineno = saved_lineno;
......@@ -3157,9 +3183,30 @@ method_header (flags, type, mdecl, throws)
if (constructor_ok)
DECL_CONSTRUCTOR_P (meth) = 1;
/* Eventually set the @deprecated tag flag */
CHECK_DEPRECATED (meth);
return meth;
}
static void
fix_method_argument_names (orig_arg, meth)
tree orig_arg, meth;
{
tree arg = TYPE_ARG_TYPES (TREE_TYPE (meth));
if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE)
{
TREE_PURPOSE (arg) = this_identifier_node;
arg = TREE_CHAIN (arg);
}
while (orig_arg)
{
TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg);
orig_arg = TREE_CHAIN (orig_arg);
arg = TREE_CHAIN (arg);
}
}
/* Complete the method declaration with METHOD_BODY. */
static void
......@@ -3305,6 +3352,9 @@ 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);
/* Check redefinition */
for (already = arg_types; already; already = TREE_CHAIN (already))
if (TREE_PURPOSE (already) == name)
......@@ -3564,14 +3614,20 @@ void
safe_layout_class (class)
tree class;
{
tree list;
tree save_current_class = current_class;
char *save_input_filename = input_filename;
int save_lineno = lineno;
push_obstacks (&permanent_obstack, &permanent_obstack);
if (!CLASS_METHOD_CHECKED_P (class))
CHECK_METHODS (TYPE_NAME (class));
CLASS_METHOD_CHECKED_P (class) = 1;
layout_class (class);
pop_obstacks ();
current_class = save_current_class;
input_filename = save_input_filename;
lineno = save_lineno;
......@@ -3655,6 +3711,8 @@ java_complete_class ()
field_type = promote_type (field_type);
pop_obstacks ();
TREE_TYPE (field_decl) = field_type;
DECL_ALIGN (field_decl) = 0;
layout_decl (field_decl, 0);
SOURCE_FRONTEND_DEBUG
(("Completed field/var decl `%s' with `%s'",
IDENTIFIER_POINTER (DECL_NAME (field_decl)),
......@@ -3817,7 +3875,6 @@ do_resolve_class (class_type, decl, cl)
/* 2- And check for the type in the current compilation unit. If it fails,
try with a name qualified with the package name if appropriate. */
if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
{
if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
......@@ -3830,6 +3887,8 @@ do_resolve_class (class_type, decl, cl)
if (!QUALIFIED_P (TYPE_NAME (class_type)) && ctxp->package)
TYPE_NAME (class_type) = merge_qualified_name (ctxp->package,
TYPE_NAME (class_type));
if (!(new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
load_class (TYPE_NAME (class_type), 0);
if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
{
if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
......@@ -3984,9 +4043,7 @@ get_printable_method_name (decl)
if (DECL_CONSTRUCTOR_P (decl))
{
name = DECL_NAME (decl);
DECL_NAME (decl) =
DECL_NAME (ctxp->current_parsed_class ?
ctxp->current_parsed_class : current_class);
DECL_NAME (decl) = DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)));
}
to_return = lang_printable_name (decl, 0);
......@@ -3996,6 +4053,28 @@ get_printable_method_name (decl)
return to_return;
}
/* Reinstall the proper DECL_NAME on METHOD. Return 0 if the method
nevertheless needs to be verfied, 1 otherwise. */
static int
reset_method_name (method)
tree method;
{
if (DECL_NAME (method) != clinit_identifier_node
&& DECL_NAME (method) != finit_identifier_node)
{
/* NAME is just the plain name when Object is being defined */
if (DECL_CONTEXT (method) != object_type_node)
DECL_NAME (method) =
(DECL_CONSTRUCTOR_P (method) ? init_identifier_node :
(TREE_CODE (DECL_NAME (method)) == EXPR_WITH_FILE_LOCATION ?
EXPR_WFL_NODE (DECL_NAME (method)) : DECL_NAME (method)));
return 0;
}
else
return 1;
}
/* Track method being redefined inside the same class. As a side
effect, set DECL_NAME to an IDENTIFIER (prior entering this
function it's a FWL, so we can track errors more accurately */
......@@ -4009,19 +4088,14 @@ check_method_redefinition (class, method)
tree sig = TYPE_LANG_SPECIFIC (TREE_TYPE (method))->signature;
/* decl name of artificial <clinit> and <finit> doesn't need to be fixed and
checked */
if (DECL_NAME (method) != clinit_identifier_node
&& DECL_NAME (method) != finit_identifier_node)
{
/* NAME is just the plain name when Object is being defined */
if (class != object_type_node)
name = DECL_NAME (method) = (DECL_CONSTRUCTOR_P (method) ?
init_identifier_node :
EXPR_WFL_NODE (DECL_NAME (method)));
else
name = DECL_NAME (method);
}
else
/* Reset the method name before running the check. If it returns 1,
the method doesn't need to be verified with respect to method
redeclaration and we return 0 */
if (reset_method_name (method))
return 0;
name = DECL_NAME (method);
for (redef = TYPE_METHODS (class); redef; redef = TREE_CHAIN (redef))
{
......@@ -4049,20 +4123,26 @@ static void
java_check_regular_methods (class_decl)
tree class_decl;
{
int saw_constructor = 0;
tree method;
tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl));
tree super_class = CLASSTYPE_SUPER (class);
int saw_constructor = 0;
tree saved_found_wfl = NULL_TREE, found = NULL_TREE;
TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
/* Should take interfaces into account. FIXME */
for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
{
tree found, sig;
tree sig;
tree method_wfl = DECL_NAME (method);
int aflags;
/* If we previously found something and its name was saved,
reinstall it now */
if (found && saved_found_wfl)
DECL_NAME (found) = saved_found_wfl;
/* Check for redefinitions */
if (check_method_redefinition (class, method))
continue;
......@@ -4077,12 +4157,17 @@ java_check_regular_methods (class_decl)
}
sig = build_java_argument_signature (TREE_TYPE (method));
found = lookup_argument_method (super_class, DECL_NAME (method), sig);
/* Nothing overrides or it's a private method */
/* Nothing overrides or it's a private method. */
if (!found || (found && METHOD_PRIVATE (found)))
continue;
continue;
/* If found wasn't verified, it's DECL_NAME won't be set properly.
We set it temporarily for the sake of the error report. */
saved_found_wfl = DECL_NAME (found);
reset_method_name (found);
/* Can't override a method with the same name and different return
types. */
if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method)))
......@@ -4126,19 +4211,27 @@ java_check_regular_methods (class_decl)
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
continue;
}
/* Overriding/hiding public must be public or
overriding/hiding protected must be protected or public */
if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) ||
(METHOD_PROTECTED (found)
&& !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method))))
aflags = get_access_flags_from_decl (found);
/* - Overriding/hiding public must be public
- Overriding/hiding protected must be protected or public
- If the overriden or hidden method has default (package)
access, then the overriding or hiding method must not be
private; otherwise, a compile-time error occurs */
if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method))
|| (METHOD_PROTECTED (found)
&& !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method)))
|| (!(aflags & (ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC))
&& METHOD_PRIVATE (method)))
{
parse_error_context
(method_wfl,
"Methods can't be overridden to be more private. Method `%s' is "
"%s in class `%s'", lang_printable_name (found, 0),
(METHOD_PUBLIC (found) ? "public" : "protected"),
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
"not %s in class `%s'", lang_printable_name (method, 0),
(METHOD_PUBLIC (method) ? "public" :
(METHOD_PRIVATE (method) ? "private" : "protected")),
IDENTIFIER_POINTER (DECL_NAME
(TYPE_NAME (DECL_CONTEXT (found)))));
continue;
}
......@@ -4148,9 +4241,10 @@ java_check_regular_methods (class_decl)
/* If the method has default access in an other package, then
issue a warning that the current method doesn't override the
one that was found elsewhere */
aflags = get_access_flags_from_decl (found);
if ((!aflags || (aflags > ACC_PROTECTED))
one that was found elsewhere. Do not issue this warning when
the match was found in java.lang.Object. */
if (DECL_CONTEXT (found) != object_type_node
&& (!aflags || (aflags > ACC_PROTECTED))
&& !class_in_current_package (DECL_CONTEXT (found)))
parse_warning_context
(method_wfl, "Method `%s' in class `%s' does not "
......@@ -4160,10 +4254,16 @@ java_check_regular_methods (class_decl)
IDENTIFIER_POINTER (DECL_NAME (class_decl)),
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
/* Check on (default) package access. FIXME. */
/* Inheriting multiple methods with the same signature. FIXME */
}
/* Don't forget eventual pending found and saved_found_wfl. Take
into account that we might have exited because we saw an
aritifical method as the last entry. */
if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
DECL_NAME (found) = saved_found_wfl;
TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
if (!saw_constructor)
......@@ -4220,11 +4320,12 @@ check_throws_clauses (method, method_wfl, found)
/* Check abstract method of interface INTERFACE */
static void
java_check_abstract_methods (interface)
tree interface;
java_check_abstract_methods (interface_decl)
tree interface_decl;
{
int i, n;
tree method, basetype_vec, found;
tree interface = TREE_TYPE (interface_decl);
for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method))
{
......@@ -4239,16 +4340,20 @@ java_check_abstract_methods (interface)
found = lookup_java_interface_method2 (interface, method);
if (found)
{
char *t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)),
0));
char *t;
tree saved_found_wfl = DECL_NAME (found);
reset_method_name (found);
t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0));
parse_error_context
(method_wfl,
"Method `%s' was defined with return type `%s' in class `%s ",
"Method `%s' was defined with return type `%s' in class `%s'",
lang_printable_name (found, 0), t,
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
free (t);
continue;
DECL_NAME (found) = saved_found_wfl;
}
}
......@@ -4270,37 +4375,39 @@ java_check_abstract_methods (interface)
found = lookup_java_interface_method2 (interface,
sub_interface_method);
if (found && (found != sub_interface_method))
parse_error_context
(lookup_cl (sub_interface_method),
"Interface `%s' inherits method `%s' from interface `%s'. This "
"method is redefined with a different return "
"type in interface `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (interface))),
lang_printable_name (found, 0),
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (sub_interface_method)))),
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
{
tree saved_found_wfl = DECL_NAME (found);
reset_method_name (found);
parse_error_context
(lookup_cl (sub_interface_method),
"Interface `%s' inherits method `%s' from interface `%s'. "
"This method is redefined with a different return type in "
"interface `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (interface))),
lang_printable_name (found, 0),
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME
(DECL_CONTEXT (sub_interface_method)))),
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
DECL_NAME (found) = saved_found_wfl;
}
}
}
}
/* Check the method on all the defined classes. Should be done to the
classes declared in the compilation unit only. FIXME */
/* 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->class_list; current; current = TREE_CHAIN (current))
if (CLASS_FROM_SOURCE_P (TREE_TYPE (current)))
for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
{
tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current));
if (CLASS_INTERFACE (TYPE_NAME (class)))
java_check_abstract_methods (class);
else
java_check_regular_methods (current);
CHECK_METHODS (TREE_VALUE (current));
CLASS_METHOD_CHECKED_P (TREE_TYPE (TREE_VALUE (current))) = 1;
}
}
......@@ -4345,9 +4452,12 @@ lookup_java_method2 (clas, method_decl, do_interface)
tree clas, method_decl;
int do_interface;
{
tree method, method_signature, method_name, method_type;
tree method, method_signature, method_name, method_type, name;
method_signature = build_java_argument_signature (TREE_TYPE (method_decl));
method_name = DECL_NAME (method_decl);
name = DECL_NAME (method_decl);
method_name = (TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
EXPR_WFL_NODE (name) : name);
method_type = TREE_TYPE (TREE_TYPE (method_decl));
while (clas != NULL_TREE)
......@@ -4356,12 +4466,12 @@ lookup_java_method2 (clas, method_decl, do_interface)
method != NULL_TREE; method = TREE_CHAIN (method))
{
tree method_sig = build_java_argument_signature (TREE_TYPE (method));
if (DECL_NAME (method) == method_name
tree name = DECL_NAME (method);
if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
EXPR_WFL_NODE (name) : name) == method_name
&& method_sig == method_signature
&& TREE_TYPE (TREE_TYPE (method)) != method_type)
{
return method;
}
return method;
}
clas = (do_interface ? NULL_TREE : CLASSTYPE_SUPER (clas));
}
......@@ -4450,8 +4560,6 @@ find_in_imports (class_type)
{
TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import));
QUALIFIED_P (TYPE_NAME (class_type)) = 1;
return check_pkg_class_access (TYPE_NAME (class_type),
TREE_PURPOSE (import));
}
return 0;
}
......@@ -4675,6 +4783,50 @@ find_in_imports_on_demand (class_type)
return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */
}
static tree
resolve_package (pkg, next)
tree pkg, *next;
{
tree type_name = NULL_TREE;
char *name = IDENTIFIER_POINTER (EXPR_WFL_NODE (pkg));
int length = IDENTIFIER_LENGTH (EXPR_WFL_NODE (pkg));
/* The trick is to determine when the package name stops and were
the name of something contained in the package starts. Then we
return a fully qualified name of what we want to get. */
/* Do a quick search on well known package names */
if (!strncmp (name, "java.lang.reflect", 17))
{
*next =
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg))));
type_name = lookup_package_type (name, 17);
}
else if (!strncmp (name, "java.lang", 9))
{
*next = TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg)));
type_name = lookup_package_type (name, 9);
}
else
return NULL_TREE; /* FIXME, search all imported packages. */
return type_name;
}
static tree
lookup_package_type (name, from)
char *name;
int from;
{
char subname [128];
char *sub = &name[from+1];
while (*sub != '.' && *sub)
sub++;
strncpy (subname, name, sub-name);
subname [sub-name] = '\0';
return get_identifier (subname);
}
/* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no
access violations were found, 1 otherwise. */
......@@ -5021,16 +5173,21 @@ 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
several field related lists. */
/* Layout all class found during parsing. Also fixes the order of some
lists. */
void
java_layout_classes ()
{
tree current;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
java_check_methods ();
/* Error reported by the caller */
if (java_error_count)
return;
for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (current);
current_class = TREE_TYPE (TREE_VALUE (current));
/* Reverse the fields if it's necessary (they've already
reversed if the dummy field has been inserted at the
......@@ -5042,6 +5199,10 @@ java_layout_classes ()
/* Do a layout if necessary */
if (!TYPE_SIZE (current_class) || (current_class == object_type_node))
safe_layout_class (current_class);
/* Error reported by the caller */
if (java_error_count)
return;
}
}
......@@ -5080,7 +5241,9 @@ java_complete_expand_methods ()
restore_line_number_status (0);
}
}
else
else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
continue;
else
java_complete_expand_method (decl);
}
......@@ -5135,6 +5298,7 @@ java_complete_expand_method (mdecl)
if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)))
java_complete_tree (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)));
/* Don't go any further if we've found error(s) during the
expansion */
if (!java_error_count)
......@@ -5294,6 +5458,13 @@ 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)
return;
java_layout_classes ();
java_parse_abort_on_error ();
for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
{
ctxp = ctxp_for_generation;
......@@ -5425,8 +5596,9 @@ cut_identifier_in_qualified (wfl)
/* Resolve the expression name NAME. Return its decl. */
static tree
resolve_expression_name (id)
resolve_expression_name (id, orig)
tree id;
tree *orig;
{
tree name = EXPR_WFL_NODE (id);
tree decl;
......@@ -5445,6 +5617,7 @@ resolve_expression_name (id)
decl = lookup_field_wrapper (current_class, name);
if (decl)
{
tree value = NULL_TREE;
int fs = FIELD_STATIC (decl);
/* Instance variable (8.3.1.1) can't appear within
static method, static initializer or initializer for
......@@ -5468,9 +5641,20 @@ resolve_expression_name (id)
"constructor has been called", IDENTIFIER_POINTER (name));
return error_mark_node;
}
/* The field is final. We may use its value instead */
if (fs && FIELD_FINAL (decl))
value = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl));
/* Otherwise build what it takes to access the field */
decl = build_field_ref ((fs ? NULL_TREE : current_this),
current_class, name);
return (fs ? build_class_init (current_class, decl) : decl);
if (fs && !flag_emit_class_files)
decl = build_class_init (current_class, decl);
/* We may be asked to save the real field access node */
if (orig)
*orig = decl;
/* And we return what we got */
return (value ? value : decl);
}
/* Fall down to error report on undefined variable */
}
......@@ -5478,6 +5662,8 @@ resolve_expression_name (id)
/* 6.5.5.2 Qualified Expression Names */
else
{
if (orig)
*orig = NULL_TREE;
qualify_ambiguous_name (id);
/* 15.10.1 Field Access Using a Primary and/or Expression Name */
/* 15.10.2: Accessing Superclass Members using super */
......@@ -5523,12 +5709,24 @@ resolve_field_access (qual_wfl, field_decl, field_type)
field_ref = decl;
else if (DECL_P (decl))
{
int static_final_found = 0;
if (!type_found)
type_found = DECL_CONTEXT (decl);
is_static = DECL_P (decl) && FIELD_STATIC (decl);
field_ref = build_field_ref ((is_static ? NULL_TREE : where_found),
type_found, DECL_NAME (decl));
if (FIELD_FINAL (decl)
&& JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
&& DECL_LANG_SPECIFIC (decl)
&& DECL_LOCAL_STATIC_VALUE (decl))
{
field_ref = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl));
static_final_found = 1;
}
else
field_ref = build_field_ref ((is_static ? NULL_TREE : where_found),
type_found, DECL_NAME (decl));
if (field_ref == error_mark_node)
return error_mark_node;
if (is_static)
if (is_static && !static_final_found)
{
field_ref = build_class_init (type_found, field_ref);
/* If the static field was identified by an expression that
......@@ -5571,7 +5769,6 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
tree qual_wfl = QUAL_WFL (q);
/* 15.10.1 Field Access Using a Primary */
switch (TREE_CODE (qual_wfl))
{
case CALL_EXPR:
......@@ -5619,6 +5816,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
continue;
case CONDITIONAL_EXPR:
case STRING_CST:
*where_found = decl = java_complete_tree (qual_wfl);
if (decl == error_mark_node)
return 1;
......@@ -5660,7 +5858,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
}
/* We have to generate code for intermediate acess */
*where_found = decl = current_this;
type = QUAL_DECL_TYPE (decl);
*type_found = type = QUAL_DECL_TYPE (decl);
continue;
}
......@@ -5692,17 +5890,33 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
assume a variable/class name was meant. */
if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
{
if (from_super || from_cast)
parse_error_context
((from_cast ? qual_wfl : wfl),
"No variable `%s' defined in class `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)),
lang_printable_name (type, 0));
tree name = resolve_package (wfl, &q);
if (name)
{
*where_found = decl = resolve_no_layout (name, qual_wfl);
/* We wan't to be absolutely that the class is laid
out. We're going to search something inside it. */
*type_found = type = TREE_TYPE (decl);
layout_class (type);
from_type = 1;
/* Should be a list, really. FIXME */
RESOLVE_EXPRESSION_NAME_P (QUAL_WFL (TREE_CHAIN (q))) = 1;
RESOLVE_PACKAGE_NAME_P (QUAL_WFL (TREE_CHAIN (q))) = 0;
}
else
parse_error_context
(qual_wfl, "Undefined variable or class name: `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)));
return 1;
{
if (from_super || from_cast)
parse_error_context
((from_cast ? qual_wfl : wfl),
"No variable `%s' defined in class `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)),
lang_printable_name (type, 0));
else
parse_error_context
(qual_wfl, "Undefined variable or class name: `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)));
return 1;
}
}
/* We have a type name. It's been already resolved when the
......@@ -5722,6 +5936,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
return 1;
}
check_deprecation (qual_wfl, decl);
type = TREE_TYPE (decl);
from_type = 1;
......@@ -5738,18 +5953,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
if (!from_super && QUAL_RESOLUTION (q))
{
decl = QUAL_RESOLUTION (q);
*type_found = type;
if (!type && !FIELD_STATIC (decl))
{
*where_found = current_this;
*type_found = type;
}
}
/* We have to search for a field, knowing the type of its
container. The flag FROM_TYPE indicates that we resolved
the last member of the expression as a type name, which
means that for the resolution of this field, will check
on other errors than if the it was resolved as a member
of an other field. */
means that for the resolution of this field, we'll look
for other errors than if it was resolved as a member of
an other field. */
else
{
int is_static;
tree field_decl_type; /* For layout */
if (!from_type && !JREFERENCE_TYPE_P (type))
{
parse_error_context
......@@ -5769,6 +5990,17 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
return 1;
}
/* Layout the type of field_decl, since we may need
it. Don't do primitive types or loaded classes */
if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE)
field_decl_type = TREE_TYPE (TREE_TYPE (field_decl));
else
field_decl_type = TREE_TYPE (field_decl);
if (!JPRIMITIVE_TYPE_P (field_decl_type)
&& !CLASS_LOADED_P (field_decl_type))
resolve_and_layout (DECL_NAME (TYPE_NAME (field_decl_type)),
NULL_TREE);
/* Check on accessibility here */
if (not_accessible_p (type, field_decl, from_super))
......@@ -5784,6 +6016,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
(DECL_NAME (TYPE_NAME (current_class))));
return 1;
}
check_deprecation (qual_wfl, field_decl);
/* There are things to check when fields are accessed
from type. There are no restrictions on a static
......@@ -5802,8 +6035,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
}
from_cast = from_super = 0;
/* If we need to generate something to get a proper handle
on what this field is accessed from, do it now. */
/* If we need to generate something to get a proper
handle on what this field is accessed from, do it
now. */
if (!is_static)
{
decl = maybe_access_field (decl, *where_found, *type_found);
......@@ -5889,6 +6123,38 @@ int not_accessible_p (reference, member, from_super)
return 0;
}
/* Test deprecated decl access. */
static void
check_deprecation (wfl, decl)
tree wfl, decl;
{
char *file = DECL_SOURCE_FILE (decl);
/* Complain if the field is deprecated and the file it was defined
in isn't compiled at the same time the file which contains its
use is */
if (DECL_DEPRECATED (decl)
&& !IS_A_COMMAND_LINE_FILENAME_P (get_identifier (file)))
{
char the [20];
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
strcpy (the, "method");
break;
case FIELD_DECL:
strcpy (the, "field");
break;
case TYPE_DECL:
strcpy (the, "class");
break;
}
parse_warning_context
(wfl, "The %s `%s' in class `%s' has been deprecated",
the, lang_printable_name (decl, 0),
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))));
}
}
/* Returns 1 if class was declared in the current package, 0 otherwise */
static int
......@@ -5933,10 +6199,8 @@ static tree
maybe_access_field (decl, where, type)
tree decl, where, type;
{
if (DECL_P (decl) && decl != current_this
&& (!(TREE_CODE (decl) != PARM_DECL
&& FIELD_STATIC (decl)))
&& !IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
if (TREE_CODE (decl) == FIELD_DECL && decl != current_this
&& !FIELD_STATIC (decl))
decl = build_field_ref (where ? where : current_this,
(type ? type : DECL_CONTEXT (decl)),
DECL_NAME (decl));
......@@ -5957,7 +6221,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
tree wfl = TREE_OPERAND (patch, 0);
tree args = TREE_OPERAND (patch, 1);
tree name = EXPR_WFL_NODE (wfl);
tree list, class_type;
tree list;
int is_static_flag = 0;
/* Should be overriden if everything goes well. Otherwise, if
......@@ -6028,6 +6292,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
free (fct_name);
PATCH_METHOD_RETURN_ERROR ();
}
args = nreverse (args);
}
/* We're resolving an expression name */
else
......@@ -6053,9 +6318,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
args = tree_cons (NULL_TREE, field, nreverse (args));
}
/* CLASS_TYPE is used during the call to not_accessible_p and
IDENTIFIER_WFL will be used to report any problem further */
class_type = TREE_TYPE (class_decl);
/* IDENTIFIER_WFL will be used to report any problem further */
wfl = identifier_wfl;
}
/* Resolution of simple names, names generated after a primary: or
......@@ -6099,8 +6362,11 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
PATCH_METHOD_RETURN_ERROR ();
}
/* Can't instantiate an abstract class */
if (CLASS_ABSTRACT (class_to_search))
/* Can't instantiate an abstract class, but we can
invoke it's constructor. It's use within the `new'
context is denied here. */
if (CLASS_ABSTRACT (class_to_search)
&& TREE_CODE (patch) == NEW_CLASS_EXPR)
{
parse_error_context
(wfl, "Class `%s' is an abstract class. It can't be "
......@@ -6143,8 +6409,6 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
args = nreverse (args);
if (!METHOD_STATIC (list) && TREE_CODE (patch) != NEW_CLASS_EXPR)
args = tree_cons (NULL_TREE, primary ? primary : current_this, args);
class_type = class_to_search;
}
/* Merge point of all resolution schemes. If we have nothing, this
......@@ -6154,18 +6418,19 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
/* Check accessibility, position the is_static flag, build and
return the call */
if (not_accessible_p (class_type, list, 0))
if (not_accessible_p (DECL_CONTEXT (list), list, 0))
{
char *fct_name = strdup (lang_printable_name (list, 0));
parse_error_context
(wfl, "Can't access %s method `%s %s.%s' from `%s'",
java_accstring_lookup (get_access_flags_from_decl (list)),
lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0),
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))), fct_name,
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list)))),
fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
free (fct_name);
PATCH_METHOD_RETURN_ERROR ();
}
check_deprecation (wfl, list);
is_static_flag = METHOD_STATIC (list);
......@@ -6223,9 +6488,14 @@ patch_invoke (patch, method, args, from_super)
tree signature = build_java_signature (TREE_TYPE (method));
tree original_call, t, ta;
/* Last step for args: convert build-in types. */
for (t = TYPE_ARG_TYPES (TREE_TYPE (method)), ta = args;
t && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta))
/* Last step for args: convert build-in types. If we're dealing with
a new TYPE() type call, the first argument to the constructor
isn't found in the incomming argument list, but delivered by
`new' */
t = TYPE_ARG_TYPES (TREE_TYPE (method));
if (TREE_CODE (patch) == NEW_CLASS_EXPR)
t = TREE_CHAIN (t);
for (ta = args; t && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta))
if (JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_VALUE (ta))) &&
TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t))
TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta));
......@@ -6243,6 +6513,11 @@ patch_invoke (patch, method, args, from_super)
DECL_CONTEXT (method), signature, args);
break;
case INVOKE_INTERFACE:
dtable = invoke_build_dtable (1, args);
func = build_invokeinterface (dtable, DECL_NAME (method), signature);
break;
default:
fatal ("Unknown invocation mode `%d' - build_invoke", im);
return NULL_TREE;
......@@ -6318,34 +6593,24 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
tree class, name, arg_list;
{
tree method = make_node (FUNCTION_TYPE);
tree arg_type_list = NULL_TREE;
tree atl = NULL_TREE; /* Arg Type List */
tree signature, list, node;
char *candidates; /* Used for error report */
/* Fix the arguments */
for (node = arg_list; node; node = TREE_CHAIN (node))
{
tree current_arg = TREE_TYPE (TREE_VALUE (node));
if (TREE_CODE (current_arg) == RECORD_TYPE)
current_arg = promote_type (current_arg);
arg_type_list = tree_cons (NULL_TREE, current_arg, arg_type_list);
atl = tree_cons (NULL_TREE, current_arg, atl);
}
TYPE_ARG_TYPES (method) = arg_type_list;
TYPE_ARG_TYPES (method) = atl;
if (!lc)
{
list = find_applicable_accessible_methods_list (class, name,
arg_type_list);
list = find_most_specific_methods_list (list);
}
else
{
TREE_TYPE (method) = void_type_node;
signature = build_java_signature (method);
list = lookup_java_constructor (class, signature);
}
if (lc && list)
return list;
/* Find all candidates and then refine the list, searching for the
most specific method. */
list = find_applicable_accessible_methods_list (lc, class, name, atl);
list = find_most_specific_methods_list (list);
if (list && !TREE_CHAIN (list))
return TREE_VALUE (list);
......@@ -6386,10 +6651,12 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
return NULL_TREE;
}
/* 15.11.2.1: Find Methods that are Applicable and Accessible */
/* 15.11.2.1: Find Methods that are Applicable and Accessible. LC is 1
when we're looking for a constructor. */
static tree
find_applicable_accessible_methods_list (class, name, arglist)
find_applicable_accessible_methods_list (lc, class, name, arglist)
int lc;
tree class, name, arglist;
{
tree method;
......@@ -6400,10 +6667,12 @@ find_applicable_accessible_methods_list (class, name, arglist)
for (method = TYPE_METHODS (class);
method != NULL_TREE; method = TREE_CHAIN (method))
{
/* Names have to match and we're not looking for constructor */
if (DECL_NAME (method) != name || DECL_CONSTRUCTOR_P (method))
if (lc && !DECL_CONSTRUCTOR_P (method))
continue;
else if (!lc && (DECL_CONSTRUCTOR_P (method)
|| DECL_NAME (method) != name))
continue;
if (argument_types_convertible (method, arglist))
{
/* Retain accessible methods only */
......@@ -6414,7 +6683,9 @@ find_applicable_accessible_methods_list (class, name, arglist)
all_list = tree_cons (NULL_TREE, method, list);
}
}
class = CLASSTYPE_SUPER (class);
/* When dealing with constructor, stop here, otherwise search
other classes */
class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class));
}
/* Either return the list obtained or all selected (but
inaccessible) methods for better error report. */
......@@ -6598,8 +6869,9 @@ qualify_ambiguous_name (id)
/* Do one more interation to set things up */
super_found = again = 1;
}
/* Loop one more time if we're dealing with ?: up front */
if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR)
/* Loop one more time if we're dealing with ?: or a string constant */
if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR
|| TREE_CODE (qual_wfl) == STRING_CST)
{
qual = TREE_CHAIN (qual);
qual_wfl = QUAL_WFL (qual);
......@@ -6709,8 +6981,10 @@ not_initialized_as_it_should_p (decl)
{
if (DECL_P (decl))
{
if (TREE_CODE (decl) == FIELD_DECL
&& METHOD_STATIC (current_function_decl))
if (FIELD_FINAL (decl))
return 0;
if (TREE_CODE (decl) == FIELD_DECL
&& (METHOD_STATIC (current_function_decl)))
return 0;
return DECL_P (decl) && !INITIALIZED_P (decl);
}
......@@ -6860,7 +7134,7 @@ java_complete_tree (node)
case EXPR_WITH_FILE_LOCATION:
if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */
|| TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE)
return resolve_expression_name (node);
return resolve_expression_name (node, NULL);
else
{
EXPR_WFL_NODE (node) = java_complete_tree (EXPR_WFL_NODE (node));
......@@ -6958,7 +7232,8 @@ java_complete_tree (node)
an error during the assignment. In any cases, the
assignment operation fails. */
if (TREE_CODE (TREE_OPERAND (node, 1)) != EXPR_WITH_FILE_LOCATION
&& TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node)
&& TREE_TYPE (TREE_OPERAND (node, 1)) != error_mark_node
&& TREE_TYPE (TREE_OPERAND (node, 1)))
patch_assignment (node, wfl_op1, wfl_op2);
/* Now, we still mark the lhs as initialized */
......@@ -7015,6 +7290,11 @@ java_complete_tree (node)
}
return patch_binop (node, wfl_op1, wfl_op2);
case INSTANCEOF_EXPR:
wfl_op1 = TREE_OPERAND (node, 0);
COMPLETE_CHECK_OP_0 (node);
return patch_binop (node, wfl_op1, TREE_OPERAND (node, 1));
case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
......@@ -7108,8 +7388,10 @@ complete_function_arguments (node)
`+' operator. Build `parm.toString()' and expand it. */
if ((temp = patch_string (parm)))
parm = temp;
TREE_VALUE (cn) = parm;
/* Inline PRIMTYPE.TYPE read access */
parm = maybe_build_primttype_type_ref (parm, wfl);
TREE_VALUE (cn) = parm;
if (not_initialized_as_it_should_p (parm))
{
ERROR_VARIABLE_NOT_INITIALIZED (wfl, EXPR_WFL_NODE (wfl));
......@@ -7350,6 +7632,47 @@ print_int_node (node)
return buffer;
}
/* Return 1 if you an assignment of a FINAL is attempted */
static int
check_final_assignment (lvalue, wfl)
tree lvalue, wfl;
{
if (DECL_P (lvalue) && FIELD_FINAL (lvalue))
{
parse_error_context
(wfl, "Can't assign a value to the final variable `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
return 1;
}
return 0;
}
/* Inline references to java.lang.PRIMTYPE.TYPE when accessed in
read. This is needed to avoid circularities in the implementation
of these fields in libjava. */
static tree
maybe_build_primttype_type_ref (rhs, wfl)
tree rhs, wfl;
{
tree to_return = NULL_TREE;
tree rhs_type = TREE_TYPE (rhs);
if (TREE_CODE (rhs) == COMPOUND_EXPR)
{
tree n = TREE_OPERAND (rhs, 1);
if (TREE_CODE (n) == VAR_DECL
&& DECL_NAME (n) == TYPE_identifier_node
&& rhs_type == class_ptr_type)
{
char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl));
if (!strncmp (self_name, "java.lang.", 10))
to_return = build_primtype_type_ref (self_name);
}
}
return (to_return ? to_return : rhs );
}
/* 15.25 Assignment operators. */
static tree
......@@ -7359,19 +7682,14 @@ patch_assignment (node, wfl_op1, wfl_op2)
tree wfl_op2;
{
tree rhs = TREE_OPERAND (node, 1);
tree lvalue = TREE_OPERAND (node, 0);
tree lvalue = TREE_OPERAND (node, 0), llvalue;
tree lhs_type, rhs_type, new_rhs = NULL_TREE;
int error_found = 0;
int lvalue_from_array = 0;
/* Can't assign to a final. */
if (DECL_P (lvalue) && FIELD_FINAL (lvalue))
{
parse_error_context
(wfl_op1, "Can't assign a value to the final variable `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op1)));
error_found = 1;
}
if (check_final_assignment (lvalue, wfl_op1))
error_found = 1;
EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
......@@ -7394,8 +7712,18 @@ patch_assignment (node, wfl_op1, wfl_op2)
/* Or a function return slot */
else if (TREE_CODE (lvalue) == RESULT_DECL)
lhs_type = TREE_TYPE (lvalue);
/* Otherwise, this is an error */
else
/* Otherwise, we might want to try to write into an optimized static
final, this is an of a different nature, reported further on. */
else if (TREE_CODE (wfl_op1) == EXPR_WITH_FILE_LOCATION
&& resolve_expression_name (wfl_op1, &llvalue)
&& check_final_assignment (llvalue, wfl_op1))
{
error_found = 1;
/* What we should do instead is resetting the all the flags
previously set, exchange lvalue for llvalue and continue. */
return error_mark_node;
}
else
{
parse_error_context (wfl_op1, "Invalid left hand side of assignment");
error_found = 1;
......@@ -7462,6 +7790,22 @@ patch_assignment (node, wfl_op1, wfl_op2)
INITIALIZED_P (rhs) = 1;
}
/* Inline read access to java.lang.PRIMTYPE.TYPE */
rhs = maybe_build_primttype_type_ref (rhs, wfl_op2);
if (TREE_CODE (rhs) == COMPOUND_EXPR)
{
tree n = TREE_OPERAND (rhs, 1);
if (TREE_CODE (n) == VAR_DECL
&& DECL_NAME (n) == TYPE_identifier_node
&& rhs_type == class_ptr_type)
{
char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op2));
if (!strncmp (self_name, "java.lang.", 10))
rhs = build_primtype_type_ref (self_name);
}
}
if (error_found)
return error_mark_node;
......@@ -7515,9 +7859,15 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs)
tree new_rhs = NULL_TREE;
tree rhs_type = TREE_TYPE (rhs);
/* Zero accepted everywhere */
if (TREE_CODE (rhs) == INTEGER_CST
&& TREE_INT_CST_HIGH (rhs) == 0 && TREE_INT_CST_LOW (rhs) == 0
&& JPRIMITIVE_TYPE_P (rhs_type))
new_rhs = convert (lhs_type, rhs);
/* 5.1.1 Try Identity Conversion,
5.1.2 Try Widening Primitive Conversion */
if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type))
else if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type))
new_rhs = convert (lhs_type, rhs);
/* Try a narrowing primitive conversion (5.1.3):
......@@ -7552,20 +7902,32 @@ static int
valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)
tree lhs_type, rhs_type;
{
int all_primitive =
int all_primitive;
if (lhs_type == rhs_type)
return 1;
all_primitive =
JPRIMITIVE_TYPE_P (lhs_type) && JPRIMITIVE_TYPE_P (rhs_type);
if (!all_primitive)
return 0;
if (lhs_type == rhs_type)
return 1;
/* byte, even if it's smaller than a char can't be converted into a
char. Short can't too, but the < test below takes care of that */
if (lhs_type == char_type_node && rhs_type == byte_type_node)
return 0;
/* Accept all promoted type here. Note, we can't use <= in the test
below, because we still need to bounce out assignments of short
to char and the likes */
if (lhs_type == int_type_node
&& (rhs_type == promoted_byte_type_node
|| rhs_type == promoted_short_type_node
|| rhs_type == promoted_char_type_node
|| rhs_type == promoted_boolean_type_node))
return 1;
if (JINTEGRAL_TYPE_P (rhs_type)
&& ((TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type))
|| (JFLOAT_TYPE_P (lhs_type) &&
......@@ -7590,6 +7952,8 @@ valid_ref_assignconv_cast_p (source, dest, cast)
tree dest;
int cast;
{
if (JNULLP_TYPE_P (source))
return 1;
if (TREE_CODE (source) == POINTER_TYPE)
source = TREE_TYPE (source);
if (TREE_CODE (dest) == POINTER_TYPE)
......@@ -7715,8 +8079,8 @@ valid_method_invocation_conversion_p (dest, source)
return ((JPRIMITIVE_TYPE_P (source)
&& JPRIMITIVE_TYPE_P (dest)
&& valid_builtin_assignconv_identity_widening_p (dest, source))
|| (JREFERENCE_TYPE_P (source)
&& JREFERENCE_TYPE_P (dest)
|| ((JREFERENCE_TYPE_P (source) || JNULLP_TYPE_P (source))
&& (JREFERENCE_TYPE_P (dest) || JNULLP_TYPE_P (dest))
&& valid_ref_assignconv_cast_p (source, dest, 0)));
}
......@@ -7728,9 +8092,7 @@ build_binop (op, op_location, op1, op2)
int op_location;
tree op1, op2;
{
tree binop;
binop = build (op, NULL_TREE, op1, op2);
tree binop = build (op, NULL_TREE, op1, op2);
TREE_SIDE_EFFECTS (binop) = 1;
/* Store the location of the operator, for better error report. The
string of the operator will be rebuild based on the OP value. */
......@@ -7935,7 +8297,63 @@ patch_binop (node, wfl_op1, wfl_op2)
TREE_SET_CODE (node, RSHIFT_EXPR);
}
break;
/* 15.19.1 Type Comparison Operator instaceof */
case INSTANCEOF_EXPR:
TREE_TYPE (node) = boolean_type_node;
if (!(op2_type = resolve_type_during_patch (op2)))
return error_mark_node;
/* The first operand must be a reference type or the null type */
if (!JREFERENCE_TYPE_P (op1_type) && op1 != null_pointer_node)
error_found = 1; /* Error reported further below */
/* The second operand must be a reference type */
if (!JREFERENCE_TYPE_P (op2_type))
{
SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);
parse_error_context
(wfl_operator, "Invalid argument `%s' for `instanceof'",
lang_printable_name (op2_type, 0));
error_found = 1;
}
if (!error_found && valid_ref_assignconv_cast_p (op1_type, op2_type, 1))
{
/* If the first operand is null, the result is always false */
if (op1 == null_pointer_node)
return boolean_false_node;
/* Otherwise we have to invoke instance of to figure it out */
else
{
tree call =
build (CALL_EXPR, boolean_type_node,
build_address_of (soft_instanceof_node),
tree_cons
(NULL_TREE, op1,
build_tree_list (NULL_TREE,
build_class_ref (op2_type))),
NULL_TREE);
TREE_SIDE_EFFECTS (call) = 1;
return call;
}
}
/* There is no way the expression operand can be an instance of
the type operand. This is a compile time error. */
else
{
char *t1 = strdup (lang_printable_name (op1_type, 0));
SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
parse_error_context
(wfl_operator, "Impossible for `%s' to be instance of `%s'",
t1, lang_printable_name (op2_type, 0));
free (t1);
error_found = 1;
}
break;
/* 15.21 Bitwise and Logical Operators */
case BIT_AND_EXPR:
......@@ -8011,7 +8429,7 @@ patch_binop (node, wfl_op1, wfl_op2)
case NE_EXPR:
/* 15.20.1 Numerical Equality Operators == and != */
/* Binary numeric promotion is performed on the operands */
if (JPRIMITIVE_TYPE_P (op1_type) && JPRIMITIVE_TYPE_P (op2_type))
if (JNUMERIC_TYPE_P (op1_type) && JNUMERIC_TYPE_P (op2_type))
binary_numeric_promotion (op1_type, op2_type, &op1, &op2);
/* 15.20.2 Boolean Equality Operators == and != */
......@@ -8020,10 +8438,14 @@ patch_binop (node, wfl_op1, wfl_op2)
; /* Nothing to do here */
/* 15.20.3 Reference Equality Operators == and != */
/* Types have to be either references or the null type */
/* Types have to be either references or the null type. If
they're references, it must be possible to convert either
type to the other by casting conversion. */
else if (op1 == null_pointer_node || op2 == null_pointer_node
|| (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type)
&& ((op1_type == op2_type))))
&& (valid_ref_assignconv_cast_p (op1_type, op2_type, 1)
|| valid_ref_assignconv_cast_p (op2_type,
op1_type, 1))))
; /* Nothing to do here */
/* Else we have an error figure what can't be converted into
......@@ -8344,22 +8766,25 @@ patch_unaryop (node, wfl_op)
case PREINCREMENT_EXPR:
/* 15.14.2 Prefix Decrement Operator -- */
case PREDECREMENT_EXPR:
if (!DECL_P (op) && !(TREE_CODE (op) == INDIRECT_REF
if (!DECL_P (op) && !((TREE_CODE (op) == INDIRECT_REF
|| TREE_CODE (op) == COMPONENT_REF)
&& JPRIMITIVE_TYPE_P (TREE_TYPE (op))))
{
parse_error_context (wfl_operator, "Invalid argument to `%s'",
operator_string (node));
TREE_TYPE (node) = error_mark_node;
error_found = 1;
}
else if (DECL_P (op) && FIELD_FINAL (op))
{
parse_error_context
(wfl_op, "Can't assign a value to the final variable `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op)));
tree lvalue;
/* Before screaming, check that we're not in fact trying to
increment a optimized static final access, in which case
we issue an different error message. */
if (!(TREE_CODE (wfl_op) == EXPR_WITH_FILE_LOCATION
&& resolve_expression_name (wfl_op, &lvalue)
&& check_final_assignment (lvalue, wfl_op)))
parse_error_context (wfl_operator, "Invalid argument to `%s'",
operator_string (node));
TREE_TYPE (node) = error_mark_node;
error_found = 1;
}
else if (check_final_assignment (op, wfl_op))
error_found = 1;
/* From now on, we know that op if a variable and that it has a
valid wfl. We use wfl_op to locate errors related to the
++/-- operand. */
......@@ -8480,7 +8905,10 @@ resolve_type_during_patch (type)
return NULL_TREE;
}
else
return TREE_TYPE (type_decl);
{
CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1;
return TREE_TYPE (type_decl);
}
}
return type;
}
......@@ -8515,6 +8943,10 @@ patch_cast (node, wfl_operator)
return convert (cast_type, op);
}
/* null can be casted to references */
if (op == null_pointer_node && JREFERENCE_TYPE_P (cast_type))
return build_null_of_type (cast_type);
/* The remaining legal casts involve conversion between reference
types. Check for their compile time correctness. */
if (JREFERENCE_TYPE_P (op_type) && JREFERENCE_TYPE_P (cast_type)
......@@ -8544,6 +8976,17 @@ patch_cast (node, wfl_operator)
return error_mark_node;
}
/* Build a null constant and give it the type TYPE. */
static tree
build_null_of_type (type)
tree type;
{
tree node = build_int_2 (0, 0);
TREE_TYPE (node) = promote_type (type);
return node;
}
/* Build an ARRAY_REF incomplete tree node. Note that operand 1 isn't
a list of indices. */
static tree
......@@ -8617,8 +9060,11 @@ patch_array_ref (node, wfl_array, wfl_index)
return error_mark_node;
index = convert (promoted_index_type, index);
if (TREE_CODE (array_type) == RECORD_TYPE)
array_type = promote_type (TYPE_ARRAY_ELEMENT (array_type));
array_type = TYPE_ARRAY_ELEMENT (array_type);
if (TREE_CODE (array_type) == RECORD_TYPE
&& !JPRIMITIVE_TYPE_P (TREE_TYPE (array_type)))
array_type = promote_type (array_type);
if (flag_emit_class_files)
{
TREE_OPERAND (node, 0)= array;
......@@ -8804,7 +9250,6 @@ patch_return (node)
tree return_exp = TREE_OPERAND (node, 0);
tree meth = current_function_decl;
tree mtype = TREE_TYPE (TREE_TYPE (current_function_decl));
tree modify;
int error_found = 0;
TREE_TYPE (node) = error_mark_node;
......@@ -8838,12 +9283,33 @@ patch_return (node)
return error_mark_node;
}
/* If we have a return_exp, build a modify expression and expand it */
/* If we have a return_exp, build a modify expression and expand
it. Note: at that point, the assignment is declared valid, but we
may want to carry some more hacks */
if (return_exp)
{
modify = build (MODIFY_EXPR, NULL_TREE, DECL_RESULT (meth), return_exp);
tree exp = java_complete_tree (return_exp);
tree modify, patched;
/* If the function returned value and EXP are booleans, EXP has
to be converted into the type of DECL_RESULT, which is integer
(see complete_start_java_method) */
if (TREE_TYPE (exp) == boolean_type_node &&
TREE_TYPE (TREE_TYPE (meth)) == boolean_type_node)
exp = convert_to_integer (TREE_TYPE (DECL_RESULT (meth)), exp);
/* `null' can be assigned to a function returning a reference */
if (JREFERENCE_TYPE_P (TREE_TYPE (TREE_TYPE (meth))) &&
exp == null_pointer_node)
exp = build_null_of_type (TREE_TYPE (TREE_TYPE (meth)));
if ((patched = patch_string (exp)))
exp = patched;
modify = build (MODIFY_EXPR, NULL_TREE, DECL_RESULT (meth), exp);
EXPR_WFL_LINECOL (modify) = EXPR_WFL_LINECOL (node);
modify = java_complete_tree (modify);
if (modify != error_mark_node)
{
TREE_SIDE_EFFECTS (modify) = 1;
......
......@@ -52,10 +52,6 @@ set_local_type (slot, type)
type_map[++slot] = void_type_node;
}
extern tree convert_to_integer (tree type, tree expr);
extern tree convert_to_real (tree type, tree expr);
extern tree convert_to_pointer (tree type, tree expr);
/* Create an expression whose value is that of EXPR,
converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable
......@@ -663,7 +659,7 @@ lookup_argument_method (clas, method_name, method_signature)
tree method_sig = build_java_argument_signature (TREE_TYPE (method));
tree name = DECL_NAME (method);
if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
EXPR_WFL_NODE (DECL_NAME (method)) : name) == method_name
EXPR_WFL_NODE (name) : name) == method_name
&& method_sig == method_signature)
return method;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment