re PR java/18119 (Private inner class is visible when it shouldn't be)

2005-07-07  Bryce McKinlay  <mckinlay@redhat.com>

	PR java/18119
	* parse.y (inner_class_accessible): New function. Logic moved from
	check_inner_class_access.
	(check_inner_class_access): Use inner_class_accessible.
	(resolve_inner_class): Simplify arguments. Create circularity hash
	here. Keep looking for classes if we found one that was
	inaccessible. Return the inaccessible class only if there is no other
	match.
	(do_resolve_class): Update for new resolve_inner_class arguments.
	Don't create circularity_hash here.

From-SVN: r101715
This commit is contained in:
Bryce McKinlay 2005-07-07 14:43:59 +00:00 committed by Bryce McKinlay
parent 90475fe0fc
commit cb14ee6a76
4 changed files with 116 additions and 81 deletions

View File

@ -1,3 +1,15 @@
2005-07-07 Bryce McKinlay <mckinlay@redhat.com>
PR java/18119
* parse.y (inner_class_accessible): New function. Logic moved from
check_inner_class_access.
(check_inner_class_access): Use inner_class_accessible.
(resolve_inner_class): Simplify arguments. Create circularity hash
here. Keep looking for classes if we found one that was inaccessible.
Return the inaccessible class only if there is no other match.
(do_resolve_class): Update for new resolve_inner_class arguments.
Don't create circularity_hash here.
2005-07-07 Bryce McKinlay <mckinlay@redhat.com>
PR java/21045

View File

@ -112,6 +112,7 @@ static int process_imports (void);
static void read_import_dir (tree);
static int find_in_imports_on_demand (tree, tree);
static void find_in_imports (tree, tree);
static bool inner_class_accessible (tree, tree);
static void check_inner_class_access (tree, tree, tree);
static int check_pkg_class_access (tree, tree, bool, tree);
static tree resolve_package (tree, tree *, tree *);
@ -311,7 +312,7 @@ static int pop_current_osb (struct parser_ctxt *);
static tree maybe_make_nested_class_name (tree);
static int make_nested_class_name (tree);
static void link_nested_class_to_enclosing (void);
static tree resolve_inner_class (htab_t, tree, tree *, tree *, tree);
static tree resolve_inner_class (tree, tree, tree, tree);
static tree find_as_inner_class (tree, tree, tree);
static tree find_as_inner_class_do (tree, tree);
static int check_inner_class_redefinition (tree, tree);
@ -3663,46 +3664,52 @@ check_inner_class_redefinition (tree raw_name, tree cl)
return 0;
}
/* Tries to find a decl for CLASS_TYPE within ENCLOSING. If we fail,
we remember ENCLOSING and SUPER. */
/* Tries to find a decl for CLASS_TYPE within ENCLOSING. May return an
invisible/non-accessible matching decl when an accessible one could not be
found, in order to give a better error message when accessibility is
checked later. */
static tree
resolve_inner_class (htab_t circularity_hash, tree cl, tree *enclosing,
tree *super, tree class_type)
resolve_inner_class (tree context, tree cl, tree enclosing, tree class_type)
{
tree local_enclosing = *enclosing;
tree local_super = NULL_TREE;
tree candidate = NULL_TREE;
while (local_enclosing)
/* This hash table is used to register the classes we're going
through when searching the current class as an inner class, in
order to detect circular references. */
htab_t circularity_hash = htab_create (20, htab_hash_pointer, htab_eq_pointer,
NULL);
while (enclosing)
{
tree intermediate, decl;
tree decl;
*htab_find_slot (circularity_hash, local_enclosing, INSERT) =
local_enclosing;
*htab_find_slot (circularity_hash, enclosing, INSERT) = enclosing;
if ((decl = find_as_inner_class (local_enclosing, class_type, cl)))
return decl;
intermediate = local_enclosing;
/* Explore enclosing contexts. */
while (INNER_CLASS_DECL_P (intermediate))
{
intermediate = DECL_CONTEXT (intermediate);
if ((decl = find_as_inner_class (intermediate, class_type, cl)))
return decl;
}
if ((decl = find_as_inner_class (enclosing, class_type, cl)))
{
if (inner_class_accessible (decl, context))
{
candidate = decl;
break;
}
else
if (candidate == NULL_TREE)
candidate = decl;
}
/* Now go to the upper classes, bail out if necessary. We will
analyze the returned SUPER and act accordingly (see
do_resolve_class). */
if (JPRIMITIVE_TYPE_P (TREE_TYPE (local_enclosing))
|| TREE_TYPE (local_enclosing) == void_type_node)
if (JPRIMITIVE_TYPE_P (TREE_TYPE (enclosing))
|| TREE_TYPE (enclosing) == void_type_node)
{
parse_error_context (cl, "Qualifier must be a reference");
local_enclosing = NULL_TREE;
enclosing = NULL_TREE;
break;
}
local_super = CLASSTYPE_SUPER (TREE_TYPE (local_enclosing));
local_super = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
if (!local_super || local_super == object_type_node)
break;
@ -3716,22 +3723,22 @@ resolve_inner_class (htab_t circularity_hash, tree cl, tree *enclosing,
if (htab_find (circularity_hash, local_super) != NULL)
{
if (!cl)
cl = lookup_cl (local_enclosing);
cl = lookup_cl (enclosing);
parse_error_context
(cl, "Cyclic inheritance involving %s",
IDENTIFIER_POINTER (DECL_NAME (local_enclosing)));
local_enclosing = NULL_TREE;
IDENTIFIER_POINTER (DECL_NAME (enclosing)));
enclosing = NULL_TREE;
}
else
local_enclosing = local_super;
enclosing = local_super;
}
/* We failed. Return LOCAL_SUPER and LOCAL_ENCLOSING. */
*super = local_super;
*enclosing = local_enclosing;
htab_delete (circularity_hash);
return NULL_TREE;
/* We failed, but we might have found a matching class that wasn't
accessible. Return that to get a better error message. */
return candidate;
}
/* Within ENCLOSING, find a decl for NAME and return it. NAME can be
@ -5866,10 +5873,10 @@ tree
do_resolve_class (tree enclosing, tree import_type, tree class_type, tree decl,
tree cl)
{
tree new_class_decl = NULL_TREE, super = NULL_TREE;
tree new_class_decl = NULL_TREE;
tree saved_enclosing_type = enclosing ? TREE_TYPE (enclosing) : NULL_TREE;
tree candidate = NULL_TREE;
tree decl_result;
htab_t circularity_hash;
if (QUALIFIED_P (TYPE_NAME (class_type)))
{
@ -5893,12 +5900,7 @@ do_resolve_class (tree enclosing, tree import_type, tree class_type, tree decl,
if (enclosing)
{
/* This hash table is used to register the classes we're going
through when searching the current class as an inner class, in
order to detect circular references. Remember to free it before
returning the section 0- of this function. */
circularity_hash = htab_create (20, htab_hash_pointer, htab_eq_pointer,
NULL);
tree context = enclosing;
/* 0- Search in the current class as an inner class.
Maybe some code here should be added to load the class or
@ -5906,22 +5908,23 @@ do_resolve_class (tree enclosing, tree import_type, tree class_type, tree decl,
being loaded from class file. FIXME. */
while (enclosing)
{
new_class_decl = resolve_inner_class (circularity_hash, cl, &enclosing,
&super, class_type);
new_class_decl = resolve_inner_class (context, cl, enclosing, class_type);
if (new_class_decl)
break;
{
if (inner_class_accessible (new_class_decl, context))
break;
else
if (candidate == NULL_TREE)
candidate = new_class_decl;
new_class_decl = NULL_TREE;
}
/* If we haven't found anything because SUPER reached Object and
ENCLOSING happens to be an innerclass, try the enclosing context. */
if ((!super || super == object_type_node) &&
enclosing && INNER_CLASS_DECL_P (enclosing))
enclosing = DECL_CONTEXT (enclosing);
else
enclosing = NULL_TREE;
/* Now that we've looked through all superclasses, try the enclosing
context. */
enclosing = DECL_CONTEXT (enclosing);
}
htab_delete (circularity_hash);
if (new_class_decl)
return new_class_decl;
}
@ -6007,7 +6010,10 @@ do_resolve_class (tree enclosing, tree import_type, tree class_type, tree decl,
}
} while (!decl_result && separator);
}
return decl_result;
if (decl_result)
return decl_result;
else
return candidate;
}
static tree
@ -7263,25 +7269,14 @@ resolve_package (tree pkg, tree *next, tree *type_name)
return decl;
}
/* Check accessibility of inner class DECL, from the context ENCLOSING_DECL,
according to member access rules. */
/* 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 (tree decl, tree enclosing_decl, tree cl)
static bool
inner_class_accessible (tree decl, tree enclosing_decl)
{
const char *access;
tree enclosing_decl_type;
/* 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;
enclosing_decl_type = TREE_TYPE (enclosing_decl);
if (CLASS_PRIVATE (decl))
@ -7294,15 +7289,14 @@ check_inner_class_access (tree decl, tree enclosing_decl, tree cl)
while (DECL_CONTEXT (enclosing_decl))
enclosing_decl = DECL_CONTEXT (enclosing_decl);
if (top_level == enclosing_decl)
return;
access = "private";
return true;
}
else if (CLASS_PROTECTED (decl))
{
tree decl_context;
/* Access is permitted from within the same package... */
if (in_same_package (decl, enclosing_decl))
return;
return true;
/* ... or from within the body of a subtype of the context in which
DECL is declared. */
@ -7313,30 +7307,58 @@ check_inner_class_access (tree decl, tree enclosing_decl, tree cl)
{
if (interface_of_p (TREE_TYPE (decl_context),
enclosing_decl_type))
return;
return true;
}
else
{
/* Eww. The order of the arguments is different!! */
if (inherits_from_p (enclosing_decl_type,
TREE_TYPE (decl_context)))
return;
return true;
}
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";
return true;
}
else
/* Class is public. */
return true;
return false;
}
/* 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 (tree decl, tree enclosing_decl, tree cl)
{
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
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;
if (inner_class_accessible (decl, enclosing_decl))
return;
if (CLASS_PRIVATE (decl))
access = "private";
else if (CLASS_PROTECTED (decl))
access = "protected";
else
access = "non-public";
parse_error_context (cl, "Nested %s %s is %s; cannot be accessed from here",
(CLASS_INTERFACE (decl) ? "interface" : "class"),
lang_printable_name (decl, 2), access);

View File

@ -1,3 +1,8 @@
2005-07-07 Bryce McKinlay <mckinlay@redhat.com>
* testsuite/libjava.jacks/jacks.xfail: Remove 6.5.5.1-nested-4,
6.5.5.1-nested-7, 6.5.5.1-nested-16, 6.5.5.1-nested-17.
2005-07-07 Bryce McKinlay <mckinlay@redhat.com>
* testsuite/libjava.compile/PR21045.java: New test.

View File

@ -466,14 +466,10 @@
6.5.5.1-import-2
6.5.5.1-import-3
6.5.5.1-nested-14
6.5.5.1-nested-16
6.5.5.1-nested-17
6.5.5.1-nested-19
6.5.5.1-nested-20
6.5.5.1-nested-21
6.5.5.1-nested-23
6.5.5.1-nested-4
6.5.5.1-nested-7
6.5.5.1-nested-8
6.5.5.1-nested-9
6.5.5.2-type-4