From 4dbf4496573255460757de76bb8347669196587c Mon Sep 17 00:00:00 2001 From: Alexandre Petit-Bianco Date: Thu, 20 Jul 2000 17:01:43 -0700 Subject: [PATCH] [multiple changes] 2000-07-13 Alexandre Petit-Bianco * parse.y (patch_method_invocation): Fixed comment. (maybe_use_access_method): Build this$s to the context of the target method, or a type that extends it. Fixes gcj/242. 2000-07-13 Alexandre Petit-Bianco * parse.y (not_accessible_p): Access granted to innerclasses (indirectly) extending the reference type. Fixes gcj/249. 2000-07-10 Alexandre Petit-Bianco * parse.y (resolve_qualified_expression_name): Verify qualified access to `this.' Fixes gcj/239. 2000-07-10 Alexandre Petit-Bianco * class.c (set_super_info): Handled protected inner classes. (common_enclosing_context_p): Bail early if arguments aren't both inner classes. (get_access_flags_from_decl): Handle private and protected inner classes. * java-tree.h (TYPE_PROTECTED_INNER_CLASS): New macro. (CLASS_PROTECTED): Likewise. (struct lang_type): New bitfield `poic.' * parse.y (jdep_resolve_class): Call check_inner_class_access on inner classes only. (check_inner_class_access): Renamed arguments, added comments. Handles protected inner classes (fixes gcj/225) (not_accessible_p): Fixed comments. Avoid handling inner classes. 2000-07-07 Alexandre Petit-Bianco * parse.y (resolve_qualified_expression_name): Handle inner class access. Fixes gcj/256. (Fixes gcj/242, gcj/249, gcj/239, gcj/225 and gcj/256: http://gcc.gnu.org/ml/gcc-patches/2000-07/msg00801.html) From-SVN: r35156 --- gcc/java/class.c | 7 ++- gcc/java/java-tree.h | 3 ++ gcc/java/parse.y | 102 +++++++++++++++++++++++++++++++++---------- 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/gcc/java/class.c b/gcc/java/class.c index d719f04ff26f..f99d0e5bd04b 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -401,6 +401,7 @@ set_super_info (access_flags, this_class, super_class, interfaces_count) if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1; if (access_flags & ACC_STATIC) CLASS_STATIC (class_decl) = 1; if (access_flags & ACC_PRIVATE) CLASS_PRIVATE (class_decl) = 1; + if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1; } /* Return length of inheritance chain of CLAS, where java.lang.Object is 0, @@ -493,7 +494,7 @@ enclosing_context_p (type1, type2) int common_enclosing_context_p (type1, type2) tree type1, type2; { - if (!PURE_INNER_CLASS_TYPE_P (type1) && !PURE_INNER_CLASS_TYPE_P (type2)) + if (!PURE_INNER_CLASS_TYPE_P (type1) || !PURE_INNER_CLASS_TYPE_P (type2)) return 0; for (type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); type1; @@ -1075,6 +1076,10 @@ get_access_flags_from_decl (decl) access_flags |= ACC_ABSTRACT; if (CLASS_STATIC (decl)) access_flags |= ACC_STATIC; + if (CLASS_PRIVATE (decl)) + access_flags |= ACC_PRIVATE; + if (CLASS_PROTECTED (decl)) + access_flags |= ACC_PROTECTED; return access_flags; } if (TREE_CODE (decl) == FUNCTION_DECL) diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 5d132beaa201..07a5521673db 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -576,6 +576,7 @@ struct lang_decl_var for non primitive types when compiling to bytecode. */ #define TYPE_DOT_CLASS(T) (TYPE_LANG_SPECIFIC(T)->dot_class) #define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic) +#define TYPE_PROTECTED_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->poic) struct lang_type { @@ -591,6 +592,7 @@ struct lang_type compiling to bytecode to implement .class */ unsigned pic:1; /* Private Inner Class. */ + unsigned poic:1; /* Protected Inner Class. */ }; #ifdef JAVA_USE_HANDLES @@ -840,6 +842,7 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode, #define CLASS_SUPER(DECL) DECL_LANG_FLAG_6 (DECL) #define CLASS_STATIC(DECL) DECL_LANG_FLAG_7 (DECL) #define CLASS_PRIVATE(DECL) (TYPE_PRIVATE_INNER_CLASS (TREE_TYPE (DECL))) +#define CLASS_PROTECTED(DECL) (TYPE_PROTECTED_INNER_CLASS (TREE_TYPE (DECL))) /* @deprecated marker flag on methods, fields and classes */ diff --git a/gcc/java/parse.y b/gcc/java/parse.y index c13eb4bc350f..af7b19b11bd4 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -5199,7 +5199,8 @@ jdep_resolve_class (dep) if (!decl) complete_class_report_errors (dep); - check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep)); + if (PURE_INNER_CLASS_DECL_P (decl)) + check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep)); return decl; } @@ -6781,24 +6782,37 @@ lookup_package_type (name, from) } static void -check_inner_class_access (decl, enclosing_type, cl) - tree decl, enclosing_type, cl; +check_inner_class_access (decl, enclosing_decl, cl) + tree decl, enclosing_decl, cl; { - if (!decl) - return; + 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. */ - if (!(cl && PURE_INNER_CLASS_DECL_P (decl) && CLASS_PRIVATE (decl)) - || (PURE_INNER_CLASS_DECL_P (enclosing_type) - && common_enclosing_context_p (TREE_TYPE (enclosing_type), - TREE_TYPE (decl))) - || enclosing_context_p (TREE_TYPE (enclosing_type), TREE_TYPE (decl))) + 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; - parse_error_context (cl, "Can't access nested %s %s. Only public classes and interfaces in other packages can be accessed", + /* 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)); } @@ -9001,9 +9015,19 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) *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; } @@ -9169,6 +9193,24 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) 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 @@ -9283,7 +9325,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found) } /* 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) @@ -9292,6 +9335,10 @@ 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; @@ -9310,7 +9357,17 @@ not_accessible_p (reference, member, from_super) 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; @@ -9318,8 +9375,7 @@ not_accessible_p (reference, member, from_super) /* 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)); @@ -9643,7 +9699,7 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl) 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); @@ -9811,7 +9867,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) 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); @@ -9822,7 +9878,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) 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;