mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 09:20:44 +08:00
parse.y (parser_check_super_interface): Don't call check_pkg_class_access for an inner interface.
* parse.y (parser_check_super_interface): Don't call check_pkg_class_access for an inner interface. (parser_check_super): Don't call check_pkg_class_access for inner class. (do_resolve_class): Simplify enclosing type loop. Don't call check_pkg_class_access if CL and DECL are not set. (find_in_imports_on_demand): Set DECL if class_type needed to be loaded. Don't call check_pkg_class_access for an inner class. (check_inner_class_access): Rewritten to implement member access rules as per spec 6.6.1. (check_pkg_class_access): Handle the empty package correctly. (in_same_package): New function. Determine if two classes are in the same package. From-SVN: r39909
This commit is contained in:
parent
2c0fc02de2
commit
a648f4e4c8
@ -1,3 +1,19 @@
|
||||
2001-02-19 Bryce McKinlay <bryce@albatross.co.nz>
|
||||
|
||||
* parse.y (parser_check_super_interface): Don't call
|
||||
check_pkg_class_access for an inner interface.
|
||||
(parser_check_super): Don't call check_pkg_class_access for inner
|
||||
class.
|
||||
(do_resolve_class): Simplify enclosing type loop. Don't call
|
||||
check_pkg_class_access if CL and DECL are not set.
|
||||
(find_in_imports_on_demand): Set DECL if class_type needed to be
|
||||
loaded. Don't call check_pkg_class_access for an inner class.
|
||||
(check_inner_class_access): Rewritten to implement member access
|
||||
rules as per spec 6.6.1.
|
||||
(check_pkg_class_access): Handle the empty package correctly.
|
||||
(in_same_package): New function. Determine if two classes are in the
|
||||
same package.
|
||||
|
||||
2001-02-18 Bryce McKinlay <bryce@albatross.co.nz>
|
||||
|
||||
* typeck.c (build_java_array_type): Don't try to poke a public `clone'
|
||||
|
171
gcc/java/parse.y
171
gcc/java/parse.y
@ -127,6 +127,7 @@ static int check_class_interface_creation PARAMS ((int, int, tree,
|
||||
static tree patch_method_invocation PARAMS ((tree, tree, tree, int,
|
||||
int *, tree *));
|
||||
static int breakdown_qualified PARAMS ((tree *, tree *, tree));
|
||||
static int in_same_package PARAMS ((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));
|
||||
@ -4895,8 +4896,10 @@ parser_check_super_interface (super_decl, this_decl, this_wfl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check scope: same package OK, other package: OK if public */
|
||||
if (check_pkg_class_access (DECL_NAME (super_decl), lookup_cl (this_decl)))
|
||||
/* Check top-level interface access. Inner classes are subject to member
|
||||
access rules (6.6.1). */
|
||||
if (! INNER_CLASS_P (super_type)
|
||||
&& check_pkg_class_access (DECL_NAME (super_decl), lookup_cl (this_decl)))
|
||||
return 1;
|
||||
|
||||
SOURCE_FRONTEND_DEBUG (("Completing interface %s with %s",
|
||||
@ -4932,8 +4935,10 @@ parser_check_super (super_decl, this_decl, wfl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check scope: same package OK, other package: OK if public */
|
||||
if (check_pkg_class_access (DECL_NAME (super_decl), wfl))
|
||||
/* Check top-level class scope. Inner classes are subject to member access
|
||||
rules (6.6.1). */
|
||||
if (! INNER_CLASS_P (super_type)
|
||||
&& (check_pkg_class_access (DECL_NAME (super_decl), wfl)))
|
||||
return 1;
|
||||
|
||||
SOURCE_FRONTEND_DEBUG (("Completing class %s with %s",
|
||||
@ -5508,7 +5513,6 @@ do_resolve_class (enclosing, class_type, decl, cl)
|
||||
being loaded from class file. FIXME. */
|
||||
while (enclosing)
|
||||
{
|
||||
tree name;
|
||||
tree intermediate;
|
||||
|
||||
if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
|
||||
@ -5527,19 +5531,12 @@ do_resolve_class (enclosing, class_type, decl, cl)
|
||||
/* Now go to the upper classes, bail out if necessary. */
|
||||
enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
|
||||
if (!enclosing || enclosing == object_type_node)
|
||||
break;
|
||||
|
||||
if (TREE_CODE (enclosing) == RECORD_TYPE)
|
||||
{
|
||||
enclosing = TYPE_NAME (enclosing);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
if (TREE_CODE (enclosing) == IDENTIFIER_NODE)
|
||||
BUILD_PTR_FROM_NAME (name, enclosing);
|
||||
if (TREE_CODE (enclosing) == POINTER_TYPE)
|
||||
enclosing = do_resolve_class (NULL, enclosing, NULL, NULL);
|
||||
else
|
||||
name = enclosing;
|
||||
enclosing = do_resolve_class (NULL, name, NULL, NULL);
|
||||
enclosing = TYPE_NAME (enclosing);
|
||||
}
|
||||
|
||||
/* 1- Check for the type in single imports. This will change
|
||||
@ -5592,10 +5589,19 @@ do_resolve_class (enclosing, class_type, decl, cl)
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
if (!cl)
|
||||
cl = lookup_cl (decl);
|
||||
|
||||
/* If we don't have a value for CL, then we're being called recursively.
|
||||
We can't check package access just yet, but it will be taken care of
|
||||
by the caller. */
|
||||
if (cl)
|
||||
{
|
||||
if (check_pkg_class_access (TYPE_NAME (class_type), cl))
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* 6- Last call for a resolution */
|
||||
return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
|
||||
}
|
||||
@ -6671,9 +6677,16 @@ find_in_imports_on_demand (class_type)
|
||||
loaded and not seen in source yet, the load */
|
||||
if (!decl || (!CLASS_LOADED_P (TREE_TYPE (decl))
|
||||
&& !CLASS_FROM_SOURCE_P (TREE_TYPE (decl))))
|
||||
load_class (node_to_use, 0);
|
||||
{
|
||||
load_class (node_to_use, 0);
|
||||
decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
|
||||
}
|
||||
lineno = saved_lineno;
|
||||
return check_pkg_class_access (TYPE_NAME (class_type), cl);
|
||||
if (! INNER_CLASS_P (TREE_TYPE (decl)))
|
||||
return check_pkg_class_access (TYPE_NAME (class_type), cl);
|
||||
else
|
||||
/* 6.6.1: Inner classes are subject to member access rules. */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */
|
||||
@ -6767,11 +6780,15 @@ lookup_package_type (name, from)
|
||||
return get_identifier (subname);
|
||||
}
|
||||
|
||||
/* Check accessibility of inner classes according to member access rules.
|
||||
DECL is the inner class, ENCLOSING_DECL is the class from which the
|
||||
access is being attempted. */
|
||||
|
||||
static void
|
||||
check_inner_class_access (decl, enclosing_decl, cl)
|
||||
tree decl, enclosing_decl, cl;
|
||||
{
|
||||
int access = 0;
|
||||
const char *access;
|
||||
|
||||
/* 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
|
||||
@ -6781,30 +6798,69 @@ check_inner_class_access (decl, enclosing_decl, cl)
|
||||
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. */
|
||||
tree enclosing_decl_type = TREE_TYPE (enclosing_decl);
|
||||
|
||||
if (CLASS_PRIVATE (decl))
|
||||
access = 1;
|
||||
if (CLASS_PROTECTED (decl))
|
||||
access = 2;
|
||||
if (!access)
|
||||
return;
|
||||
{
|
||||
/* Access is permitted only within the body of the top-level
|
||||
class in which DECL is declared. */
|
||||
tree top_level = decl;
|
||||
while (DECL_CONTEXT (top_level))
|
||||
top_level = DECL_CONTEXT (top_level);
|
||||
while (DECL_CONTEXT (enclosing_decl))
|
||||
enclosing_decl = DECL_CONTEXT (enclosing_decl);
|
||||
if (top_level == enclosing_decl)
|
||||
return;
|
||||
access = "private";
|
||||
}
|
||||
else if (CLASS_PROTECTED (decl))
|
||||
{
|
||||
tree decl_context;
|
||||
/* Access is permitted from within the same package... */
|
||||
if (in_same_package (decl, enclosing_decl))
|
||||
return;
|
||||
|
||||
if (common_enclosing_context_p (TREE_TYPE (enclosing_decl),
|
||||
TREE_TYPE (decl))
|
||||
|| enclosing_context_p (TREE_TYPE (enclosing_decl),
|
||||
TREE_TYPE (decl)))
|
||||
/* ... or from within the body of a subtype of the context in which
|
||||
DECL is declared. */
|
||||
decl_context = DECL_CONTEXT (decl);
|
||||
while (enclosing_decl)
|
||||
{
|
||||
if (CLASS_INTERFACE (decl))
|
||||
{
|
||||
if (interface_of_p (TREE_TYPE (decl_context),
|
||||
enclosing_decl_type))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Eww. The order of the arguments is different!! */
|
||||
if (inherits_from_p (enclosing_decl_type,
|
||||
TREE_TYPE (decl_context)))
|
||||
return;
|
||||
}
|
||||
enclosing_decl = DECL_CONTEXT (enclosing_decl);
|
||||
}
|
||||
access = "protected";
|
||||
}
|
||||
else if (! CLASS_PUBLIC (decl))
|
||||
{
|
||||
/* Access is permitted only from within the same package as DECL. */
|
||||
if (in_same_package (decl, enclosing_decl))
|
||||
return;
|
||||
access = "non-public";
|
||||
}
|
||||
else
|
||||
/* Class is public. */
|
||||
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"),
|
||||
parse_error_context (cl, "Nested %s %s is %s; cannot be accessed from here",
|
||||
(CLASS_INTERFACE (decl) ? "interface" : "class"),
|
||||
lang_printable_name (decl, 0));
|
||||
lang_printable_name (decl, 0), access);
|
||||
}
|
||||
|
||||
/* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no
|
||||
access violations were found, 1 otherwise. */
|
||||
/* Accessibility check for top-level classes. If CLASS_NAME is in a foreign
|
||||
package, it must be PUBLIC. Return 0 if no access violations were found,
|
||||
1 otherwise. */
|
||||
|
||||
static int
|
||||
check_pkg_class_access (class_name, cl)
|
||||
@ -6813,7 +6869,7 @@ check_pkg_class_access (class_name, cl)
|
||||
{
|
||||
tree type;
|
||||
|
||||
if (!QUALIFIED_P (class_name) || !IDENTIFIER_CLASS_VALUE (class_name))
|
||||
if (!IDENTIFIER_CLASS_VALUE (class_name))
|
||||
return 0;
|
||||
|
||||
if (!(type = TREE_TYPE (IDENTIFIER_CLASS_VALUE (class_name))))
|
||||
@ -6825,7 +6881,11 @@ check_pkg_class_access (class_name, cl)
|
||||
allowed. */
|
||||
tree l, r;
|
||||
breakdown_qualified (&l, &r, class_name);
|
||||
if (!QUALIFIED_P (class_name) && !ctxp->package)
|
||||
/* Both in the empty package. */
|
||||
return 0;
|
||||
if (l == ctxp->package)
|
||||
/* Both in the same package. */
|
||||
return 0;
|
||||
|
||||
parse_error_context
|
||||
@ -10948,6 +11008,35 @@ breakdown_qualified (left, right, source)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return TRUE if two classes are from the same package. */
|
||||
|
||||
static int
|
||||
in_same_package (name1, name2)
|
||||
tree name1, name2;
|
||||
{
|
||||
tree tmp;
|
||||
tree pkg1;
|
||||
tree pkg2;
|
||||
|
||||
if (TREE_CODE (name1) == TYPE_DECL)
|
||||
name1 = DECL_NAME (name1);
|
||||
if (TREE_CODE (name2) == TYPE_DECL)
|
||||
name2 = DECL_NAME (name2);
|
||||
|
||||
if (QUALIFIED_P (name1) != QUALIFIED_P (name2))
|
||||
/* One in empty package. */
|
||||
return 0;
|
||||
|
||||
if (QUALIFIED_P (name1) == 0 && QUALIFIED_P (name2) == 0)
|
||||
/* Both in empty package. */
|
||||
return 1;
|
||||
|
||||
breakdown_qualified (&pkg1, &tmp, name1);
|
||||
breakdown_qualified (&pkg2, &tmp, name2);
|
||||
|
||||
return (pkg1 == pkg2);
|
||||
}
|
||||
|
||||
/* Patch tree nodes in a function body. When a BLOCK is found, push
|
||||
local variable decls if present.
|
||||
Same as java_complete_lhs, but does resolve static finals to values. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user