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> 1998-10-30 Tom Tromey <tromey@cygnus.com>
* class.c (build_class_ref): Changed name of primitive classes to * class.c (build_class_ref): Changed name of primitive classes to
......
...@@ -1153,7 +1153,12 @@ is_compiled_class (class) ...@@ -1153,7 +1153,12 @@ is_compiled_class (class)
if (flag_assume_compiled) if (flag_assume_compiled)
{ {
if (!CLASS_LOADED_P (class)) if (!CLASS_LOADED_P (class))
{
if (CLASS_FROM_SOURCE_P (class))
safe_layout_class (class);
else
load_class (class, 1); load_class (class, 1);
}
return 1; return 1;
} }
......
/* Definition of conversion functions. /* Definition of conversion functions.
Copyright (C) 1993 Free Software Foundation, Inc. Copyright (C) 1993 Free Software Foundation, Inc.
...@@ -22,3 +23,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -22,3 +23,6 @@ Boston, MA 02111-1307, USA. */
extern tree convert_to_boolean PROTO ((tree, tree)); extern tree convert_to_boolean PROTO ((tree, tree));
extern tree convert_to_char 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 () ...@@ -527,8 +527,7 @@ init_decl_processing ()
methodtable_type = make_node (RECORD_TYPE); methodtable_type = make_node (RECORD_TYPE);
layout_type (methodtable_type); layout_type (methodtable_type);
pushdecl (build_decl (TYPE_DECL, get_identifier ("methodtable"), build_decl (TYPE_DECL, get_identifier ("methodtable"), methodtable_type);
methodtable_type));
methodtable_ptr_type = build_pointer_type (methodtable_type); methodtable_ptr_type = build_pointer_type (methodtable_type);
TYPE_identifier_node = get_identifier ("TYPE"); TYPE_identifier_node = get_identifier ("TYPE");
...@@ -554,8 +553,7 @@ init_decl_processing () ...@@ -554,8 +553,7 @@ init_decl_processing ()
PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node); PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node);
PUSH_FIELD (constants_type_node, field, "data", ptr_type_node); PUSH_FIELD (constants_type_node, field, "data", ptr_type_node);
FINISH_RECORD (constants_type_node); FINISH_RECORD (constants_type_node);
pushdecl (build_decl (TYPE_DECL, get_identifier ("constants"), build_decl (TYPE_DECL, get_identifier ("constants"), constants_type_node);
constants_type_node));
access_flags_type_node = unsigned_short_type_node; access_flags_type_node = unsigned_short_type_node;
...@@ -606,7 +604,7 @@ init_decl_processing () ...@@ -606,7 +604,7 @@ init_decl_processing ()
FIELD_PRIVATE (t) = 1; FIELD_PRIVATE (t) = 1;
push_super_field (class_type_node, object_type_node); push_super_field (class_type_node, object_type_node);
FINISH_RECORD (class_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); field_info_union_node = make_node (UNION_TYPE);
PUSH_FIELD (field_info_union_node, field, "boffset", int_type_node); PUSH_FIELD (field_info_union_node, field, "boffset", int_type_node);
...@@ -623,7 +621,7 @@ init_decl_processing () ...@@ -623,7 +621,7 @@ init_decl_processing ()
PUSH_FIELD (field_type_node, field, "info", field_info_union_node); PUSH_FIELD (field_type_node, field, "info", field_info_union_node);
FINISH_RECORD (field_type_node); FINISH_RECORD (field_type_node);
CLASS_LOADED_P (field_type_node) = 1; 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); one_elt_array_domain_type = build_index_type (integer_one_node);
nativecode_ptr_array_type_node nativecode_ptr_array_type_node
...@@ -632,7 +630,7 @@ init_decl_processing () ...@@ -632,7 +630,7 @@ init_decl_processing ()
PUSH_FIELD (dtable_type, field, "class", class_ptr_type); PUSH_FIELD (dtable_type, field, "class", class_ptr_type);
PUSH_FIELD (dtable_type, field, "methods", nativecode_ptr_array_type_node); PUSH_FIELD (dtable_type, field, "methods", nativecode_ptr_array_type_node);
FINISH_RECORD (dtable_type); 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_type int_type_node
#define jint_ptr_type ptr_type_node #define jint_ptr_type ptr_type_node
...@@ -643,7 +641,7 @@ init_decl_processing () ...@@ -643,7 +641,7 @@ init_decl_processing ()
PUSH_FIELD (jexception_type, field, "handler_pc", ptr_type_node); PUSH_FIELD (jexception_type, field, "handler_pc", ptr_type_node);
PUSH_FIELD (jexception_type, field, "catch_type", class_ptr_type); PUSH_FIELD (jexception_type, field, "catch_type", class_ptr_type);
FINISH_RECORD (jexception_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); jexception_ptr_type = build_pointer_type (jexception_type);
lineNumberEntry_type = make_node (RECORD_TYPE); lineNumberEntry_type = make_node (RECORD_TYPE);
...@@ -665,7 +663,7 @@ init_decl_processing () ...@@ -665,7 +663,7 @@ init_decl_processing ()
PUSH_FIELD (method_type_node, field, "ncode", nativecode_ptr_type_node); PUSH_FIELD (method_type_node, field, "ncode", nativecode_ptr_type_node);
FINISH_RECORD (method_type_node); FINISH_RECORD (method_type_node);
CLASS_LOADED_P (method_type_node) = 1; 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, t = tree_cons (NULL_TREE, class_ptr_type,
build_tree_list (NULL_TREE, int_type_node)); build_tree_list (NULL_TREE, int_type_node));
......
...@@ -1431,6 +1431,32 @@ build_invokevirtual (dtable, method) ...@@ -1431,6 +1431,32 @@ build_invokevirtual (dtable, method)
return func; 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. /* Expand one of the invoke_* opcodes.
OCPODE is the specific opcode. OCPODE is the specific opcode.
METHOD_REF_INDEX is an index into the constant pool. METHOD_REF_INDEX is an index into the constant pool.
...@@ -1449,8 +1475,6 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1449,8 +1475,6 @@ expand_invoke (opcode, method_ref_index, nargs)
char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type))); char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
tree call, func, method, arg_list, method_type; tree call, func, method, arg_list, method_type;
static tree class_ident = NULL_TREE;
if (! CLASS_LOADED_P (self_type)) if (! CLASS_LOADED_P (self_type))
{ {
load_class (self_type, 1); load_class (self_type, 1);
...@@ -1522,30 +1546,7 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1522,30 +1546,7 @@ expand_invoke (opcode, method_ref_index, nargs)
if (opcode == OPCODE_invokevirtual) if (opcode == OPCODE_invokevirtual)
func = build_invokevirtual (dtable, method); func = build_invokevirtual (dtable, method);
else else
{ func = build_invokeinterface (dtable, method_name, method_signature);
/* 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 = build1 (NOP_EXPR, build_pointer_type (method_type), func); func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE); 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) ...@@ -1615,29 +1616,10 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
&& field_type == class_ptr_type && field_type == class_ptr_type
&& strncmp (self_name, "java.lang.", 10) == 0) && strncmp (self_name, "java.lang.", 10) == 0)
{ {
char *class_name = self_name+10; tree typ = build_primtype_type_ref (self_name);
tree typ; if (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)
{ {
push_value (build_class_ref (typ)); push_value (typ);
return; return;
} }
} }
...@@ -1672,6 +1654,36 @@ expand_java_field_op (is_static, is_putting, field_ref_index) ...@@ -1672,6 +1654,36 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
push_value (field_ref); 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 void
load_type_state (label) load_type_state (label)
tree label; tree label;
......
...@@ -70,3 +70,10 @@ DEFTREECODE (THROW_EXPR, "throw", '1', 1) ...@@ -70,3 +70,10 @@ DEFTREECODE (THROW_EXPR, "throw", '1', 1)
Operand 1 is the then-value Operand 1 is the then-value
Operand 2 is the else-value. */ Operand 2 is the else-value. */
DEFTREECODE (CONDITIONAL_EXPR, "?:", 'e', 3) 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; ...@@ -56,6 +56,7 @@ struct JCF;
IS_CRAFTED_STRING_BUFFER_P (in CALL_EXPR) IS_CRAFTED_STRING_BUFFER_P (in CALL_EXPR)
Usage of TYPE_LANG_FLAG_?: Usage of TYPE_LANG_FLAG_?:
0: CLASS_METHOD_CHECKED_P (in RECORD_TYPE)
1: TYPE_ARRAY_P (in RECORD_TYPE). 1: TYPE_ARRAY_P (in RECORD_TYPE).
2: CLASS_LOADED_P (in RECORD_TYPE). 2: CLASS_LOADED_P (in RECORD_TYPE).
3: CLASS_FROM_SOURCE_P (in RECORD_TYPE). 3: CLASS_FROM_SOURCE_P (in RECORD_TYPE).
...@@ -64,6 +65,9 @@ struct JCF; ...@@ -64,6 +65,9 @@ struct JCF;
6: CLASS_HAS_FINIT_P (in RECORD_TYPE) 6: CLASS_HAS_FINIT_P (in RECORD_TYPE)
Usage of DECL_LANG_FLAG_?: 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). 1: METHOD_PUBLIC (in FUNCTION_DECL).
FIELD_PUBLIC (in FIELD_DECL). FIELD_PUBLIC (in FIELD_DECL).
CLASS_PUBLIC (in TYPE_DECL). CLASS_PUBLIC (in TYPE_DECL).
...@@ -85,7 +89,7 @@ struct JCF; ...@@ -85,7 +89,7 @@ struct JCF;
LABEL_CHANGED (in LABEL_DECL) LABEL_CHANGED (in LABEL_DECL)
CLASS_SUPER (in TYPE_DECL, ACC_SUPER flag) CLASS_SUPER (in TYPE_DECL, ACC_SUPER flag)
INITIALIZED_P (in FIELD_DECL, VAR_DECL, PARM_DECL) 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. /* True if the class whose TYPE_BINFO this is has a superclass.
...@@ -396,6 +400,9 @@ struct lang_identifier ...@@ -396,6 +400,9 @@ struct lang_identifier
slot_number in decl_map. */ slot_number in decl_map. */
#define DECL_LOCAL_SLOT_CHAIN(NODE) \ #define DECL_LOCAL_SLOT_CHAIN(NODE) \
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->slot_chain) (((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. */ /* DECL_LANG_SPECIFIC for FUNCTION_DECLs. */
struct lang_decl struct lang_decl
...@@ -501,6 +508,7 @@ extern tree lookup_name PROTO ((tree)); ...@@ -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_known_method_ref PROTO ((tree, tree, tree, tree, tree));
extern tree build_class_init PROTO ((tree, tree)); extern tree build_class_init PROTO ((tree, tree));
extern tree build_invokevirtual 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 invoke_build_dtable PROTO ((int, tree));
extern tree build_field_ref PROTO ((tree, tree, tree)); extern tree build_field_ref PROTO ((tree, tree, tree));
extern void pushdecl_force_head PROTO ((tree)); extern void pushdecl_force_head PROTO ((tree));
...@@ -533,6 +541,7 @@ extern int alloc_name_constant PROTO ((int, tree)); ...@@ -533,6 +541,7 @@ extern int alloc_name_constant PROTO ((int, tree));
extern void emit_register_classes PROTO (()); extern void emit_register_classes PROTO (());
extern void lang_init_source PROTO ((int)); extern void lang_init_source PROTO ((int));
extern void write_classfile PROTO ((tree)); extern void write_classfile PROTO ((tree));
extern tree build_primtype_type_ref PROTO ((char *));
/* Access flags etc for a method (a FUNCTION_DECL): */ /* Access flags etc for a method (a FUNCTION_DECL): */
...@@ -570,6 +579,13 @@ extern void write_classfile PROTO ((tree)); ...@@ -570,6 +579,13 @@ extern void write_classfile PROTO ((tree));
#define CLASS_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL) #define CLASS_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL)
#define CLASS_SUPER(DECL) DECL_LANG_FLAG_6 (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. /* The number of virtual methods in this class's dispatch table.
Does not include initial two dummy entries (one points to the Does not include initial two dummy entries (one points to the
Class object, and the other is for G++ -fvtable-thunks compatibility). */ Class object, and the other is for G++ -fvtable-thunks compatibility). */
...@@ -657,6 +673,9 @@ extern tree *type_map; ...@@ -657,6 +673,9 @@ extern tree *type_map;
/* FIXME this use of TREE_TYPE conflicts with something or other. */ /* FIXME this use of TREE_TYPE conflicts with something or other. */
#define TYPE_ARRAY_ELEMENT(ATYPE) TREE_TYPE(ATYPE) #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. */ /* True if class TYPE has been loaded. */
#define CLASS_LOADED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE) #define CLASS_LOADED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE)
...@@ -801,7 +820,6 @@ extern tree *type_map; ...@@ -801,7 +820,6 @@ extern tree *type_map;
if (java_error_count) \ if (java_error_count) \
{ \ { \
java_report_errors (); \ java_report_errors (); \
java_pop_parser_context (0); \
return; \ return; \
} \ } \
} }
...@@ -64,15 +64,14 @@ tree main_class = NULL_TREE; ...@@ -64,15 +64,14 @@ tree main_class = NULL_TREE;
/* The FIELD_DECL for the current field. */ /* The FIELD_DECL for the current field. */
static tree current_field = NULL_TREE; static tree current_field = NULL_TREE;
/* The METHOD_DECL for the current method. */
static tree current_method = NULL_TREE; static tree current_method = NULL_TREE;
/* Declarations of some functions used here. */
static tree give_name_to_class PROTO ((JCF *jcf, int index)); static tree give_name_to_class PROTO ((JCF *jcf, int index));
void parse_zip_file_entries PROTO (());
void parse_zip_file_entries (void); void process_zip_dir PROTO (());
void process_zip_dir(); static void parse_source_file PROTO ((tree));
/* Source file compilation declarations */
static void parse_source_file ();
/* Handle "SourceFile" attribute. */ /* Handle "SourceFile" attribute. */
...@@ -506,14 +505,17 @@ int ...@@ -506,14 +505,17 @@ int
jcf_parse_source (jcf) jcf_parse_source (jcf)
JCF *jcf; JCF *jcf;
{ {
tree filename = get_identifier (input_filename); tree file;
java_parser_context_save_global ();
java_parser_context_save_global ();
java_push_parser_context ();
input_filename = current_jcf->filename; input_filename = current_jcf->filename;
file = get_identifier (input_filename);
if (!(finput = fopen (input_filename, "r"))) if (!(finput = fopen (input_filename, "r")))
fatal ("input file `%s' just disappeared - jcf_parse_source", fatal ("input file `%s' just disappeared - jcf_parse_source",
input_filename); 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 (); java_parser_context_restore_global ();
} }
...@@ -658,22 +660,16 @@ parse_class_file () ...@@ -658,22 +660,16 @@ parse_class_file ()
lineno = save_lineno; lineno = save_lineno;
} }
/* Parse a source file, as pointed by the current JCF. If PARSE_ONLY /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
is non zero, we're not parsing a file found on the command line and
we skip things related to code generation. */
static void static void
parse_source_file (parse_only) parse_source_file (file)
int parse_only; tree file;
{ {
int remember_for_generation;
tree filename = get_identifier (input_filename);
/* Mark the file as parsed */ /* 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 */ lang_init_source (1); /* Error msgs have no method prototypes */
java_push_parser_context ();
java_init_lex (); /* Initialize the parser */ java_init_lex (); /* Initialize the parser */
java_parse_abort_on_error (); java_parse_abort_on_error ();
java_parse (); /* Parse and build partial tree nodes. */ java_parse (); /* Parse and build partial tree nodes. */
...@@ -682,17 +678,6 @@ parse_source_file (parse_only) ...@@ -682,17 +678,6 @@ parse_source_file (parse_only)
java_parse_abort_on_error (); java_parse_abort_on_error ();
java_check_circular_reference (); /* Check on circular references */ java_check_circular_reference (); /* Check on circular references */
java_parse_abort_on_error (); 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 int
...@@ -775,7 +760,11 @@ yyparse () ...@@ -775,7 +760,11 @@ yyparse ()
parse_class_file (); parse_class_file ();
break; break;
case JCF_SOURCE: 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; break;
} }
} }
......
...@@ -706,7 +706,6 @@ emit_iinc (var, value, state) ...@@ -706,7 +706,6 @@ emit_iinc (var, value, state)
static void static void
emit_load_or_store (var, opcode, state) emit_load_or_store (var, opcode, state)
tree var; tree var;
int opcode;
struct jcf_partial *state; struct jcf_partial *state;
{ {
tree type = TREE_TYPE (var); tree type = TREE_TYPE (var);
......
...@@ -248,7 +248,7 @@ extern int jcf_unexpected_eof PROTO ((JCF*, int)); ...@@ -248,7 +248,7 @@ extern int jcf_unexpected_eof PROTO ((JCF*, int));
/* Debug macros, for the front end */ /* Debug macros, for the front end */
extern int quiet_flag; extern int quiet_flag;
#ifdef SOURCE_FRONTEND_DEBUG #ifdef VERBOSE_SKELETON
#undef SOURCE_FRONTEND_DEBUG #undef SOURCE_FRONTEND_DEBUG
#define SOURCE_FRONTEND_DEBUG(X) \ #define SOURCE_FRONTEND_DEBUG(X) \
{if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} } {if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} }
......
...@@ -22,11 +22,14 @@ Java and all Java-based marks are trademarks or registered trademarks ...@@ -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. of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc. */ 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 /* This is the contribution to the `lang_options' array in gcc.c for
java. */ 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", "" }, { "-fbounds-check", "" },
{ "-fno-bounds-check", "Disable automatic array bounds checking" }, { "-fno-bounds-check", "Disable automatic array bounds checking" },
{ "-fassume-compiled", "Make is_compiled_class return 1"}, { "-fassume-compiled", "Make is_compiled_class return 1"},
......
...@@ -368,6 +368,62 @@ java_parse_end_comment () ...@@ -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 /* This function to be used only by JAVA_ID_CHAR_P (), otherwise it
will return a wrong result. */ will return a wrong result. */
static int static int
...@@ -494,62 +550,8 @@ java_lex (java_lval) ...@@ -494,62 +550,8 @@ java_lex (java_lval)
{ {
if ((c = java_get_unicode ()) == '/') if ((c = java_get_unicode ()) == '/')
goto step1; /* Empy documentation comment */ goto step1; /* Empy documentation comment */
else if (java_parse_doc_section (c))
else goto step1;
/* 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 else
java_unget_unicode (); java_unget_unicode ();
...@@ -1206,6 +1208,7 @@ java_lex (java_lval) ...@@ -1206,6 +1208,7 @@ java_lex (java_lval)
case TRY_TK: case TRY_TK:
case CATCH_TK: case CATCH_TK:
case THROW_TK: case THROW_TK:
case INSTANCEOF_TK:
BUILD_OPERATOR (kw->token); BUILD_OPERATOR (kw->token);
default: default:
......
...@@ -35,13 +35,6 @@ extern int lineno; ...@@ -35,13 +35,6 @@ extern int lineno;
/* A Unicode character, as read from the input file */ /* A Unicode character, as read from the input file */
typedef unsigned short unicode_t; 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 */ /* Debug macro to print-out what we match */
#ifdef JAVA_LEX_DEBUG #ifdef JAVA_LEX_DEBUG
#ifdef JAVA_LEX_DEBUG_CHAR #ifdef JAVA_LEX_DEBUG_CHAR
...@@ -511,4 +504,23 @@ static tree build_wfl_node (); ...@@ -511,4 +504,23 @@ static tree build_wfl_node ();
#define JAVA_READ_BUFFER 256 #define JAVA_READ_BUFFER 256
#define UEOF (unicode_t)0xffff #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 #endif
...@@ -70,7 +70,6 @@ void ...@@ -70,7 +70,6 @@ void
emit_unicode_mangled_name (obstack, name, len) emit_unicode_mangled_name (obstack, name, len)
struct obstack *obstack; struct obstack *obstack;
char *name; char *name;
int len;
{ {
unsigned char *ptr; unsigned char *ptr;
unsigned char *limit = (unsigned char *)name + len; 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)); ...@@ -47,7 +47,7 @@ extern tree stabilize_reference PROTO ((tree));
#define RULE( rule ) #define RULE( rule )
#endif #endif
#ifdef SOURCE_FRONTEND_DEBUG #ifdef VERBOSE_SKELETON
#undef SOURCE_FRONTEND_DEBUG #undef SOURCE_FRONTEND_DEBUG
#define SOURCE_FRONTEND_DEBUG(X) \ #define SOURCE_FRONTEND_DEBUG(X) \
{if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} } {if (!quiet_flag) {printf ("* "); printf X; putchar ('\n');} }
...@@ -182,6 +182,8 @@ extern tree stabilize_reference PROTO ((tree)); ...@@ -182,6 +182,8 @@ extern tree stabilize_reference PROTO ((tree));
|| (TREE_CODE (TYPE) == POINTER_TYPE \ || (TREE_CODE (TYPE) == POINTER_TYPE \
&& TREE_CODE (TREE_TYPE (TYPE)) == \ && TREE_CODE (TREE_TYPE (TYPE)) == \
RECORD_TYPE))) RECORD_TYPE)))
#define JNULLP_TYPE_P(TYPE) ((TYPE) && (TREE_CODE (TYPE) == POINTER_TYPE) \
&& (TYPE) == TREE_TYPE (null_pointer_node))
/* Other predicate */ /* Other predicate */
#define DECL_P(NODE) (NODE && (TREE_CODE (NODE) == PARM_DECL \ #define DECL_P(NODE) (NODE && (TREE_CODE (NODE) == PARM_DECL \
...@@ -524,6 +526,32 @@ static jdeplist *reverse_jdep_list (); ...@@ -524,6 +526,32 @@ static jdeplist *reverse_jdep_list ();
return error_mark_node; \ 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. */ /* Parser context data structure. */
struct parser_ctxt { struct parser_ctxt {
...@@ -542,6 +570,7 @@ struct parser_ctxt { ...@@ -542,6 +570,7 @@ struct parser_ctxt {
int minus_seen; /* Integral literal overflow */ int minus_seen; /* Integral literal overflow */
int lineno; /* Current lineno */ int lineno; /* Current lineno */
int java_error_flag; /* Report error when true */ int java_error_flag; /* Report error when true */
int deprecated; /* @deprecated tag seen */
/* This section is defined only if we compile jc1 */ /* This section is defined only if we compile jc1 */
#ifndef JC1_LITE #ifndef JC1_LITE
...@@ -561,7 +590,9 @@ struct parser_ctxt { ...@@ -561,7 +590,9 @@ struct parser_ctxt {
tree incomplete_class; /* List of non-complete classes */ tree incomplete_class; /* List of non-complete classes */
tree current_parsed_class; /* Class currently parsed */ 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 class_list; /* List of classes in a CU */
tree gclass_list; /* All classes seen so far. */
jdeplist *classd_list; /* Classe dependencies in a CU */ jdeplist *classd_list; /* Classe dependencies in a CU */
tree non_static_initialized; /* List of non static initialized fields */ tree non_static_initialized; /* List of non static initialized fields */
...@@ -604,9 +635,11 @@ static void check_modifiers_consistency PROTO ((int)); ...@@ -604,9 +635,11 @@ static void check_modifiers_consistency PROTO ((int));
static tree lookup_cl PROTO ((tree)); static tree lookup_cl PROTO ((tree));
static tree lookup_java_method2 PROTO ((tree, tree, int)); static tree lookup_java_method2 PROTO ((tree, tree, int));
static tree method_header PROTO ((int, tree, tree, tree)); 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 tree method_declarator PROTO ((tree, tree));
static void parse_error_context VPROTO ((tree cl, char *msg, ...)); static void parse_error_context VPROTO ((tree cl, char *msg, ...));
static void parse_warning_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 tree parse_jdk1_1_error PROTO ((char *));
static void complete_class_report_errors PROTO ((jdep *)); static void complete_class_report_errors PROTO ((jdep *));
static int process_imports PROTO ((void)); static int process_imports PROTO ((void));
...@@ -614,6 +647,8 @@ static void read_import_dir PROTO ((tree)); ...@@ -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_on_demand PROTO ((tree));
static int find_in_imports PROTO ((tree)); static int find_in_imports PROTO ((tree));
static int check_pkg_class_access PROTO ((tree, 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 resolve_class PROTO ((tree, tree, tree));
static tree do_resolve_class PROTO ((tree, tree, tree)); static tree do_resolve_class PROTO ((tree, tree, tree));
static void declare_local_variables PROTO ((int, tree, tree)); static void declare_local_variables PROTO ((int, tree, tree));
...@@ -623,7 +658,7 @@ static void expand_start_java_method PROTO ((tree)); ...@@ -623,7 +658,7 @@ static void expand_start_java_method PROTO ((tree));
static tree find_name_in_single_imports PROTO ((tree)); static tree find_name_in_single_imports PROTO ((tree));
static void check_abstract_method_header PROTO ((tree)); static void check_abstract_method_header PROTO ((tree));
static tree lookup_java_interface_method2 PROTO ((tree, 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 tree maybe_create_class_interface_decl PROTO ((tree, tree, tree));
static int check_class_interface_creation PROTO ((int, int, tree, static int check_class_interface_creation PROTO ((int, int, tree,
tree, tree, tree)); tree, tree, tree));
...@@ -633,7 +668,8 @@ static int breakdown_qualified PROTO ((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_and_layout PROTO ((tree, tree));
static tree resolve_no_layout PROTO ((tree, tree)); static tree resolve_no_layout PROTO ((tree, tree));
static int invocation_mode PROTO ((tree, int)); 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 tree find_most_specific_methods_list PROTO ((tree));
static int argument_types_convertible PROTO ((tree, tree)); static int argument_types_convertible PROTO ((tree, tree));
static tree patch_invoke PROTO ((tree, tree, tree, int)); static tree patch_invoke PROTO ((tree, tree, tree, int));
...@@ -654,12 +690,14 @@ static tree build_method_invocation PROTO ((tree, tree)); ...@@ -654,12 +690,14 @@ static tree build_method_invocation PROTO ((tree, tree));
static tree build_new_invocation PROTO ((tree, tree)); static tree build_new_invocation PROTO ((tree, tree));
static tree build_assignment PROTO ((int, int, tree, tree)); static tree build_assignment PROTO ((int, int, tree, tree));
static tree build_binop PROTO ((enum tree_code, 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_assignment PROTO ((tree, tree, tree ));
static tree patch_binop PROTO ((tree, tree, tree)); static tree patch_binop PROTO ((tree, tree, tree));
static tree build_unaryop PROTO ((int, int, tree)); static tree build_unaryop PROTO ((int, int, tree));
static tree build_incdec PROTO ((int, int, tree, int)); static tree build_incdec PROTO ((int, int, tree, int));
static tree patch_unaryop PROTO ((tree, tree)); static tree patch_unaryop PROTO ((tree, tree));
static tree build_cast PROTO ((int, 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 tree patch_cast PROTO ((tree, tree));
static int valid_ref_assignconv_cast_p PROTO ((tree, tree, int)); static int valid_ref_assignconv_cast_p PROTO ((tree, tree, int));
static int valid_builtin_assignconv_identity_widening_p PROTO ((tree, tree)); static int valid_builtin_assignconv_identity_widening_p PROTO ((tree, tree));
...@@ -689,6 +727,7 @@ static tree maybe_access_field PROTO ((tree, tree, tree)); ...@@ -689,6 +727,7 @@ static tree maybe_access_field PROTO ((tree, tree, tree));
static int complete_function_arguments PROTO ((tree)); static int complete_function_arguments PROTO ((tree));
static int check_for_static_method_reference PROTO ((tree, tree, tree, tree, tree)); static int check_for_static_method_reference PROTO ((tree, tree, tree, tree, tree));
static int not_accessible_p PROTO ((tree, tree, int)); 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 int class_in_current_package PROTO ((tree));
static tree build_if_else_statement PROTO ((int, tree, tree, tree)); static tree build_if_else_statement PROTO ((int, tree, tree, tree));
static tree patch_if_else_statement PROTO ((tree)); static tree patch_if_else_statement PROTO ((tree));
...@@ -735,6 +774,11 @@ static tree create_artificial_method PROTO ((tree, int, tree, tree, 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 start_artificial_method_body PROTO ((tree));
static void end_artificial_method_body PROTO ((tree)); static void end_artificial_method_body PROTO ((tree));
static tree generate_field_initialization_code 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 safe_layout_class PROTO ((tree));
void java_complete_class PROTO ((void)); void java_complete_class PROTO ((void));
......
...@@ -67,6 +67,7 @@ definitions and other extensions. */ ...@@ -67,6 +67,7 @@ definitions and other extensions. */
#include "lex.h" #include "lex.h"
#include "parse.h" #include "parse.h"
#include "zipfile.h" #include "zipfile.h"
#include "convert.h"
/* Number of error found so far. */ /* Number of error found so far. */
int java_error_count; int java_error_count;
...@@ -248,7 +249,7 @@ static tree wfl_to_string = NULL_TREE; ...@@ -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> 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> 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> 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> THIS_TK SUPER_TK RETURN_TK BREAK_TK CONTINUE_TK
%type <operator> CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK %type <operator> CASE_TK DEFAULT_TK TRY_TK CATCH_TK SYNCHRONIZED_TK
...@@ -409,14 +410,11 @@ single_type_import_declaration: ...@@ -409,14 +410,11 @@ single_type_import_declaration:
($2, "Ambiguous class: `%s' and `%s'", ($2, "Ambiguous class: `%s' and `%s'",
IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (name),
IDENTIFIER_POINTER (err)); IDENTIFIER_POINTER (err));
}
else else
{ REGISTER_IMPORT ($2, last_name)
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;
} }
else
REGISTER_IMPORT ($2, last_name);
} }
| IMPORT_TK error | IMPORT_TK error
{yyerror ("Missing name"); RECOVER;} {yyerror ("Missing name"); RECOVER;}
...@@ -1936,6 +1934,7 @@ relational_expression: ...@@ -1936,6 +1934,7 @@ relational_expression:
$1, $3); $1, $3);
} }
| relational_expression INSTANCEOF_TK reference_type | relational_expression INSTANCEOF_TK reference_type
{ $$ = build_binop (INSTANCEOF_EXPR, $2.location, $1, $3); }
| relational_expression LT_TK error | relational_expression LT_TK error
{yyerror ("Missing term"); RECOVER;} {yyerror ("Missing term"); RECOVER;}
| relational_expression GT_TK error | relational_expression GT_TK error
...@@ -2098,7 +2097,10 @@ java_push_parser_context () ...@@ -2098,7 +2097,10 @@ java_push_parser_context ()
new->next = ctxp; new->next = ctxp;
ctxp = new; ctxp = new;
if (ctxp->next) 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 /* If the first file of a file list was a class file, no context
...@@ -2142,12 +2144,17 @@ java_pop_parser_context (generate) ...@@ -2142,12 +2144,17 @@ java_pop_parser_context (generate)
int generate; int generate;
{ {
tree current; tree current;
struct parser_ctxt *toFree = ctxp; struct parser_ctxt *toFree, *next;
struct parser_ctxt *next = ctxp->next;
if (!ctxp)
return;
toFree = ctxp;
next = ctxp->next;
if (next) if (next)
{ {
next->incomplete_class = ctxp->incomplete_class; next->incomplete_class = ctxp->incomplete_class;
next->gclass_list = ctxp->gclass_list;
lineno = ctxp->lineno; lineno = ctxp->lineno;
finput = ctxp->finput; finput = ctxp->finput;
current_class = ctxp->current_class; current_class = ctxp->current_class;
...@@ -2259,6 +2266,24 @@ parse_error (msg) ...@@ -2259,6 +2266,24 @@ parse_error (msg)
java_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 */ /* Issue an error message at a current source line CL */
static void static void
...@@ -2269,6 +2294,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...)) ...@@ -2269,6 +2294,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...))
char *msg; char *msg;
#endif #endif
char buffer [4096]; char buffer [4096];
char *saved;
va_list ap; va_list ap;
VA_START (ap, msg); VA_START (ap, msg);
...@@ -2279,10 +2305,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...)) ...@@ -2279,10 +2305,7 @@ parse_error_context VPROTO ((tree cl, char *msg, ...))
vsprintf (buffer, msg, ap); vsprintf (buffer, msg, ap);
force_error = 1; force_error = 1;
ctxp->elc.line = EXPR_WFL_LINENO (cl); issue_warning_error_from_context (cl, buffer);
ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl));
parse_error (buffer);
force_error = 0; force_error = 0;
} }
...@@ -2296,6 +2319,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) ...@@ -2296,6 +2319,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...))
char *msg; char *msg;
#endif #endif
char buffer [4096]; char buffer [4096];
char *saved;
va_list ap; va_list ap;
VA_START (ap, msg); VA_START (ap, msg);
...@@ -2306,10 +2330,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...)) ...@@ -2306,10 +2330,7 @@ parse_warning_context VPROTO ((tree cl, char *msg, ...))
vsprintf (buffer, msg, ap); vsprintf (buffer, msg, ap);
force_error = do_warning = 1; force_error = do_warning = 1;
ctxp->elc.line = EXPR_WFL_LINENO (cl); issue_warning_error_from_context (cl, buffer);
ctxp->elc.col = (EXPR_WFL_COLNO (cl) == 0xfff ? -1 : EXPR_WFL_COLNO (cl));
parse_error (buffer);
do_warning = force_error = 0; do_warning = force_error = 0;
} }
...@@ -2562,9 +2583,7 @@ static tree ...@@ -2562,9 +2583,7 @@ static tree
maybe_create_class_interface_decl (decl, qualified_name, cl) maybe_create_class_interface_decl (decl, qualified_name, cl)
tree decl, qualified_name, cl; tree decl, qualified_name, cl;
{ {
if (decl) if (!decl)
DECL_ARTIFICIAL (decl) = 1; /* FIXME */
else
decl = push_class (make_class (), qualified_name); decl = push_class (make_class (), qualified_name);
/* Take care of the file and line business */ /* Take care of the file and line business */
...@@ -2579,6 +2598,10 @@ maybe_create_class_interface_decl (decl, qualified_name, cl) ...@@ -2579,6 +2598,10 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
/* Link the declaration to the already seen ones */ /* Link the declaration to the already seen ones */
TREE_CHAIN (decl) = ctxp->class_list; TREE_CHAIN (decl) = ctxp->class_list;
ctxp->class_list = decl; ctxp->class_list = decl;
/* Create a new node in the global list */
ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
/* Install a new dependency list element */ /* Install a new dependency list element */
create_jdep_list (ctxp); create_jdep_list (ctxp);
...@@ -2602,10 +2625,11 @@ add_superinterfaces (decl, interface_list) ...@@ -2602,10 +2625,11 @@ add_superinterfaces (decl, interface_list)
for (node = interface_list; node; node = TREE_CHAIN (node)) for (node = interface_list; node; node = TREE_CHAIN (node))
{ {
tree current = TREE_PURPOSE (node), interface_decl; 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)) if (!parser_check_super_interface (idecl, decl, current))
parser_add_interface (decl, interface_decl, current); parser_add_interface (decl, idecl, current);
} }
else else
register_incomplete_type (JDEP_INTERFACE, register_incomplete_type (JDEP_INTERFACE,
...@@ -2673,6 +2697,7 @@ create_class (flags, id, super, interfaces) ...@@ -2673,6 +2697,7 @@ create_class (flags, id, super, interfaces)
class_id = parser_qualified_classname (id); class_id = parser_qualified_classname (id);
decl = IDENTIFIER_CLASS_VALUE (class_id); decl = IDENTIFIER_CLASS_VALUE (class_id);
ctxp->current_parsed_class_un = EXPR_WFL_NODE (id);
EXPR_WFL_NODE (id) = class_id; EXPR_WFL_NODE (id) = class_id;
/* Basic check: scope, redefinition, modifiers */ /* Basic check: scope, redefinition, modifiers */
...@@ -2725,6 +2750,9 @@ create_class (flags, id, super, interfaces) ...@@ -2725,6 +2750,9 @@ create_class (flags, id, super, interfaces)
CLASS_COMPLETE_P (decl) = 1; CLASS_COMPLETE_P (decl) = 1;
add_superinterfaces (decl, interfaces); add_superinterfaces (decl, interfaces);
/* Eventually sets the @deprecated tag flag */
CHECK_DEPRECATED (decl);
return decl; return decl;
} }
...@@ -2854,9 +2882,10 @@ register_fields (flags, type, variable_list) ...@@ -2854,9 +2882,10 @@ register_fields (flags, type, variable_list)
} }
/* Set lineno to the line the field was found and create a /* 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); lineno = EXPR_WFL_LINENO (cl);
field_decl = add_field (class_type, current_name, type, flags); field_decl = add_field (class_type, current_name, type, flags);
CHECK_DEPRECATED (field_decl);
/* Check if we must chain. */ /* Check if we must chain. */
if (must_chain) if (must_chain)
...@@ -2873,12 +2902,16 @@ register_fields (flags, type, variable_list) ...@@ -2873,12 +2902,16 @@ register_fields (flags, type, variable_list)
/* The field is declared static */ /* The field is declared static */
if (flags & ACC_STATIC) if (flags & ACC_STATIC)
{ {
/* FIXME */
if (flags & ACC_FINAL) if (flags & ACC_FINAL)
; {
/* Otherwise, the field should be initialized in if (DECL_LANG_SPECIFIC (field_decl) == NULL)
<clinit>. This field is remembered so we can DECL_LANG_SPECIFIC (field_decl) = (struct lang_decl *)
generate <clinit> later. */ 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 else
{ {
INITIALIZED_P (field_decl) = 1; INITIALIZED_P (field_decl) = 1;
...@@ -2886,10 +2919,9 @@ register_fields (flags, type, variable_list) ...@@ -2886,10 +2919,9 @@ register_fields (flags, type, variable_list)
ctxp->static_initialized = init; ctxp->static_initialized = init;
} }
} }
/* A non-static field declared with an immediate /* A non-static field declared with an immediate initialization is
initialization is to be initialized in <init>, if to be initialized in <init>, if any. This field is remembered
any. This field is remembered to be processed at the to be processed at the time of the generation of <init>. */
time of the generation of <init>. */
else else
{ {
INITIALIZED_P (field_decl) = 1; INITIALIZED_P (field_decl) = 1;
...@@ -2986,7 +3018,7 @@ method_header (flags, type, mdecl, throws) ...@@ -2986,7 +3018,7 @@ method_header (flags, type, mdecl, throws)
tree meth = TREE_VALUE (mdecl); tree meth = TREE_VALUE (mdecl);
tree id = TREE_PURPOSE (mdecl); tree id = TREE_PURPOSE (mdecl);
tree this_class = TREE_TYPE (ctxp->current_parsed_class); 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 saved_lineno;
int constructor_ok = 0; int constructor_ok = 0;
...@@ -3014,7 +3046,7 @@ method_header (flags, type, mdecl, throws) ...@@ -3014,7 +3046,7 @@ method_header (flags, type, mdecl, throws)
int ec = java_error_count; int ec = java_error_count;
/* 8.6: Constructor declarations: we might be trying to define a /* 8.6: Constructor declarations: we might be trying to define a
method without specifying a return type. */ 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 parse_error_context
(id, "Invalid method declaration, return type required"); (id, "Invalid method declaration, return type required");
/* 8.6.3: Constructor modifiers */ /* 8.6.3: Constructor modifiers */
...@@ -3077,7 +3109,11 @@ method_header (flags, type, mdecl, throws) ...@@ -3077,7 +3109,11 @@ method_header (flags, type, mdecl, throws)
} }
} }
else else
{
if (TREE_CODE (type) == RECORD_TYPE)
type = promote_type (type);
TREE_TYPE (meth) = type; TREE_TYPE (meth) = type;
}
saved_lineno = lineno; saved_lineno = lineno;
/* When defining an abstract or interface method, the curly /* When defining an abstract or interface method, the curly
...@@ -3086,6 +3122,9 @@ method_header (flags, type, mdecl, throws) ...@@ -3086,6 +3122,9 @@ method_header (flags, type, mdecl, throws)
lineno = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 : lineno = (ctxp->first_ccb_indent1 ? ctxp->first_ccb_indent1 :
EXPR_WFL_LINENO (id)); 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 */ if (patch_stage) /* includes ret type and/or all args */
{ {
jdep *jdep; jdep *jdep;
...@@ -3101,28 +3140,15 @@ method_header (flags, type, mdecl, throws) ...@@ -3101,28 +3140,15 @@ method_header (flags, type, mdecl, throws)
register_incomplete_type (JDEP_METHOD_END, NULL_TREE, meth, NULL_TREE); register_incomplete_type (JDEP_METHOD_END, NULL_TREE, meth, NULL_TREE);
} }
else else
{ meth = add_method (this_class, flags, meth_name,
tree signature = build_java_signature (meth); 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 /* Fix the method argument list so we have the argument name
information */ information */
arg = TYPE_ARG_TYPES (TREE_TYPE (meth)); fix_method_argument_names (orig_arg, meth);
if (TREE_CODE (TREE_TYPE (meth)) == METHOD_TYPE)
{ /* Register the parameter number and re-install the current line
TREE_PURPOSE (arg) = this_identifier_node; number */
arg = TREE_CHAIN (arg);
}
while (orig_arg)
{
TREE_PURPOSE (arg) = TREE_PURPOSE (orig_arg);
orig_arg = TREE_CHAIN (orig_arg);
arg = TREE_CHAIN (arg);
}
}
DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1; DECL_MAX_LOCALS (meth) = ctxp->formal_parameter_number+1;
lineno = saved_lineno; lineno = saved_lineno;
...@@ -3157,9 +3183,30 @@ method_header (flags, type, mdecl, throws) ...@@ -3157,9 +3183,30 @@ method_header (flags, type, mdecl, throws)
if (constructor_ok) if (constructor_ok)
DECL_CONSTRUCTOR_P (meth) = 1; DECL_CONSTRUCTOR_P (meth) = 1;
/* Eventually set the @deprecated tag flag */
CHECK_DEPRECATED (meth);
return 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. */ /* Complete the method declaration with METHOD_BODY. */
static void static void
...@@ -3305,6 +3352,9 @@ method_declarator (id, list) ...@@ -3305,6 +3352,9 @@ method_declarator (id, list)
type = build_array_from_name (type, type_wfl, name, &name); type = build_array_from_name (type, type_wfl, name, &name);
EXPR_WFL_NODE (wfl_name) = name; EXPR_WFL_NODE (wfl_name) = name;
if (TREE_CODE (type) == RECORD_TYPE)
type = promote_type (type);
/* Check redefinition */ /* Check redefinition */
for (already = arg_types; already; already = TREE_CHAIN (already)) for (already = arg_types; already; already = TREE_CHAIN (already))
if (TREE_PURPOSE (already) == name) if (TREE_PURPOSE (already) == name)
...@@ -3564,11 +3614,17 @@ void ...@@ -3564,11 +3614,17 @@ void
safe_layout_class (class) safe_layout_class (class)
tree class; tree class;
{ {
tree list;
tree save_current_class = current_class; tree save_current_class = current_class;
char *save_input_filename = input_filename; char *save_input_filename = input_filename;
int save_lineno = lineno; int save_lineno = lineno;
push_obstacks (&permanent_obstack, &permanent_obstack); 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); layout_class (class);
pop_obstacks (); pop_obstacks ();
...@@ -3655,6 +3711,8 @@ java_complete_class () ...@@ -3655,6 +3711,8 @@ java_complete_class ()
field_type = promote_type (field_type); field_type = promote_type (field_type);
pop_obstacks (); pop_obstacks ();
TREE_TYPE (field_decl) = field_type; TREE_TYPE (field_decl) = field_type;
DECL_ALIGN (field_decl) = 0;
layout_decl (field_decl, 0);
SOURCE_FRONTEND_DEBUG SOURCE_FRONTEND_DEBUG
(("Completed field/var decl `%s' with `%s'", (("Completed field/var decl `%s' with `%s'",
IDENTIFIER_POINTER (DECL_NAME (field_decl)), IDENTIFIER_POINTER (DECL_NAME (field_decl)),
...@@ -3817,7 +3875,6 @@ do_resolve_class (class_type, decl, cl) ...@@ -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, /* 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. */ try with a name qualified with the package name if appropriate. */
if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type)))) if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
{ {
if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) && if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
...@@ -3830,6 +3887,8 @@ do_resolve_class (class_type, decl, cl) ...@@ -3830,6 +3887,8 @@ do_resolve_class (class_type, decl, cl)
if (!QUALIFIED_P (TYPE_NAME (class_type)) && ctxp->package) if (!QUALIFIED_P (TYPE_NAME (class_type)) && ctxp->package)
TYPE_NAME (class_type) = merge_qualified_name (ctxp->package, TYPE_NAME (class_type) = merge_qualified_name (ctxp->package,
TYPE_NAME (class_type)); 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 ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
{ {
if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) && if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
...@@ -3984,9 +4043,7 @@ get_printable_method_name (decl) ...@@ -3984,9 +4043,7 @@ get_printable_method_name (decl)
if (DECL_CONSTRUCTOR_P (decl)) if (DECL_CONSTRUCTOR_P (decl))
{ {
name = DECL_NAME (decl); name = DECL_NAME (decl);
DECL_NAME (decl) = DECL_NAME (decl) = DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)));
DECL_NAME (ctxp->current_parsed_class ?
ctxp->current_parsed_class : current_class);
} }
to_return = lang_printable_name (decl, 0); to_return = lang_printable_name (decl, 0);
...@@ -3996,6 +4053,28 @@ get_printable_method_name (decl) ...@@ -3996,6 +4053,28 @@ get_printable_method_name (decl)
return to_return; 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 /* Track method being redefined inside the same class. As a side
effect, set DECL_NAME to an IDENTIFIER (prior entering this effect, set DECL_NAME to an IDENTIFIER (prior entering this
function it's a FWL, so we can track errors more accurately */ function it's a FWL, so we can track errors more accurately */
...@@ -4009,20 +4088,15 @@ check_method_redefinition (class, method) ...@@ -4009,20 +4088,15 @@ check_method_redefinition (class, method)
tree sig = TYPE_LANG_SPECIFIC (TREE_TYPE (method))->signature; tree sig = TYPE_LANG_SPECIFIC (TREE_TYPE (method))->signature;
/* decl name of artificial <clinit> and <finit> doesn't need to be fixed and /* decl name of artificial <clinit> and <finit> doesn't need to be fixed and
checked */ checked */
if (DECL_NAME (method) != clinit_identifier_node
&& DECL_NAME (method) != finit_identifier_node) /* Reset the method name before running the check. If it returns 1,
{ the method doesn't need to be verified with respect to method
/* NAME is just the plain name when Object is being defined */ redeclaration and we return 0 */
if (class != object_type_node) if (reset_method_name (method))
name = DECL_NAME (method) = (DECL_CONSTRUCTOR_P (method) ?
init_identifier_node :
EXPR_WFL_NODE (DECL_NAME (method)));
else
name = DECL_NAME (method);
}
else
return 0; return 0;
name = DECL_NAME (method);
for (redef = TYPE_METHODS (class); redef; redef = TREE_CHAIN (redef)) for (redef = TYPE_METHODS (class); redef; redef = TREE_CHAIN (redef))
{ {
struct lang_type *t = TYPE_LANG_SPECIFIC (TREE_TYPE (redef)); struct lang_type *t = TYPE_LANG_SPECIFIC (TREE_TYPE (redef));
...@@ -4049,20 +4123,26 @@ static void ...@@ -4049,20 +4123,26 @@ static void
java_check_regular_methods (class_decl) java_check_regular_methods (class_decl)
tree class_decl; tree class_decl;
{ {
int saw_constructor = 0;
tree method; tree method;
tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl)); tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl));
tree super_class = CLASSTYPE_SUPER (class); 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)); TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
/* Should take interfaces into account. FIXME */ /* Should take interfaces into account. FIXME */
for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method)) for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
{ {
tree found, sig; tree sig;
tree method_wfl = DECL_NAME (method); tree method_wfl = DECL_NAME (method);
int aflags; 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 */ /* Check for redefinitions */
if (check_method_redefinition (class, method)) if (check_method_redefinition (class, method))
continue; continue;
...@@ -4077,12 +4157,17 @@ java_check_regular_methods (class_decl) ...@@ -4077,12 +4157,17 @@ java_check_regular_methods (class_decl)
} }
sig = build_java_argument_signature (TREE_TYPE (method)); sig = build_java_argument_signature (TREE_TYPE (method));
found = lookup_argument_method (super_class, DECL_NAME (method), sig); 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))) 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 /* Can't override a method with the same name and different return
types. */ types. */
if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method))) if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method)))
...@@ -4126,19 +4211,27 @@ java_check_regular_methods (class_decl) ...@@ -4126,19 +4211,27 @@ java_check_regular_methods (class_decl)
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
continue; continue;
} }
/* Overriding/hiding public must be public or
overriding/hiding protected must be protected or public */ aflags = get_access_flags_from_decl (found);
if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) || /* - Overriding/hiding public must be public
(METHOD_PROTECTED (found) - Overriding/hiding protected must be protected or public
&& !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method)))) - 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 parse_error_context
(method_wfl, (method_wfl,
"Methods can't be overridden to be more private. Method `%s' is " "Methods can't be overridden to be more private. Method `%s' is "
"%s in class `%s'", lang_printable_name (found, 0), "not %s in class `%s'", lang_printable_name (method, 0),
(METHOD_PUBLIC (found) ? "public" : "protected"), (METHOD_PUBLIC (method) ? "public" :
IDENTIFIER_POINTER (METHOD_PRIVATE (method) ? "private" : "protected")),
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); IDENTIFIER_POINTER (DECL_NAME
(TYPE_NAME (DECL_CONTEXT (found)))));
continue; continue;
} }
...@@ -4148,9 +4241,10 @@ java_check_regular_methods (class_decl) ...@@ -4148,9 +4241,10 @@ java_check_regular_methods (class_decl)
/* If the method has default access in an other package, then /* If the method has default access in an other package, then
issue a warning that the current method doesn't override the issue a warning that the current method doesn't override the
one that was found elsewhere */ one that was found elsewhere. Do not issue this warning when
aflags = get_access_flags_from_decl (found); the match was found in java.lang.Object. */
if ((!aflags || (aflags > ACC_PROTECTED)) if (DECL_CONTEXT (found) != object_type_node
&& (!aflags || (aflags > ACC_PROTECTED))
&& !class_in_current_package (DECL_CONTEXT (found))) && !class_in_current_package (DECL_CONTEXT (found)))
parse_warning_context parse_warning_context
(method_wfl, "Method `%s' in class `%s' does not " (method_wfl, "Method `%s' in class `%s' does not "
...@@ -4160,10 +4254,16 @@ java_check_regular_methods (class_decl) ...@@ -4160,10 +4254,16 @@ java_check_regular_methods (class_decl)
IDENTIFIER_POINTER (DECL_NAME (class_decl)), IDENTIFIER_POINTER (DECL_NAME (class_decl)),
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
/* Check on (default) package access. FIXME. */
/* Inheriting multiple methods with the same signature. 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)); TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
if (!saw_constructor) if (!saw_constructor)
...@@ -4220,11 +4320,12 @@ check_throws_clauses (method, method_wfl, found) ...@@ -4220,11 +4320,12 @@ check_throws_clauses (method, method_wfl, found)
/* Check abstract method of interface INTERFACE */ /* Check abstract method of interface INTERFACE */
static void static void
java_check_abstract_methods (interface) java_check_abstract_methods (interface_decl)
tree interface; tree interface_decl;
{ {
int i, n; int i, n;
tree method, basetype_vec, found; tree method, basetype_vec, found;
tree interface = TREE_TYPE (interface_decl);
for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method)) for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method))
{ {
...@@ -4239,16 +4340,20 @@ java_check_abstract_methods (interface) ...@@ -4239,16 +4340,20 @@ java_check_abstract_methods (interface)
found = lookup_java_interface_method2 (interface, method); found = lookup_java_interface_method2 (interface, method);
if (found) if (found)
{ {
char *t = strdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), char *t;
0)); 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 parse_error_context
(method_wfl, (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, lang_printable_name (found, 0), t,
IDENTIFIER_POINTER IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
free (t); free (t);
continue; continue;
DECL_NAME (found) = saved_found_wfl;
} }
} }
...@@ -4270,37 +4375,39 @@ java_check_abstract_methods (interface) ...@@ -4270,37 +4375,39 @@ java_check_abstract_methods (interface)
found = lookup_java_interface_method2 (interface, found = lookup_java_interface_method2 (interface,
sub_interface_method); sub_interface_method);
if (found && (found != sub_interface_method)) if (found && (found != sub_interface_method))
{
tree saved_found_wfl = DECL_NAME (found);
reset_method_name (found);
parse_error_context parse_error_context
(lookup_cl (sub_interface_method), (lookup_cl (sub_interface_method),
"Interface `%s' inherits method `%s' from interface `%s'. This " "Interface `%s' inherits method `%s' from interface `%s'. "
"method is redefined with a different return " "This method is redefined with a different return type in "
"type in interface `%s'", "interface `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (interface))), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (interface))),
lang_printable_name (found, 0), lang_printable_name (found, 0),
IDENTIFIER_POINTER IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (sub_interface_method)))), (DECL_NAME (TYPE_NAME
(DECL_CONTEXT (sub_interface_method)))),
IDENTIFIER_POINTER IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); (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 /* Check the method on all the defined classes. Process all the
classes declared in the compilation unit only. FIXME */ classes that we compiled from source code for this CU. */
void void
java_check_methods () java_check_methods ()
{ {
tree current; tree current;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
if (CLASS_FROM_SOURCE_P (TREE_TYPE (current))) if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
{ {
tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (current)); CHECK_METHODS (TREE_VALUE (current));
CLASS_METHOD_CHECKED_P (TREE_TYPE (TREE_VALUE (current))) = 1;
if (CLASS_INTERFACE (TYPE_NAME (class)))
java_check_abstract_methods (class);
else
java_check_regular_methods (current);
} }
} }
...@@ -4345,9 +4452,12 @@ lookup_java_method2 (clas, method_decl, do_interface) ...@@ -4345,9 +4452,12 @@ lookup_java_method2 (clas, method_decl, do_interface)
tree clas, method_decl; tree clas, method_decl;
int do_interface; 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_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)); method_type = TREE_TYPE (TREE_TYPE (method_decl));
while (clas != NULL_TREE) while (clas != NULL_TREE)
...@@ -4356,13 +4466,13 @@ lookup_java_method2 (clas, method_decl, do_interface) ...@@ -4356,13 +4466,13 @@ lookup_java_method2 (clas, method_decl, do_interface)
method != NULL_TREE; method = TREE_CHAIN (method)) method != NULL_TREE; method = TREE_CHAIN (method))
{ {
tree method_sig = build_java_argument_signature (TREE_TYPE (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 && method_sig == method_signature
&& TREE_TYPE (TREE_TYPE (method)) != method_type) && TREE_TYPE (TREE_TYPE (method)) != method_type)
{
return method; return method;
} }
}
clas = (do_interface ? NULL_TREE : CLASSTYPE_SUPER (clas)); clas = (do_interface ? NULL_TREE : CLASSTYPE_SUPER (clas));
} }
return NULL_TREE; return NULL_TREE;
...@@ -4450,8 +4560,6 @@ find_in_imports (class_type) ...@@ -4450,8 +4560,6 @@ find_in_imports (class_type)
{ {
TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import)); TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import));
QUALIFIED_P (TYPE_NAME (class_type)) = 1; QUALIFIED_P (TYPE_NAME (class_type)) = 1;
return check_pkg_class_access (TYPE_NAME (class_type),
TREE_PURPOSE (import));
} }
return 0; return 0;
} }
...@@ -4675,6 +4783,50 @@ find_in_imports_on_demand (class_type) ...@@ -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 */ 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 /* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no
access violations were found, 1 otherwise. */ access violations were found, 1 otherwise. */
...@@ -5021,16 +5173,21 @@ add_stmt_to_compound (existing, type, stmt) ...@@ -5021,16 +5173,21 @@ add_stmt_to_compound (existing, type, stmt)
/* Hold THIS for the scope of the current public method decl. */ /* Hold THIS for the scope of the current public method decl. */
static tree current_this; static tree current_this;
/* Layout all class found during parsing. Also fixes the order of /* Layout all class found during parsing. Also fixes the order of some
several field related lists. */ lists. */
void void
java_layout_classes () java_layout_classes ()
{ {
tree current; 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 /* Reverse the fields if it's necessary (they've already
reversed if the dummy field has been inserted at the reversed if the dummy field has been inserted at the
...@@ -5042,6 +5199,10 @@ java_layout_classes () ...@@ -5042,6 +5199,10 @@ java_layout_classes ()
/* Do a layout if necessary */ /* Do a layout if necessary */
if (!TYPE_SIZE (current_class) || (current_class == object_type_node)) if (!TYPE_SIZE (current_class) || (current_class == object_type_node))
safe_layout_class (current_class); safe_layout_class (current_class);
/* Error reported by the caller */
if (java_error_count)
return;
} }
} }
...@@ -5080,6 +5241,8 @@ java_complete_expand_methods () ...@@ -5080,6 +5241,8 @@ java_complete_expand_methods ()
restore_line_number_status (0); restore_line_number_status (0);
} }
} }
else if (METHOD_ABSTRACT (decl) || METHOD_NATIVE (decl))
continue;
else else
java_complete_expand_method (decl); java_complete_expand_method (decl);
} }
...@@ -5135,6 +5298,7 @@ java_complete_expand_method (mdecl) ...@@ -5135,6 +5298,7 @@ java_complete_expand_method (mdecl)
if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl))) if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)))
java_complete_tree (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 /* Don't go any further if we've found error(s) during the
expansion */ expansion */
if (!java_error_count) if (!java_error_count)
...@@ -5294,6 +5458,13 @@ java_expand_finals () ...@@ -5294,6 +5458,13 @@ java_expand_finals ()
void void
java_expand_classes () 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) for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
{ {
ctxp = ctxp_for_generation; ctxp = ctxp_for_generation;
...@@ -5425,8 +5596,9 @@ cut_identifier_in_qualified (wfl) ...@@ -5425,8 +5596,9 @@ cut_identifier_in_qualified (wfl)
/* Resolve the expression name NAME. Return its decl. */ /* Resolve the expression name NAME. Return its decl. */
static tree static tree
resolve_expression_name (id) resolve_expression_name (id, orig)
tree id; tree id;
tree *orig;
{ {
tree name = EXPR_WFL_NODE (id); tree name = EXPR_WFL_NODE (id);
tree decl; tree decl;
...@@ -5445,6 +5617,7 @@ resolve_expression_name (id) ...@@ -5445,6 +5617,7 @@ resolve_expression_name (id)
decl = lookup_field_wrapper (current_class, name); decl = lookup_field_wrapper (current_class, name);
if (decl) if (decl)
{ {
tree value = NULL_TREE;
int fs = FIELD_STATIC (decl); int fs = FIELD_STATIC (decl);
/* Instance variable (8.3.1.1) can't appear within /* Instance variable (8.3.1.1) can't appear within
static method, static initializer or initializer for static method, static initializer or initializer for
...@@ -5468,9 +5641,20 @@ resolve_expression_name (id) ...@@ -5468,9 +5641,20 @@ resolve_expression_name (id)
"constructor has been called", IDENTIFIER_POINTER (name)); "constructor has been called", IDENTIFIER_POINTER (name));
return error_mark_node; 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), decl = build_field_ref ((fs ? NULL_TREE : current_this),
current_class, name); 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 */ /* Fall down to error report on undefined variable */
} }
...@@ -5478,6 +5662,8 @@ resolve_expression_name (id) ...@@ -5478,6 +5662,8 @@ resolve_expression_name (id)
/* 6.5.5.2 Qualified Expression Names */ /* 6.5.5.2 Qualified Expression Names */
else else
{ {
if (orig)
*orig = NULL_TREE;
qualify_ambiguous_name (id); qualify_ambiguous_name (id);
/* 15.10.1 Field Access Using a Primary and/or Expression Name */ /* 15.10.1 Field Access Using a Primary and/or Expression Name */
/* 15.10.2: Accessing Superclass Members using super */ /* 15.10.2: Accessing Superclass Members using super */
...@@ -5523,12 +5709,24 @@ resolve_field_access (qual_wfl, field_decl, field_type) ...@@ -5523,12 +5709,24 @@ resolve_field_access (qual_wfl, field_decl, field_type)
field_ref = decl; field_ref = decl;
else if (DECL_P (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); is_static = DECL_P (decl) && FIELD_STATIC (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), field_ref = build_field_ref ((is_static ? NULL_TREE : where_found),
type_found, DECL_NAME (decl)); type_found, DECL_NAME (decl));
if (field_ref == error_mark_node) if (field_ref == error_mark_node)
return 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); field_ref = build_class_init (type_found, field_ref);
/* If the static field was identified by an expression that /* 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) ...@@ -5571,7 +5769,6 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
tree qual_wfl = QUAL_WFL (q); tree qual_wfl = QUAL_WFL (q);
/* 15.10.1 Field Access Using a Primary */ /* 15.10.1 Field Access Using a Primary */
switch (TREE_CODE (qual_wfl)) switch (TREE_CODE (qual_wfl))
{ {
case CALL_EXPR: case CALL_EXPR:
...@@ -5619,6 +5816,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5619,6 +5816,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
continue; continue;
case CONDITIONAL_EXPR: case CONDITIONAL_EXPR:
case STRING_CST:
*where_found = decl = java_complete_tree (qual_wfl); *where_found = decl = java_complete_tree (qual_wfl);
if (decl == error_mark_node) if (decl == error_mark_node)
return 1; return 1;
...@@ -5660,7 +5858,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5660,7 +5858,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
} }
/* We have to generate code for intermediate acess */ /* We have to generate code for intermediate acess */
*where_found = decl = current_this; *where_found = decl = current_this;
type = QUAL_DECL_TYPE (decl); *type_found = type = QUAL_DECL_TYPE (decl);
continue; continue;
} }
...@@ -5692,6 +5890,21 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5692,6 +5890,21 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
assume a variable/class name was meant. */ assume a variable/class name was meant. */
if (RESOLVE_PACKAGE_NAME_P (qual_wfl)) if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
{ {
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
{
if (from_super || from_cast) if (from_super || from_cast)
parse_error_context parse_error_context
((from_cast ? qual_wfl : wfl), ((from_cast ? qual_wfl : wfl),
...@@ -5704,6 +5917,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5704,6 +5917,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl))); IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)));
return 1; return 1;
} }
}
/* We have a type name. It's been already resolved when the /* We have a type name. It's been already resolved when the
expression was qualified. */ expression was qualified. */
...@@ -5722,6 +5936,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5722,6 +5936,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
return 1; return 1;
} }
check_deprecation (qual_wfl, decl);
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
from_type = 1; from_type = 1;
...@@ -5738,18 +5953,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5738,18 +5953,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
if (!from_super && QUAL_RESOLUTION (q)) if (!from_super && QUAL_RESOLUTION (q))
{ {
decl = QUAL_RESOLUTION (q); decl = QUAL_RESOLUTION (q);
if (!type && !FIELD_STATIC (decl))
{
*where_found = current_this;
*type_found = type; *type_found = type;
} }
}
/* We have to search for a field, knowing the type of its /* We have to search for a field, knowing the type of its
container. The flag FROM_TYPE indicates that we resolved container. The flag FROM_TYPE indicates that we resolved
the last member of the expression as a type name, which the last member of the expression as a type name, which
means that for the resolution of this field, will check means that for the resolution of this field, we'll look
on other errors than if the it was resolved as a member for other errors than if it was resolved as a member of
of an other field. */ an other field. */
else else
{ {
int is_static; int is_static;
tree field_decl_type; /* For layout */
if (!from_type && !JREFERENCE_TYPE_P (type)) if (!from_type && !JREFERENCE_TYPE_P (type))
{ {
parse_error_context parse_error_context
...@@ -5770,6 +5991,17 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5770,6 +5991,17 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
return 1; 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 */ /* Check on accessibility here */
if (not_accessible_p (type, field_decl, from_super)) if (not_accessible_p (type, field_decl, from_super))
{ {
...@@ -5784,6 +6016,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5784,6 +6016,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
(DECL_NAME (TYPE_NAME (current_class)))); (DECL_NAME (TYPE_NAME (current_class))));
return 1; return 1;
} }
check_deprecation (qual_wfl, field_decl);
/* There are things to check when fields are accessed /* There are things to check when fields are accessed
from type. There are no restrictions on a static from type. There are no restrictions on a static
...@@ -5802,8 +6035,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) ...@@ -5802,8 +6035,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
} }
from_cast = from_super = 0; from_cast = from_super = 0;
/* If we need to generate something to get a proper handle /* If we need to generate something to get a proper
on what this field is accessed from, do it now. */ handle on what this field is accessed from, do it
now. */
if (!is_static) if (!is_static)
{ {
decl = maybe_access_field (decl, *where_found, *type_found); decl = maybe_access_field (decl, *where_found, *type_found);
...@@ -5889,6 +6123,38 @@ int not_accessible_p (reference, member, from_super) ...@@ -5889,6 +6123,38 @@ int not_accessible_p (reference, member, from_super)
return 0; 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 */ /* Returns 1 if class was declared in the current package, 0 otherwise */
static int static int
...@@ -5933,10 +6199,8 @@ static tree ...@@ -5933,10 +6199,8 @@ static tree
maybe_access_field (decl, where, type) maybe_access_field (decl, where, type)
tree decl, where, type; tree decl, where, type;
{ {
if (DECL_P (decl) && decl != current_this if (TREE_CODE (decl) == FIELD_DECL && decl != current_this
&& (!(TREE_CODE (decl) != PARM_DECL && !FIELD_STATIC (decl))
&& FIELD_STATIC (decl)))
&& !IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
decl = build_field_ref (where ? where : current_this, decl = build_field_ref (where ? where : current_this,
(type ? type : DECL_CONTEXT (decl)), (type ? type : DECL_CONTEXT (decl)),
DECL_NAME (decl)); DECL_NAME (decl));
...@@ -5957,7 +6221,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) ...@@ -5957,7 +6221,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
tree wfl = TREE_OPERAND (patch, 0); tree wfl = TREE_OPERAND (patch, 0);
tree args = TREE_OPERAND (patch, 1); tree args = TREE_OPERAND (patch, 1);
tree name = EXPR_WFL_NODE (wfl); tree name = EXPR_WFL_NODE (wfl);
tree list, class_type; tree list;
int is_static_flag = 0; int is_static_flag = 0;
/* Should be overriden if everything goes well. Otherwise, if /* 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) ...@@ -6028,6 +6292,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
free (fct_name); free (fct_name);
PATCH_METHOD_RETURN_ERROR (); PATCH_METHOD_RETURN_ERROR ();
} }
args = nreverse (args);
} }
/* We're resolving an expression name */ /* We're resolving an expression name */
else else
...@@ -6053,9 +6318,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super) ...@@ -6053,9 +6318,7 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
args = tree_cons (NULL_TREE, field, nreverse (args)); 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 */
IDENTIFIER_WFL will be used to report any problem further */
class_type = TREE_TYPE (class_decl);
wfl = identifier_wfl; wfl = identifier_wfl;
} }
/* Resolution of simple names, names generated after a primary: or /* 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) ...@@ -6099,8 +6362,11 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
PATCH_METHOD_RETURN_ERROR (); PATCH_METHOD_RETURN_ERROR ();
} }
/* Can't instantiate an abstract class */ /* Can't instantiate an abstract class, but we can
if (CLASS_ABSTRACT (class_to_search)) 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 parse_error_context
(wfl, "Class `%s' is an abstract class. It can't be " (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) ...@@ -6143,8 +6409,6 @@ patch_method_invocation_stmt (patch, primary, where, is_static, ret_decl, super)
args = nreverse (args); args = nreverse (args);
if (!METHOD_STATIC (list) && TREE_CODE (patch) != NEW_CLASS_EXPR) if (!METHOD_STATIC (list) && TREE_CODE (patch) != NEW_CLASS_EXPR)
args = tree_cons (NULL_TREE, primary ? primary : current_this, args); 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 /* 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) ...@@ -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 /* Check accessibility, position the is_static flag, build and
return the call */ 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)); char *fct_name = strdup (lang_printable_name (list, 0));
parse_error_context parse_error_context
(wfl, "Can't access %s method `%s %s.%s' from `%s'", (wfl, "Can't access %s method `%s %s.%s' from `%s'",
java_accstring_lookup (get_access_flags_from_decl (list)), java_accstring_lookup (get_access_flags_from_decl (list)),
lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), 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 (DECL_CONTEXT (list)))),
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
free (fct_name); free (fct_name);
PATCH_METHOD_RETURN_ERROR (); PATCH_METHOD_RETURN_ERROR ();
} }
check_deprecation (wfl, list);
is_static_flag = METHOD_STATIC (list); is_static_flag = METHOD_STATIC (list);
...@@ -6223,9 +6488,14 @@ patch_invoke (patch, method, args, from_super) ...@@ -6223,9 +6488,14 @@ patch_invoke (patch, method, args, from_super)
tree signature = build_java_signature (TREE_TYPE (method)); tree signature = build_java_signature (TREE_TYPE (method));
tree original_call, t, ta; tree original_call, t, ta;
/* Last step for args: convert build-in types. */ /* Last step for args: convert build-in types. If we're dealing with
for (t = TYPE_ARG_TYPES (TREE_TYPE (method)), ta = args; a new TYPE() type call, the first argument to the constructor
t && ta; t = TREE_CHAIN (t), ta = TREE_CHAIN (ta)) 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))) && if (JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_VALUE (ta))) &&
TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t)) TREE_TYPE (TREE_VALUE (ta)) != TREE_VALUE (t))
TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta)); TREE_VALUE (ta) = convert (TREE_VALUE (t), TREE_VALUE (ta));
...@@ -6243,6 +6513,11 @@ patch_invoke (patch, method, args, from_super) ...@@ -6243,6 +6513,11 @@ patch_invoke (patch, method, args, from_super)
DECL_CONTEXT (method), signature, args); DECL_CONTEXT (method), signature, args);
break; break;
case INVOKE_INTERFACE:
dtable = invoke_build_dtable (1, args);
func = build_invokeinterface (dtable, DECL_NAME (method), signature);
break;
default: default:
fatal ("Unknown invocation mode `%d' - build_invoke", im); fatal ("Unknown invocation mode `%d' - build_invoke", im);
return NULL_TREE; return NULL_TREE;
...@@ -6318,34 +6593,24 @@ lookup_method_invoke (lc, cl, class, name, arg_list) ...@@ -6318,34 +6593,24 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
tree class, name, arg_list; tree class, name, arg_list;
{ {
tree method = make_node (FUNCTION_TYPE); tree method = make_node (FUNCTION_TYPE);
tree arg_type_list = NULL_TREE; tree atl = NULL_TREE; /* Arg Type List */
tree signature, list, node; tree signature, list, node;
char *candidates; /* Used for error report */ char *candidates; /* Used for error report */
/* Fix the arguments */
for (node = arg_list; node; node = TREE_CHAIN (node)) for (node = arg_list; node; node = TREE_CHAIN (node))
{ {
tree current_arg = TREE_TYPE (TREE_VALUE (node)); tree current_arg = TREE_TYPE (TREE_VALUE (node));
if (TREE_CODE (current_arg) == RECORD_TYPE) if (TREE_CODE (current_arg) == RECORD_TYPE)
current_arg = promote_type (current_arg); 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) /* Find all candidates and then refine the list, searching for the
{ most specific method. */
list = find_applicable_accessible_methods_list (class, name, list = find_applicable_accessible_methods_list (lc, class, name, atl);
arg_type_list);
list = find_most_specific_methods_list (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;
if (list && !TREE_CHAIN (list)) if (list && !TREE_CHAIN (list))
return TREE_VALUE (list); return TREE_VALUE (list);
...@@ -6386,10 +6651,12 @@ lookup_method_invoke (lc, cl, class, name, arg_list) ...@@ -6386,10 +6651,12 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
return NULL_TREE; 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 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 class, name, arglist;
{ {
tree method; tree method;
...@@ -6400,8 +6667,10 @@ find_applicable_accessible_methods_list (class, name, arglist) ...@@ -6400,8 +6667,10 @@ find_applicable_accessible_methods_list (class, name, arglist)
for (method = TYPE_METHODS (class); for (method = TYPE_METHODS (class);
method != NULL_TREE; method = TREE_CHAIN (method)) method != NULL_TREE; method = TREE_CHAIN (method))
{ {
/* Names have to match and we're not looking for constructor */ if (lc && !DECL_CONSTRUCTOR_P (method))
if (DECL_NAME (method) != name || DECL_CONSTRUCTOR_P (method)) continue;
else if (!lc && (DECL_CONSTRUCTOR_P (method)
|| DECL_NAME (method) != name))
continue; continue;
if (argument_types_convertible (method, arglist)) if (argument_types_convertible (method, arglist))
...@@ -6414,7 +6683,9 @@ find_applicable_accessible_methods_list (class, name, arglist) ...@@ -6414,7 +6683,9 @@ find_applicable_accessible_methods_list (class, name, arglist)
all_list = tree_cons (NULL_TREE, method, list); 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 /* Either return the list obtained or all selected (but
inaccessible) methods for better error report. */ inaccessible) methods for better error report. */
...@@ -6598,8 +6869,9 @@ qualify_ambiguous_name (id) ...@@ -6598,8 +6869,9 @@ qualify_ambiguous_name (id)
/* Do one more interation to set things up */ /* Do one more interation to set things up */
super_found = again = 1; super_found = again = 1;
} }
/* Loop one more time if we're dealing with ?: up front */ /* Loop one more time if we're dealing with ?: or a string constant */
if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR) if (TREE_CODE (qual_wfl) == CONDITIONAL_EXPR
|| TREE_CODE (qual_wfl) == STRING_CST)
{ {
qual = TREE_CHAIN (qual); qual = TREE_CHAIN (qual);
qual_wfl = QUAL_WFL (qual); qual_wfl = QUAL_WFL (qual);
...@@ -6709,8 +6981,10 @@ not_initialized_as_it_should_p (decl) ...@@ -6709,8 +6981,10 @@ not_initialized_as_it_should_p (decl)
{ {
if (DECL_P (decl)) if (DECL_P (decl))
{ {
if (FIELD_FINAL (decl))
return 0;
if (TREE_CODE (decl) == FIELD_DECL if (TREE_CODE (decl) == FIELD_DECL
&& METHOD_STATIC (current_function_decl)) && (METHOD_STATIC (current_function_decl)))
return 0; return 0;
return DECL_P (decl) && !INITIALIZED_P (decl); return DECL_P (decl) && !INITIALIZED_P (decl);
} }
...@@ -6860,7 +7134,7 @@ java_complete_tree (node) ...@@ -6860,7 +7134,7 @@ java_complete_tree (node)
case EXPR_WITH_FILE_LOCATION: case EXPR_WITH_FILE_LOCATION:
if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */ if (!EXPR_WFL_NODE (node) /* Or a PRIMARY flag ? */
|| TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE) || TREE_CODE (EXPR_WFL_NODE (node)) == IDENTIFIER_NODE)
return resolve_expression_name (node); return resolve_expression_name (node, NULL);
else else
{ {
EXPR_WFL_NODE (node) = java_complete_tree (EXPR_WFL_NODE (node)); EXPR_WFL_NODE (node) = java_complete_tree (EXPR_WFL_NODE (node));
...@@ -6958,7 +7232,8 @@ java_complete_tree (node) ...@@ -6958,7 +7232,8 @@ java_complete_tree (node)
an error during the assignment. In any cases, the an error during the assignment. In any cases, the
assignment operation fails. */ assignment operation fails. */
if (TREE_CODE (TREE_OPERAND (node, 1)) != EXPR_WITH_FILE_LOCATION 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); patch_assignment (node, wfl_op1, wfl_op2);
/* Now, we still mark the lhs as initialized */ /* Now, we still mark the lhs as initialized */
...@@ -7015,6 +7290,11 @@ java_complete_tree (node) ...@@ -7015,6 +7290,11 @@ java_complete_tree (node)
} }
return patch_binop (node, wfl_op1, wfl_op2); 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 UNARY_PLUS_EXPR:
case NEGATE_EXPR: case NEGATE_EXPR:
case TRUTH_NOT_EXPR: case TRUTH_NOT_EXPR:
...@@ -7108,8 +7388,10 @@ complete_function_arguments (node) ...@@ -7108,8 +7388,10 @@ complete_function_arguments (node)
`+' operator. Build `parm.toString()' and expand it. */ `+' operator. Build `parm.toString()' and expand it. */
if ((temp = patch_string (parm))) if ((temp = patch_string (parm)))
parm = temp; 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)) if (not_initialized_as_it_should_p (parm))
{ {
ERROR_VARIABLE_NOT_INITIALIZED (wfl, EXPR_WFL_NODE (wfl)); ERROR_VARIABLE_NOT_INITIALIZED (wfl, EXPR_WFL_NODE (wfl));
...@@ -7350,6 +7632,47 @@ print_int_node (node) ...@@ -7350,6 +7632,47 @@ print_int_node (node)
return buffer; 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. */ /* 15.25 Assignment operators. */
static tree static tree
...@@ -7359,19 +7682,14 @@ patch_assignment (node, wfl_op1, wfl_op2) ...@@ -7359,19 +7682,14 @@ patch_assignment (node, wfl_op1, wfl_op2)
tree wfl_op2; tree wfl_op2;
{ {
tree rhs = TREE_OPERAND (node, 1); 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; tree lhs_type, rhs_type, new_rhs = NULL_TREE;
int error_found = 0; int error_found = 0;
int lvalue_from_array = 0; int lvalue_from_array = 0;
/* Can't assign to a final. */ /* Can't assign to a final. */
if (DECL_P (lvalue) && FIELD_FINAL (lvalue)) if (check_final_assignment (lvalue, wfl_op1))
{
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; error_found = 1;
}
EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node); EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
...@@ -7394,7 +7712,17 @@ patch_assignment (node, wfl_op1, wfl_op2) ...@@ -7394,7 +7712,17 @@ patch_assignment (node, wfl_op1, wfl_op2)
/* Or a function return slot */ /* Or a function return slot */
else if (TREE_CODE (lvalue) == RESULT_DECL) else if (TREE_CODE (lvalue) == RESULT_DECL)
lhs_type = TREE_TYPE (lvalue); lhs_type = TREE_TYPE (lvalue);
/* Otherwise, this is an error */ /* 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 else
{ {
parse_error_context (wfl_op1, "Invalid left hand side of assignment"); parse_error_context (wfl_op1, "Invalid left hand side of assignment");
...@@ -7462,6 +7790,22 @@ patch_assignment (node, wfl_op1, wfl_op2) ...@@ -7462,6 +7790,22 @@ patch_assignment (node, wfl_op1, wfl_op2)
INITIALIZED_P (rhs) = 1; 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) if (error_found)
return error_mark_node; return error_mark_node;
...@@ -7515,9 +7859,15 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs) ...@@ -7515,9 +7859,15 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs)
tree new_rhs = NULL_TREE; tree new_rhs = NULL_TREE;
tree rhs_type = TREE_TYPE (rhs); 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.1 Try Identity Conversion,
5.1.2 Try Widening Primitive 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); new_rhs = convert (lhs_type, rhs);
/* Try a narrowing primitive conversion (5.1.3): /* Try a narrowing primitive conversion (5.1.3):
...@@ -7552,20 +7902,32 @@ static int ...@@ -7552,20 +7902,32 @@ static int
valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type) valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type)
tree 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); JPRIMITIVE_TYPE_P (lhs_type) && JPRIMITIVE_TYPE_P (rhs_type);
if (!all_primitive) if (!all_primitive)
return 0; return 0;
if (lhs_type == rhs_type)
return 1;
/* byte, even if it's smaller than a char can't be converted into a /* 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 */ char. Short can't too, but the < test below takes care of that */
if (lhs_type == char_type_node && rhs_type == byte_type_node) if (lhs_type == char_type_node && rhs_type == byte_type_node)
return 0; 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) if (JINTEGRAL_TYPE_P (rhs_type)
&& ((TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type)) && ((TYPE_PRECISION (rhs_type) < TYPE_PRECISION (lhs_type))
|| (JFLOAT_TYPE_P (lhs_type) && || (JFLOAT_TYPE_P (lhs_type) &&
...@@ -7590,6 +7952,8 @@ valid_ref_assignconv_cast_p (source, dest, cast) ...@@ -7590,6 +7952,8 @@ valid_ref_assignconv_cast_p (source, dest, cast)
tree dest; tree dest;
int cast; int cast;
{ {
if (JNULLP_TYPE_P (source))
return 1;
if (TREE_CODE (source) == POINTER_TYPE) if (TREE_CODE (source) == POINTER_TYPE)
source = TREE_TYPE (source); source = TREE_TYPE (source);
if (TREE_CODE (dest) == POINTER_TYPE) if (TREE_CODE (dest) == POINTER_TYPE)
...@@ -7715,8 +8079,8 @@ valid_method_invocation_conversion_p (dest, source) ...@@ -7715,8 +8079,8 @@ valid_method_invocation_conversion_p (dest, source)
return ((JPRIMITIVE_TYPE_P (source) return ((JPRIMITIVE_TYPE_P (source)
&& JPRIMITIVE_TYPE_P (dest) && JPRIMITIVE_TYPE_P (dest)
&& valid_builtin_assignconv_identity_widening_p (dest, source)) && valid_builtin_assignconv_identity_widening_p (dest, source))
|| (JREFERENCE_TYPE_P (source) || ((JREFERENCE_TYPE_P (source) || JNULLP_TYPE_P (source))
&& JREFERENCE_TYPE_P (dest) && (JREFERENCE_TYPE_P (dest) || JNULLP_TYPE_P (dest))
&& valid_ref_assignconv_cast_p (source, dest, 0))); && valid_ref_assignconv_cast_p (source, dest, 0)));
} }
...@@ -7728,9 +8092,7 @@ build_binop (op, op_location, op1, op2) ...@@ -7728,9 +8092,7 @@ build_binop (op, op_location, op1, op2)
int op_location; int op_location;
tree op1, op2; tree op1, op2;
{ {
tree binop; tree binop = build (op, NULL_TREE, op1, op2);
binop = build (op, NULL_TREE, op1, op2);
TREE_SIDE_EFFECTS (binop) = 1; TREE_SIDE_EFFECTS (binop) = 1;
/* Store the location of the operator, for better error report. The /* Store the location of the operator, for better error report. The
string of the operator will be rebuild based on the OP value. */ string of the operator will be rebuild based on the OP value. */
...@@ -7936,6 +8298,62 @@ patch_binop (node, wfl_op1, wfl_op2) ...@@ -7936,6 +8298,62 @@ patch_binop (node, wfl_op1, wfl_op2)
} }
break; 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 */ /* 15.21 Bitwise and Logical Operators */
case BIT_AND_EXPR: case BIT_AND_EXPR:
...@@ -8011,7 +8429,7 @@ patch_binop (node, wfl_op1, wfl_op2) ...@@ -8011,7 +8429,7 @@ patch_binop (node, wfl_op1, wfl_op2)
case NE_EXPR: case NE_EXPR:
/* 15.20.1 Numerical Equality Operators == and != */ /* 15.20.1 Numerical Equality Operators == and != */
/* Binary numeric promotion is performed on the operands */ /* 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); binary_numeric_promotion (op1_type, op2_type, &op1, &op2);
/* 15.20.2 Boolean Equality Operators == and != */ /* 15.20.2 Boolean Equality Operators == and != */
...@@ -8020,10 +8438,14 @@ patch_binop (node, wfl_op1, wfl_op2) ...@@ -8020,10 +8438,14 @@ patch_binop (node, wfl_op1, wfl_op2)
; /* Nothing to do here */ ; /* Nothing to do here */
/* 15.20.3 Reference Equality Operators == and != */ /* 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 else if (op1 == null_pointer_node || op2 == null_pointer_node
|| (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type) || (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 */ ; /* Nothing to do here */
/* Else we have an error figure what can't be converted into /* Else we have an error figure what can't be converted into
...@@ -8344,22 +8766,25 @@ patch_unaryop (node, wfl_op) ...@@ -8344,22 +8766,25 @@ patch_unaryop (node, wfl_op)
case PREINCREMENT_EXPR: case PREINCREMENT_EXPR:
/* 15.14.2 Prefix Decrement Operator -- */ /* 15.14.2 Prefix Decrement Operator -- */
case PREDECREMENT_EXPR: 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)))) && JPRIMITIVE_TYPE_P (TREE_TYPE (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'", parse_error_context (wfl_operator, "Invalid argument to `%s'",
operator_string (node)); operator_string (node));
TREE_TYPE (node) = error_mark_node; TREE_TYPE (node) = error_mark_node;
error_found = 1; error_found = 1;
} }
else if (DECL_P (op) && FIELD_FINAL (op)) else if (check_final_assignment (op, wfl_op))
{
parse_error_context
(wfl_op, "Can't assign a value to the final variable `%s'",
IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl_op)));
TREE_TYPE (node) = error_mark_node;
error_found = 1; error_found = 1;
}
/* From now on, we know that op if a variable and that it has a /* 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 valid wfl. We use wfl_op to locate errors related to the
++/-- operand. */ ++/-- operand. */
...@@ -8480,8 +8905,11 @@ resolve_type_during_patch (type) ...@@ -8480,8 +8905,11 @@ resolve_type_during_patch (type)
return NULL_TREE; return NULL_TREE;
} }
else else
{
CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1;
return TREE_TYPE (type_decl); return TREE_TYPE (type_decl);
} }
}
return type; return type;
} }
/* 5.5 Casting Conversion. error_mark_node is returned if an error is /* 5.5 Casting Conversion. error_mark_node is returned if an error is
...@@ -8515,6 +8943,10 @@ patch_cast (node, wfl_operator) ...@@ -8515,6 +8943,10 @@ patch_cast (node, wfl_operator)
return convert (cast_type, op); 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 /* The remaining legal casts involve conversion between reference
types. Check for their compile time correctness. */ types. Check for their compile time correctness. */
if (JREFERENCE_TYPE_P (op_type) && JREFERENCE_TYPE_P (cast_type) if (JREFERENCE_TYPE_P (op_type) && JREFERENCE_TYPE_P (cast_type)
...@@ -8544,6 +8976,17 @@ patch_cast (node, wfl_operator) ...@@ -8544,6 +8976,17 @@ patch_cast (node, wfl_operator)
return error_mark_node; 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 /* Build an ARRAY_REF incomplete tree node. Note that operand 1 isn't
a list of indices. */ a list of indices. */
static tree static tree
...@@ -8617,8 +9060,11 @@ patch_array_ref (node, wfl_array, wfl_index) ...@@ -8617,8 +9060,11 @@ patch_array_ref (node, wfl_array, wfl_index)
return error_mark_node; return error_mark_node;
index = convert (promoted_index_type, index); index = convert (promoted_index_type, index);
if (TREE_CODE (array_type) == RECORD_TYPE) array_type = TYPE_ARRAY_ELEMENT (array_type);
array_type = promote_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) if (flag_emit_class_files)
{ {
TREE_OPERAND (node, 0)= array; TREE_OPERAND (node, 0)= array;
...@@ -8804,7 +9250,6 @@ patch_return (node) ...@@ -8804,7 +9250,6 @@ patch_return (node)
tree return_exp = TREE_OPERAND (node, 0); tree return_exp = TREE_OPERAND (node, 0);
tree meth = current_function_decl; tree meth = current_function_decl;
tree mtype = TREE_TYPE (TREE_TYPE (current_function_decl)); tree mtype = TREE_TYPE (TREE_TYPE (current_function_decl));
tree modify;
int error_found = 0; int error_found = 0;
TREE_TYPE (node) = error_mark_node; TREE_TYPE (node) = error_mark_node;
...@@ -8838,12 +9283,33 @@ patch_return (node) ...@@ -8838,12 +9283,33 @@ patch_return (node)
return error_mark_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) 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); EXPR_WFL_LINECOL (modify) = EXPR_WFL_LINECOL (node);
modify = java_complete_tree (modify); modify = java_complete_tree (modify);
if (modify != error_mark_node) if (modify != error_mark_node)
{ {
TREE_SIDE_EFFECTS (modify) = 1; TREE_SIDE_EFFECTS (modify) = 1;
......
...@@ -52,10 +52,6 @@ set_local_type (slot, type) ...@@ -52,10 +52,6 @@ set_local_type (slot, type)
type_map[++slot] = void_type_node; 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, /* Create an expression whose value is that of EXPR,
converted to type TYPE. The TREE_TYPE of the value converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable is always TYPE. This function implements all reasonable
...@@ -663,7 +659,7 @@ lookup_argument_method (clas, method_name, method_signature) ...@@ -663,7 +659,7 @@ lookup_argument_method (clas, method_name, method_signature)
tree method_sig = build_java_argument_signature (TREE_TYPE (method)); tree method_sig = build_java_argument_signature (TREE_TYPE (method));
tree name = DECL_NAME (method); tree name = DECL_NAME (method);
if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ? 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) && method_sig == method_signature)
return method; 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