From a648f4e4c8f0690cf47fe6fd93030e0a8f63c6a2 Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Mon, 19 Feb 2001 22:48:16 +0000 Subject: [PATCH] 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 --- gcc/java/ChangeLog | 16 +++++ gcc/java/parse.y | 171 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 146 insertions(+), 41 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index f19c3fffc49..4a74ae7214e 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,19 @@ +2001-02-19 Bryce McKinlay + + * 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 * typeck.c (build_java_array_type): Don't try to poke a public `clone' diff --git a/gcc/java/parse.y b/gcc/java/parse.y index cb8525a8521..971a8876cc2 100644 --- a/gcc/java/parse.y +++ b/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. */ -- 2.30.2