static tree lookup_field_wrapper PARAMS ((tree, tree));
static int duplicate_declaration_error_p PARAMS ((tree, tree, tree));
static void register_fields PARAMS ((int, tree, tree));
-static tree parser_qualified_classname PARAMS ((int, tree));
+static tree parser_qualified_classname PARAMS ((tree));
static int parser_check_super PARAMS ((tree, tree, tree));
static int parser_check_super_interface PARAMS ((tree, tree, tree));
static void check_modifiers_consistency PARAMS ((int));
static int process_imports PARAMS ((void));
static void read_import_dir PARAMS ((tree));
static int find_in_imports_on_demand PARAMS ((tree));
-static int find_in_imports PARAMS ((tree));
+static void find_in_imports PARAMS ((tree));
+static void check_inner_class_access PARAMS ((tree, tree, tree));
static int check_pkg_class_access PARAMS ((tree, tree));
+static void register_package PARAMS ((tree));
static tree resolve_package PARAMS ((tree, tree *));
static tree lookup_package_type PARAMS ((const char *, int));
static tree lookup_package_type_and_set_next PARAMS ((const char *, int, tree *));
int *, tree *));
static int breakdown_qualified PARAMS ((tree *, tree *, tree));
static tree resolve_and_layout PARAMS ((tree, tree));
+static tree qualify_and_find PARAMS ((tree, tree, tree));
static tree resolve_no_layout PARAMS ((tree, tree));
static int invocation_mode PARAMS ((tree, int));
static tree find_applicable_accessible_methods_list PARAMS ((int, tree,
static tree patch_newarray PARAMS ((tree));
static tree resolve_type_during_patch PARAMS ((tree));
static tree build_this PARAMS ((int));
-static tree build_wfl_wrap PARAMS ((tree));
+static tree build_wfl_wrap PARAMS ((tree, int));
static tree build_return PARAMS ((int, tree));
static tree patch_return PARAMS ((tree));
static tree maybe_access_field PARAMS ((tree, tree, tree));
simple_name:
identifier /* Default rule */
+ {
+ if (strchr (IDENTIFIER_POINTER (EXPR_WFL_NODE ($$)), '$'))
+ parse_error_context ($$, "Invalid type name `%s'",
+ IDENTIFIER_POINTER (EXPR_WFL_NODE ($$)));
+ }
;
qualified_name:
PACKAGE_TK name SC_TK
{
ctxp->package = EXPR_WFL_NODE ($2);
- package_list = tree_cons (ctxp->package, NULL, package_list);
+ register_package (ctxp->package);
}
| PACKAGE_TK error
{yyerror ("Missing name"); RECOVER;}
single_type_import_declaration:
IMPORT_TK name SC_TK
{
- tree name = EXPR_WFL_NODE ($2), node, last_name;
+ tree name = EXPR_WFL_NODE ($2), last_name;
int i = IDENTIFIER_LENGTH (name)-1;
const char *last = &IDENTIFIER_POINTER (name)[i];
while (last != IDENTIFIER_POINTER (name))
IDENTIFIER_POINTER (name),
IDENTIFIER_POINTER (err));
else
- REGISTER_IMPORT ($2, last_name)
+ REGISTER_IMPORT ($2, last_name);
}
else
REGISTER_IMPORT ($2, last_name);
/* Don't import java.lang.* twice. */
if (name != java_lang_id)
{
- tree node = build_tree_list ($2, NULL_TREE);
read_import_dir ($2);
- TREE_CHAIN (node) = ctxp->import_demand_list;
- ctxp->import_demand_list = node;
+ ctxp->import_demand_list =
+ chainon (ctxp->import_demand_list,
+ build_tree_list ($2, NULL_TREE));
}
}
| IMPORT_TK name DOT_TK error
for_statement:
for_begin SC_TK expression SC_TK for_update CP_TK statement
- { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7); }
+ {
+ if (TREE_CODE_CLASS (TREE_CODE ($3)) == 'c')
+ $3 = build_wfl_node ($3);
+ $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);
+ }
| for_begin SC_TK SC_TK for_update CP_TK statement
{
$$ = finish_for_loop (0, NULL_TREE, $4, $6);
dim_expr:
OSB_TK expression CSB_TK
{
+ if (JNUMERIC_TYPE_P (TREE_TYPE ($2)))
+ {
+ $2 = build_wfl_node ($2);
+ TREE_TYPE ($2) = NULL_TREE;
+ }
EXPR_WFL_LINECOL ($2) = $1.location;
$$ = $2;
}
{
tree acc = NULL_TREE, decl = NULL_TREE, ptr;
- for(qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl;
- qual = TREE_CHAIN (qual))
+ for (qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl;
+ qual = TREE_CHAIN (qual))
{
acc = merge_qualified_name (acc,
EXPR_WFL_NODE (TREE_PURPOSE (qual)));
else
qual = build_tree_list (build_expr_wfl (name, NULL, 0, 0), NULL_TREE);
- return find_as_inner_class_do (qual, enclosing);
+ if (!(to_return = find_as_inner_class_do (qual, enclosing)))
+ {
+ /* It might be the case that the enclosing class was loaded as
+ bytecode, in which case it will be missing the
+ DECL_INNER_CLASS_LIST. We build a fully qualified internal
+ innerclass name and we try to load it. */
+ tree fqin = identifier_subst (name, "", '.', '$', "");
+ tree ptr;
+ BUILD_PTR_FROM_NAME (ptr, fqin);
+ to_return = resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+ }
+ return to_return;
}
/* We go inside the list of sub classes and try to find a way
tree id, super;
{
tree raw_name = EXPR_WFL_NODE (id);
- tree q_name = parser_qualified_classname (flags & ACC_STATIC, raw_name);
+ tree q_name = parser_qualified_classname (raw_name);
tree decl = IDENTIFIER_CLASS_VALUE (q_name);
EXPR_WFL_NODE (id) = q_name; /* Keep source location, even if refined. */
tree class_id, decl;
tree super_decl_type;
- class_id = parser_qualified_classname (0, raw_name);
+ class_id = parser_qualified_classname (raw_name);
decl = IDENTIFIER_CLASS_VALUE (class_id);
EXPR_WFL_NODE (id) = class_id;
CLASS_COMPLETE_P (decl) = 1;
add_superinterfaces (decl, interfaces);
- /* If the class is a top level inner class, install an alias. */
- if (INNER_CLASS_DECL_P (decl) && CLASS_STATIC (decl))
- {
- tree alias = parser_qualified_classname (1, raw_name);
- IDENTIFIER_GLOBAL_VALUE (alias) = decl;
- }
-
/* Add the private this$<n> field, Replicate final locals still in
scope as private final fields mangled like val$<local_name>.
This doesn't not occur for top level (static) inner classes. */
tree class, name;
{
tree type = class;
- tree decl;
+ tree decl = NULL_TREE;
java_parser_context_save_global ();
- decl = lookup_field (&type, name);
/* Last chance: if we're within the context of an inner class, we
might be trying to access a local variable defined in an outer
context. We try to look for it now. */
- if (INNER_CLASS_TYPE_P (class) && (!decl || decl == error_mark_node))
+ if (INNER_CLASS_TYPE_P (class))
{
char *alias_buffer;
+ tree new_name;
MANGLE_OUTER_LOCAL_VARIABLE_NAME (alias_buffer, name);
- name = get_identifier (alias_buffer);
- type = class;
- decl = lookup_field (&type, name);
+ new_name = get_identifier (alias_buffer);
+ decl = lookup_field (&type, new_name);
if (decl && decl != error_mark_node)
FIELD_LOCAL_ALIAS_USED (decl) = 1;
}
+ if (!decl || decl == error_mark_node)
+ {
+ type = class;
+ decl = lookup_field (&type, name);
+ }
java_parser_context_restore_global ();
return decl == error_mark_node ? NULL : decl;
tree init = TREE_VALUE (current);
tree current_name = EXPR_WFL_NODE (cl);
- /* Can't declare static fields in inner classes */
+ /* Can't declare non-final static fields in inner classes */
if ((flags & ACC_STATIC) && !TOPLEVEL_CLASS_TYPE_P (class_type)
- && !CLASS_INTERFACE (TYPE_NAME (class_type)))
+ && !(flags & ACC_FINAL))
parse_error_context
- (cl, "Field `%s' can't be static in innerclass `%s'. Only members of interfaces and top-level classes can be static",
+ (cl, "Field `%s' can't be static in inner class `%s' unless it is final",
IDENTIFIER_POINTER (EXPR_WFL_NODE (cl)),
lang_printable_name (class_type, 0));
&& !CLASS_INTERFACE (TYPE_NAME (this_class)))
parse_error_context
(id, "Class `%s' must be declared abstract to define abstract method `%s'",
- IDENTIFIER_POINTER (DECL_NAME (ctxp->current_parsed_class)),
+ IDENTIFIER_POINTER (DECL_NAME (GET_CPC ())),
IDENTIFIER_POINTER (EXPR_WFL_NODE (id)));
}
/* Then this$<n> */
type = TREE_TYPE (DECL_CONTEXT (GET_CPC ()));
- thisn = build_current_thisn (TYPE_NAME (GET_CPC ()));
+ thisn = build_current_thisn (TREE_TYPE (GET_CPC ()));
list = tree_cons (build_wfl_node (thisn), build_pointer_type (type),
list);
}
qualification from the current package definition. */
static tree
-parser_qualified_classname (is_static, name)
- int is_static;
+parser_qualified_classname (name)
tree name;
{
tree nested_class_name;
- if (!is_static
- && (nested_class_name = maybe_make_nested_class_name (name)))
+ if ((nested_class_name = maybe_make_nested_class_name (name)))
return nested_class_name;
if (ctxp->package)
if (!decl)
complete_class_report_errors (dep);
+ if (PURE_INNER_CLASS_DECL_P (decl))
+ check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep));
return decl;
}
push_obstacks (&permanent_obstack, &permanent_obstack);
- /* Process imports and reverse the import on demand list */
+ /* Process imports */
process_imports ();
- if (ctxp->import_demand_list)
- ctxp->import_demand_list = nreverse (ctxp->import_demand_list);
/* Rever things so we have the right order */
ctxp->class_list = nreverse (ctxp->class_list);
tree enclosing, class_type, decl, cl;
{
tree new_class_decl;
- tree original_name = NULL_TREE;
/* Do not try to replace TYPE_NAME (class_type) by a variable, since
- its is changed by find_in_imports{_on_demand} */
+ it is changed by find_in_imports{_on_demand} and (but it doesn't
+ really matter) qualify_and_find */
/* 0- Search in the current class as an inner class */
if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
return new_class_decl;
+ /* Explore enclosing contexts. */
+ while (INNER_CLASS_DECL_P (enclosing))
+ {
+ enclosing = DECL_CONTEXT (enclosing);
+ if ((new_class_decl = find_as_inner_class (enclosing,
+ class_type, cl)))
+ return new_class_decl;
+ }
+
/* Now go to the upper classes, bail out if necessary. */
enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
if (!enclosing || enclosing == object_type_node)
}
if (TREE_CODE (enclosing) == IDENTIFIER_NODE)
- {
- BUILD_PTR_FROM_NAME (name, enclosing);
- }
+ BUILD_PTR_FROM_NAME (name, enclosing);
else
name = enclosing;
enclosing = do_resolve_class (NULL, name, NULL, NULL);
}
- /* 1- Check for the type in single imports */
- if (find_in_imports (class_type))
- return NULL_TREE;
+ /* 1- Check for the type in single imports. This will change
+ TYPE_NAME() if something relevant is found */
+ find_in_imports (class_type);
- /* 2- And check for the type in the current compilation unit. If it fails,
- try with a name qualified with the package name we've seen so far */
+ /* 2- And check for the type in the current compilation unit */
if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
{
if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
}
- original_name = TYPE_NAME (class_type);
+ /* 3- Search according to the current package definition */
if (!QUALIFIED_P (TYPE_NAME (class_type)))
{
- tree package;
- for (package = package_list; package; package = TREE_CHAIN (package))
- {
- tree new_qualified;
-
- new_qualified = merge_qualified_name (TREE_PURPOSE (package),
- original_name);
- TYPE_NAME (class_type) = new_qualified;
- new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
- if (!new_class_decl)
- load_class (TYPE_NAME (class_type), 0);
- new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
- if (new_class_decl)
- {
- if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
- !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
- load_class (TYPE_NAME (class_type), 0);
- return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
- }
- }
- }
-
- TYPE_NAME (class_type) = original_name;
-
- /* 3- Check an other compilation unit that bears the name of type */
- load_class (TYPE_NAME (class_type), 0);
- if (check_pkg_class_access (TYPE_NAME (class_type),
- (cl ? cl : lookup_cl (decl))))
- return NULL_TREE;
-
- if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
- return new_class_decl;
+ if ((new_class_decl = qualify_and_find (class_type, ctxp->package,
+ TYPE_NAME (class_type))))
+ return new_class_decl;
+ }
/* 4- Check the import on demands. Don't allow bar.baz to be
imported from foo.* */
if (find_in_imports_on_demand (class_type))
return NULL_TREE;
- /* 5- Last call for a resolution */
+ /* If found in find_in_imports_on_demant, the type has already been
+ loaded. */
+ if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
+ return new_class_decl;
+
+ /* 5- Try with a name qualified with the package name we've seen so far */
+ if (!QUALIFIED_P (TYPE_NAME (class_type)))
+ {
+ tree package;
+
+ /* If there is a current package (ctxp->package), it's the first
+ element of package_list and we can skip it. */
+ for (package = (ctxp->package ?
+ TREE_CHAIN (package_list) : package_list);
+ package; package = TREE_CHAIN (package))
+ if ((new_class_decl = qualify_and_find (class_type,
+ TREE_PURPOSE (package),
+ TYPE_NAME (class_type))))
+ return new_class_decl;
+ }
+
+ /* 5- Check an other compilation unit that bears the name of type */
+ load_class (TYPE_NAME (class_type), 0);
+ if (check_pkg_class_access (TYPE_NAME (class_type),
+ (cl ? cl : lookup_cl (decl))))
+ return NULL_TREE;
+
+ /* 6- Last call for a resolution */
return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
}
+static tree
+qualify_and_find (class_type, package, name)
+ tree class_type, package, name;
+{
+ tree new_qualified = merge_qualified_name (package, name);
+ tree new_class_decl;
+
+ if (!IDENTIFIER_CLASS_VALUE (new_qualified))
+ load_class (new_qualified, 0);
+ if ((new_class_decl = IDENTIFIER_CLASS_VALUE (new_qualified)))
+ {
+ if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
+ !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
+ load_class (new_qualified, 0);
+ TYPE_NAME (class_type) = new_qualified;
+ return IDENTIFIER_CLASS_VALUE (new_qualified);
+ }
+ return NULL_TREE;
+}
+
/* Resolve NAME and lay it out (if not done and if not the current
parsed class). Return a decl node. This function is meant to be
called when type resolution is necessary during the walk pass. */
other_name = EXPR_WFL_NODE (other_name);
if (!DECL_CLINIT_P (other_method)
&& !DECL_CONSTRUCTOR_P (other_method)
- && method_name == other_name && method_sig == s)
+ && method_name == other_name
+ && method_sig == s
+ && !METHOD_ABSTRACT (other_method))
{
found = 1;
break;
return 0;
}
-/* Possibly find a class imported by a single-type import statement. Return
- 1 if an error occured, 0 otherwise. */
+/* Possibly find and mark a class imported by a single-type import
+ statement. */
-static int
+static void
find_in_imports (class_type)
tree class_type;
{
TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import));
QUALIFIED_P (TYPE_NAME (class_type)) = 1;
}
- return 0;
}
static int
return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */
}
+/* Add package NAME to the list of package encountered so far. To
+ speed up class lookup in do_resolve_class, we make sure a
+ particular package is added only once. */
+
+static void
+register_package (name)
+ tree name;
+{
+ static struct hash_table _pht, *pht = NULL;
+
+ if (!pht)
+ {
+ hash_table_init (&_pht, hash_newfunc,
+ java_hash_hash_tree_node, java_hash_compare_tree_node);
+ pht = &_pht;
+ }
+
+ if (!hash_lookup (pht, (const hash_table_key) name, FALSE, NULL))
+ {
+ package_list = chainon (package_list, build_tree_list (name, NULL));
+ hash_lookup (pht, (const hash_table_key) name, TRUE, NULL);
+ }
+}
+
static tree
resolve_package (pkg, next)
tree pkg, *next;
return get_identifier (subname);
}
+static void
+check_inner_class_access (decl, enclosing_decl, cl)
+ tree decl, enclosing_decl, cl;
+{
+ int access = 0;
+
+ /* We don't issue an error message when CL is null. CL can be null
+ as a result of processing a JDEP crafted by source_start_java_method
+ for the purpose of patching its parm decl. But the error would
+ have been already trapped when fixing the method's signature.
+ DECL can also be NULL in case of earlier errors. */
+ if (!decl || !cl)
+ return;
+
+ /* We grant access to private and protected inner classes if the
+ location from where we're trying to access DECL is an enclosing
+ context for DECL or if both have a common enclosing context. */
+ if (CLASS_PRIVATE (decl))
+ access = 1;
+ if (CLASS_PROTECTED (decl))
+ access = 2;
+ if (!access)
+ return;
+
+ if (common_enclosing_context_p (TREE_TYPE (enclosing_decl),
+ TREE_TYPE (decl))
+ || enclosing_context_p (TREE_TYPE (enclosing_decl),
+ TREE_TYPE (decl)))
+ return;
+
+ parse_error_context (cl, "Can't access %s nested %s %s. Only public classes and interfaces in other packages can be accessed",
+ (access == 1 ? "private" : "protected"),
+ (CLASS_INTERFACE (decl) ? "interface" : "class"),
+ lang_printable_name (decl, 0));
+}
+
/* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no
access violations were found, 1 otherwise. */
for (current = TYPE_CLINIT_STMT_LIST (class_type); current;
current = TREE_CHAIN (current))
{
+ tree stmt = current;
/* We build the assignment expression that will initialize the
field to its value. There are strict rules on static
initializers (8.5). FIXME */
- tree stmt = build_debugable_stmt (EXPR_WFL_LINECOL (current), current);
+ if (TREE_CODE (stmt) != BLOCK && stmt != empty_stmt_node)
+ stmt = build_debugable_stmt (EXPR_WFL_LINECOL (stmt), stmt);
java_method_add_stmt (mdecl, stmt);
}
for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
if (DECL_CONSTRUCTOR_P (sdecl))
{
+ tree m_arg_type;
tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
if (super_inner)
arg_type = TREE_CHAIN (arg_type);
- for (; (arg_type != end_params_node
- && mdecl_arg_type != end_params_node);
+ for (m_arg_type = mdecl_arg_type;
+ (arg_type != end_params_node
+ && m_arg_type != end_params_node);
arg_type = TREE_CHAIN (arg_type),
- mdecl_arg_type = TREE_CHAIN (mdecl_arg_type))
- if (TREE_VALUE (arg_type) != TREE_VALUE (mdecl_arg_type))
+ m_arg_type = TREE_CHAIN (m_arg_type))
+ if (TREE_VALUE (arg_type) != TREE_VALUE (m_arg_type))
break;
- if (arg_type == end_params_node &&
- mdecl_arg_type == end_params_node)
+ if (arg_type == end_params_node && m_arg_type == end_params_node)
return 0;
}
}
java_layout_classes ();
java_parse_abort_on_error ();
- /* The list of packages declaration seen so far needs to be
- reversed, so that package declared in a file being compiled gets
- priority over packages declared as a side effect of parsing other
- files.*/
- package_list = nreverse (package_list);
-
saved_ctxp = ctxp_for_generation;
for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
{
tree wfl;
if (TREE_CODE (primary) != EXPR_WITH_FILE_LOCATION)
- wfl = build_wfl_wrap (primary);
+ wfl = build_wfl_wrap (primary, location);
else
{
wfl = primary;
return error_mark_node;
/* Resolve the LENGTH field of an array here */
- if (DECL_NAME (decl) == length_identifier_node && TYPE_ARRAY_P (type_found)
+ if (DECL_P (decl) && DECL_NAME (decl) == length_identifier_node
+ && type_found && TYPE_ARRAY_P (type_found)
&& ! flag_emit_class_files && ! flag_emit_xref)
{
tree length = build_java_array_length_access (where_found);
if (!type_found)
type_found = DECL_CONTEXT (decl);
is_static = JDECL_P (decl) && FIELD_STATIC (decl);
- if (FIELD_FINAL (decl)
+ if (FIELD_FINAL (decl) && FIELD_STATIC (decl)
&& JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
&& DECL_INITIAL (decl))
{
- field_ref = java_complete_tree (DECL_INITIAL (decl));
+ /* When called on a FIELD_DECL of the right (primitive)
+ type, java_complete_tree will try to substitue the decl
+ for it's initial value. */
+ field_ref = java_complete_tree (decl);
static_final_found = 1;
}
else
*where_found = decl = current_this;
*type_found = type = QUAL_DECL_TYPE (decl);
}
- /* We're trying to access the this from somewhere else... */
+ /* We're trying to access the this from somewhere else. Make sure
+ it's allowed before doing so. */
else
{
+ if (!enclosing_context_p (type, current_class))
+ {
+ char *p = xstrdup (lang_printable_name (type, 0));
+ parse_error_context (qual_wfl, "Can't use variable `%s.this': type `%s' isn't an outer type of type `%s'",
+ p, p,
+ lang_printable_name (current_class, 0));
+ free (p);
+ return 1;
+ }
*where_found = decl = build_current_thisn (type);
from_qualified_this = 1;
}
field_decl = lookup_field_wrapper (type,
EXPR_WFL_NODE (qual_wfl));
+
+ /* Maybe what we're trying to access an inner class. */
+ if (!field_decl)
+ {
+ tree ptr, inner_decl;
+
+ BUILD_PTR_FROM_NAME (ptr, EXPR_WFL_NODE (qual_wfl));
+ inner_decl = resolve_class (decl, ptr, NULL_TREE, qual_wfl);
+ if (inner_decl)
+ {
+ check_inner_class_access (inner_decl, decl, qual_wfl);
+ type = TREE_TYPE (inner_decl);
+ decl = inner_decl;
+ from_type = 1;
+ continue;
+ }
+ }
+
if (field_decl == NULL_TREE)
{
parse_error_context
}
/* 6.6 Qualified name and access control. Returns 1 if MEMBER (a decl)
- can't be accessed from REFERENCE (a record type). */
+ can't be accessed from REFERENCE (a record type). This should be
+ used when decl is a field or a method.*/
static int
not_accessible_p (reference, member, from_super)
{
int access_flag = get_access_flags_from_decl (member);
+ /* Inner classes are processed by check_inner_class_access */
+ if (INNER_CLASS_TYPE_P (reference))
+ return 0;
+
/* Access always granted for members declared public */
if (access_flag & ACC_PUBLIC)
return 0;
return 0;
/* Otherwise, access is granted if occuring from the class where
- member is declared or a subclass of it */
+ member is declared or a subclass of it. Find the right
+ context to perform the check */
+ if (PURE_INNER_CLASS_TYPE_P (reference))
+ {
+ while (INNER_CLASS_TYPE_P (reference))
+ {
+ if (inherits_from_p (reference, DECL_CONTEXT (member)))
+ return 0;
+ reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+ }
+ }
if (inherits_from_p (reference, DECL_CONTEXT (member)))
return 0;
return 1;
/* Check access on private members. Access is granted only if it
occurs from within the class in which it is declared. Exceptions
- are accesses from inner-classes. This section is probably not
- complete. FIXME */
+ are accesses from inner-classes. */
if (access_flag & ACC_PRIVATE)
return (current_class == DECL_CONTEXT (member) ? 0 :
(INNER_CLASS_TYPE_P (current_class) ? 0 : 1));
maybe_use_access_method returns a non zero value if the
this_arg has to be moved into the (then generated) stub
- argument list. In the mean time, the selected function
+ argument list. In the meantime, the selected function
might have be replaced by a generated stub. */
if (maybe_use_access_method (is_super_init, &list, &this_arg))
args = tree_cons (NULL_TREE, this_arg, args);
if (non_static_context)
{
ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
- if (ctx == DECL_CONTEXT (md))
+ if (inherits_from_p (ctx, DECL_CONTEXT (md)))
{
ta = build_current_thisn (current_class);
ta = build_wfl_node (ta);
while (type)
{
maybe_build_thisn_access_method (type);
- if (type == DECL_CONTEXT (md))
+ if (inherits_from_p (type, DECL_CONTEXT (md)))
{
ta = build_access_to_thisn (ctx, type, 0);
break;
int lc;
tree class, name, arglist;
{
- static int object_done = 0;
+ static struct hash_table t, *searched_classes = NULL;
+ static int search_not_done = 0;
tree list = NULL_TREE, all_list = NULL_TREE;
+ /* Check the hash table to determine if this class has been searched
+ already. */
+ if (searched_classes)
+ {
+ if (hash_lookup (searched_classes,
+ (const hash_table_key) class, FALSE, NULL))
+ return NULL;
+ }
+ else
+ {
+ hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node,
+ java_hash_compare_tree_node);
+ searched_classes = &t;
+ }
+
+ search_not_done++;
+ hash_lookup (searched_classes,
+ (const hash_table_key) class, TRUE, NULL);
+
if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
{
load_class (class, 1);
}
/* Search interfaces */
- if (CLASS_INTERFACE (TYPE_NAME (class)))
+ if (TREE_CODE (TYPE_NAME (class)) == TYPE_DECL
+ && CLASS_INTERFACE (TYPE_NAME (class)))
{
- static struct hash_table t, *searched_interfaces = NULL;
- static int search_not_done = 0;
int i, n;
tree basetype_vec = TYPE_BINFO_BASETYPES (class);
-
- /* Search in the hash table, otherwise create a new one if
- necessary and insert the new entry. */
-
- if (searched_interfaces)
- {
- if (hash_lookup (searched_interfaces,
- (const hash_table_key) class, FALSE, NULL))
- return NULL;
- }
- else
- {
- hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node,
- java_hash_compare_tree_node);
- searched_interfaces = &t;
- }
-
- hash_lookup (searched_interfaces,
- (const hash_table_key) class, TRUE, NULL);
-
search_applicable_methods_list (lc, TYPE_METHODS (class),
name, arglist, &list, &all_list);
n = TREE_VEC_LENGTH (basetype_vec);
tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
tree rlist;
- search_not_done++;
rlist = find_applicable_accessible_methods_list (lc, t, name,
arglist);
list = chainon (rlist, list);
- search_not_done--;
- }
-
- /* We're done. Reset the searched interfaces list and finally search
- java.lang.Object */
- if (!search_not_done)
- {
- if (!object_done)
- search_applicable_methods_list (lc,
- TYPE_METHODS (object_type_node),
- name, arglist, &list, &all_list);
- hash_table_free (searched_interfaces);
- searched_interfaces = NULL;
}
}
/* Search classes */
{
tree basetype_vec = TYPE_BINFO_BASETYPES (sc);
int n = TREE_VEC_LENGTH (basetype_vec), i;
- object_done = 1;
for (i = 1; i < n; i++)
{
tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
list = chainon (rlist, list);
}
}
- object_done = 0;
}
/* Search enclosing context of inner classes before looking
else
class = sc;
- for (class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class));
- class; class = CLASSTYPE_SUPER (class))
- search_applicable_methods_list (lc, TYPE_METHODS (class),
- name, arglist, &list, &all_list);
+ /* Search superclass */
+ if (!lc && CLASSTYPE_SUPER (class) != NULL_TREE)
+ {
+ tree rlist;
+ class = CLASSTYPE_SUPER (class);
+ rlist = find_applicable_accessible_methods_list (lc, class,
+ name, arglist);
+ list = chainon (rlist, list);
+ }
+ }
+
+ search_not_done--;
+
+ /* We're done. Reset the searched classes list and finally search
+ java.lang.Object if it wasn't searched already. */
+ if (!search_not_done)
+ {
+ if (!lc
+ && TYPE_METHODS (object_type_node)
+ && !hash_lookup (searched_classes,
+ (const hash_table_key) object_type_node,
+ FALSE, NULL))
+ {
+ search_applicable_methods_list (lc,
+ TYPE_METHODS (object_type_node),
+ name, arglist, &list, &all_list);
+ }
+ hash_table_free (searched_classes);
+ searched_classes = NULL;
}
/* Either return the list obtained or all selected (but
return (!list ? all_list : list);
}
-/* Effectively search for the approriate method in method */
+/* Effectively search for the appropriate method in method */
static void
search_applicable_methods_list (lc, method, name, arglist, list, all_list)
*all_list = tree_cons (NULL_TREE, method, *list);
}
}
-}
+}
/* 15.11.2.2 Choose the Most Specific Method */
tree list;
{
int max = 0;
+ int abstract, candidates;
tree current, new_list = NULL_TREE;
for (current = list; current; current = TREE_CHAIN (current))
{
for (method = list; method; method = TREE_CHAIN (method))
{
+ tree method_v, current_v;
/* Don't test a method against itself */
if (method == current)
continue;
- /* Compare arguments and location where method where declared */
- if (argument_types_convertible (TREE_VALUE (method),
- TREE_VALUE (current))
- && valid_method_invocation_conversion_p
- (DECL_CONTEXT (TREE_VALUE (method)),
- DECL_CONTEXT (TREE_VALUE (current))))
+ method_v = TREE_VALUE (method);
+ current_v = TREE_VALUE (current);
+
+ /* Compare arguments and location where methods where declared */
+ if (argument_types_convertible (method_v, current_v))
{
- int v = ++DECL_SPECIFIC_COUNT (TREE_VALUE (current));
- max = (v > max ? v : max);
+ if (valid_method_invocation_conversion_p
+ (DECL_CONTEXT (method_v), DECL_CONTEXT (current_v))
+ || (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v))
+ && enclosing_context_p (DECL_CONTEXT (method_v),
+ DECL_CONTEXT (current_v))))
+ {
+ int v = (DECL_SPECIFIC_COUNT (current_v) +=
+ (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v)) ? 2 : 1));
+ max = (v > max ? v : max);
+ }
}
}
}
/* Review the list and select the maximally specific methods */
- for (current = list; current; current = TREE_CHAIN (current))
+ for (current = list, abstract = -1, candidates = -1;
+ current; current = TREE_CHAIN (current))
if (DECL_SPECIFIC_COUNT (TREE_VALUE (current)) == max)
- new_list = tree_cons (NULL_TREE, TREE_VALUE (current), new_list);
+ {
+ new_list = tree_cons (NULL_TREE, TREE_VALUE (current), new_list);
+ abstract += (METHOD_ABSTRACT (TREE_VALUE (current)) ? 1 : 0);
+ candidates++;
+ }
/* If we have several and they're all abstract, just pick the
closest one. */
+ if (candidates > 0 && (candidates == abstract))
+ {
+ new_list = nreverse (new_list);
+ TREE_CHAIN (new_list) = NULL_TREE;
+ }
- if (new_list && TREE_CHAIN (new_list))
+ /* We have several, we couldn't find a most specific, all but one are
+ abstract, we pick the only non abstract one. */
+ if (candidates > 0 && !max && (candidates == abstract+1))
{
- tree c;
- for (c = new_list; c && METHOD_ABSTRACT (TREE_VALUE (c));
- c = TREE_CHAIN (c))
- ;
- if (!c)
- {
- new_list = nreverse (new_list);
- TREE_CHAIN (new_list) = NULL_TREE;
- }
+ for (current = new_list; current; current = TREE_CHAIN (current))
+ if (!METHOD_ABSTRACT (TREE_VALUE (current)))
+ {
+ TREE_CHAIN (current) = NULL_TREE;
+ new_list = current;
+ }
}
/* If we can't find one, lower expectations and try to gather multiple
tree node;
{
node = java_complete_lhs (node);
- if (TREE_CODE (node) == VAR_DECL && FIELD_STATIC (node)
- && FIELD_FINAL (node) && DECL_INITIAL (node) != NULL_TREE
+ if (JDECL_P (node) && FIELD_STATIC (node) && FIELD_FINAL (node)
+ && DECL_INITIAL (node) != NULL_TREE
&& !flag_emit_xref)
{
tree value = DECL_INITIAL (node);
else
node = patch_switch_statement (node);
- if (TREE_OPERAND (node, 0) == error_mark_node)
+ if (node == error_mark_node || TREE_OPERAND (node, 0) == error_mark_node)
nn = error_mark_node;
else
{
(type == string_ptr_type_node && ! flag_emit_class_files))
return empty_stmt_node;
}
- DECL_INITIAL (nn) = NULL_TREE;
+ if (! flag_emit_class_files)
+ DECL_INITIAL (nn) = NULL_TREE;
}
wfl_op2 = TREE_OPERAND (node, 1);
/* Wrap a non WFL node around a WFL. */
static tree
-build_wfl_wrap (node)
+build_wfl_wrap (node, location)
tree node;
+ int location;
{
tree wfl, node_to_insert = node;
else
wfl = build_expr_wfl (NULL_TREE, ctxp->filename, 0, 0);
- EXPR_WFL_LINECOL (wfl) = EXPR_WFL_LINECOL (node);
+ EXPR_WFL_LINECOL (wfl) = location;
EXPR_WFL_QUALIFICATION (wfl) = build_tree_list (node_to_insert, NULL_TREE);
return wfl;
}
tree n = TREE_OPERAND (rhs, 1);
if (TREE_CODE (n) == VAR_DECL
&& DECL_NAME (n) == TYPE_identifier_node
- && rhs_type == class_ptr_type)
+ && rhs_type == class_ptr_type
+ && TREE_CODE (EXPR_WFL_NODE (wfl)) == IDENTIFIER_NODE)
{
const char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl));
if (!strncmp (self_name, "java.lang.", 10))
if (TYPE_CLASS_P (dest))
return (source == dest
|| inherits_from_p (source, dest)
- || enclosing_context_p (dest, source /*source, dest*/)
|| (cast && inherits_from_p (dest, source)));
if (TYPE_INTERFACE_P (dest))
{
return error_mark_node;
if (!flag_emit_class_files || JPRIMITIVE_TYPE_P (ref_type))
- return build_class_ref (ref_type);
+ {
+ /* A class referenced by `foo.class' is initialized. */
+ return build_class_init (ref_type, build_class_ref (ref_type));
+ }
/* If we're emitting class files and we have to deal with non
primitive types, we invoke (and consider generating) the
{
if (unresolved_type_p (type, NULL))
{
- tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), NULL_TREE);
+ tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), type);
if (!type_decl)
{
parse_error_context (type,
TREE_PURPOSE (current) = NULL_TREE;
all_constant = 0;
}
- if (elt && TREE_VALUE (elt) == error_mark_node)
+ if (elt && TREE_CODE (elt) == TREE_LIST
+ && TREE_VALUE (elt) == error_mark_node)
error_seen = 1;
}
tree op0, op1, val;
enum tree_code code = TREE_CODE (node);
- if (code == STRING_CST)
+ if (code == STRING_CST || code == INTEGER_CST || code == REAL_CST)
return node;
- if (code == INTEGER_CST || code == REAL_CST)
- return convert (TREE_TYPE (context), node);
-
switch (code)
{
case PLUS_EXPR: