re PR java/8618 (call to private constructor allowed for anonymous inner class)
authorBryce McKinlay <mckinlay@redhat.com>
Sat, 10 Jul 2004 05:38:15 +0000 (05:38 +0000)
committerBryce McKinlay <bryce@gcc.gnu.org>
Sat, 10 Jul 2004 05:38:15 +0000 (06:38 +0100)
2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>

        PR java/8618
        * parse.y (create_anonymous_class): Remove 'location' argument. Use
        the WFL from TYPE_NAME to get line number for the decl. Fix comment.
        (craft_constructor): Inherit access flags for implicit constructor
        from the enclosing class.
        (create_class): Fix comment typo.
        (resolve_qualified_expression_name): Pass type of qualifier to
        not_accessible_p, not the type in which target field was found.
        (not_accessible_p): Handle inner classes. Expand protected
        qualifier-subtype check to enclosing instances, but don't apply this
        check to static members. Allow protected access to inner classes
        of a subtype. Allow private access within common enclosing context.
        (build_super_invocation): Get WFL line number info from current
        class decl.
        (build_incomplete_class_ref): Update for new create_anonymous_class
        signature.
        * parse.h (INNER_ENCLOSING_SCOPE_CHECK): Use
        common_enclosing_instance_p.
        * class.c (common_enclosing_context_p): New. Determine if types
        share a common enclosing context, even across static contexts.
        (common_enclosing_instance_p): Renamed from
        common_enclosing_context_p. Determines if types share a common
        non-static enclosing instance.
        * java-tree.h (common_enclosing_instance_p): Declare.
        * jcf-write.c (get_method_access_flags): New. Surpress private flag
        for inner class constructors.
        (generate_classfile): Use get_method_access_flags.

From-SVN: r84443

gcc/java/ChangeLog
gcc/java/class.c
gcc/java/java-tree.h
gcc/java/jcf-write.c
gcc/java/parse.h
gcc/java/parse.y

index b2492677b214f64e597abba7b2f1e9697b58a5f6..fea2c218baf5b005a673bf41eb3993f3251ddd2e 100644 (file)
@@ -1,3 +1,33 @@
+2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>
+
+       PR java/8618
+       * parse.y (create_anonymous_class): Remove 'location' argument. Use
+       the WFL from TYPE_NAME to get line number for the decl. Fix comment.
+       (craft_constructor): Inherit access flags for implicit constructor
+       from the enclosing class.
+       (create_class): Fix comment typo.
+       (resolve_qualified_expression_name): Pass type of qualifier to
+       not_accessible_p, not the type in which target field was found.
+       (not_accessible_p): Handle inner classes. Expand protected 
+       qualifier-subtype check to enclosing instances, but don't apply this 
+       check to static members. Allow protected access to inner classes
+       of a subtype. Allow private access within common enclosing context.
+       (build_super_invocation): Get WFL line number info from current
+       class decl.
+       (build_incomplete_class_ref): Update for new create_anonymous_class
+       signature.
+       * parse.h (INNER_ENCLOSING_SCOPE_CHECK): Use
+       common_enclosing_instance_p.
+       * class.c (common_enclosing_context_p): New. Determine if types
+       share a common enclosing context, even across static contexts.
+       (common_enclosing_instance_p): Renamed from 
+       common_enclosing_context_p. Determines if types share a common
+       non-static enclosing instance.
+       * java-tree.h (common_enclosing_instance_p): Declare.
+       * jcf-write.c (get_method_access_flags): New. Surpress private flag
+       for inner class constructors.
+       (generate_classfile): Use get_method_access_flags.
+
 2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>
 
        * class.c (interface_of_p): Check for null TYPE_BINFO.
index 90f2789c8e862e8164dfac790f09cd02dab1a6bb..1273b62155f465bdc2f368c9947a1bcad08b07e0 100644 (file)
@@ -587,11 +587,33 @@ enclosing_context_p (tree type1, tree type2)
   return 0;
 }
 
-/* Return 1 iff there exists a common enclosing context between TYPE1
-   and TYPE2.  */
+
+/* Return 1 iff TYPE1 and TYPE2 share a common enclosing class, regardless of
+   nesting level.  */
 
 int
 common_enclosing_context_p (tree type1, tree type2)
+{
+  for (type1; type1; 
+       type1 = (INNER_CLASS_TYPE_P (type1) ?
+               TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE))
+    {
+      tree current;
+      for (current = type2; current;
+          current = (INNER_CLASS_TYPE_P (current) ?
+                     TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) : 
+                     NULL_TREE))
+       if (type1 == current)
+         return 1;
+    }
+  return 0;
+}
+
+/* Return 1 iff there exists a common enclosing "this" between TYPE1
+   and TYPE2, without crossing any static context.  */
+
+int
+common_enclosing_instance_p (tree type1, tree type2)
 {
   if (!PURE_INNER_CLASS_TYPE_P (type1) || !PURE_INNER_CLASS_TYPE_P (type2))
     return 0;
index 1fef83260d03d86cce14c54c939792de5d847ddf..d9e641547bdff589b850d514e3a7368eb802ff97 100644 (file)
@@ -1238,6 +1238,7 @@ extern int get_access_flags_from_decl (tree);
 extern int interface_of_p (tree, tree);
 extern int inherits_from_p (tree, tree);
 extern int common_enclosing_context_p (tree, tree);
+extern int common_enclosing_instance_p (tree, tree);
 extern int enclosing_context_p (tree, tree);
 extern tree build_result_decl (tree);
 extern void emit_handlers (void);
index c95df1eb561b43c2a5e403e02c6c2527b1fb531b..e34543c44c77fcfe7d52c933adc40263f738406b 100644 (file)
@@ -2903,6 +2903,22 @@ get_classfile_modifiers (tree class)
   return flags;
 }
 
+/* Get the access flags (modifiers) for a method to be used in the class 
+   file.  */
+
+static int
+get_method_access_flags (tree decl)
+{
+  int flags = get_access_flags (decl);
+
+  /* Promote "private" inner-class constructors to package-private.  */
+  if (DECL_CONSTRUCTOR_P (decl)
+      && INNER_CLASS_DECL_P (TYPE_NAME (DECL_CONTEXT (decl))))
+    flags &= ~(ACC_PRIVATE);
+
+  return flags;
+}
+
 /* Generate and return a list of chunks containing the class CLAS
    in the .class file representation.  The list can be written to a
    .class file using write_chunks.  Allocate chunks from obstack WORK. */
@@ -3034,7 +3050,7 @@ generate_classfile (tree clas, struct jcf_partial *state)
 
       current_function_decl = part;
       ptr = append_chunk (NULL, 8, state);
-      i = get_access_flags (part);  PUT2 (i);
+      i = get_method_access_flags (part);  PUT2 (i);
       i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
       i = find_utf8_constant (&state->cpool, build_java_signature (type));
       PUT2 (i);
index cf62dae8446566dc151ef6c46317f2671efcce4f..f0fb67acdb02d2c08cf031e16da6f86a424d9ca2 100644 (file)
@@ -842,7 +842,7 @@ struct parser_ctxt GTY(()) {
            != TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this))))              \
        && !inherits_from_p (TREE_TYPE (TREE_TYPE (current_this)),            \
                             TREE_TYPE (DECL_CONTEXT (TYPE_NAME (T))))        \
-        && !common_enclosing_context_p (TREE_TYPE (TREE_TYPE (current_this)), \
+        && !common_enclosing_instance_p (TREE_TYPE (TREE_TYPE (current_this)),\
                                        (T))                                  \
        && INNER_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_this)))          \
        && !inherits_from_p                                                   \
index 3df330d3c253108f621b63ef0be95e190882b791..8d65bd1e52f4eca139e90aecad590a908a930565 100644 (file)
@@ -320,7 +320,7 @@ static int outer_field_expanded_access_p (tree, tree *,
 static tree outer_field_access_fix (tree, tree, tree);
 static tree build_incomplete_class_ref (int, tree);
 static tree patch_incomplete_class_ref (tree);
-static tree create_anonymous_class (int, tree);
+static tree create_anonymous_class (tree);
 static void patch_anonymous_class (tree, tree, tree);
 static void add_inner_class_fields (tree, tree);
 
@@ -2034,7 +2034,7 @@ class_instance_creation_expression:
 
 anonymous_class_creation:
        NEW_TK class_type OP_TK argument_list CP_TK
-               { create_anonymous_class ($1.location, $2); }
+               { create_anonymous_class ($2); }
         class_body
                {
                  tree id = build_wfl_node (DECL_NAME (GET_CPC ()));
@@ -2067,7 +2067,7 @@ anonymous_class_creation:
 
                }
 |      NEW_TK class_type OP_TK CP_TK
-               { create_anonymous_class ($1.location, $2); }
+               { create_anonymous_class ($2); }
         class_body
                {
                  tree id = build_wfl_node (DECL_NAME (GET_CPC ()));
@@ -3905,8 +3905,11 @@ patch_anonymous_class (tree type_decl, tree class_decl, tree wfl)
     }
 }
 
+/* Create an anonymous class which extends/implements TYPE_NAME, and return
+   its decl.  */
+
 static tree
-create_anonymous_class (int location, tree type_name)
+create_anonymous_class (tree type_name)
 {
   char buffer [80];
   tree super = NULL_TREE, itf = NULL_TREE;
@@ -3915,7 +3918,7 @@ create_anonymous_class (int location, tree type_name)
   /* The unqualified name of the anonymous class. It's just a number. */
   sprintf (buffer, "%d", anonymous_class_counter++);
   id = build_wfl_node (get_identifier (buffer));
-  EXPR_WFL_LINECOL (id) = location;
+  EXPR_WFL_LINECOL (id) = EXPR_WFL_LINECOL (type_name);
 
   /* We know about the type to extend/implement. We go ahead */
   if ((type_decl = IDENTIFIER_CLASS_VALUE (EXPR_WFL_NODE (type_name))))
@@ -4035,7 +4038,7 @@ create_class (int flags, tree id, tree super, tree interfaces)
 
   /* 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. */
+     This does not occur for top level (static) inner classes. */
   if (PURE_INNER_CLASS_DECL_P (decl))
     add_inner_class_fields (decl, current_function_decl);
 
@@ -5393,8 +5396,9 @@ craft_constructor (tree class_decl, tree args)
 {
   tree class_type = TREE_TYPE (class_decl);
   tree parm = NULL_TREE;
-  int flags = (get_access_flags_from_decl (class_decl) & ACC_PUBLIC ?
-              ACC_PUBLIC : 0);
+  /* Inherit access flags for the constructor from its enclosing class. */
+  int valid_ctor_flags = ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE;
+  int flags = (get_access_flags_from_decl (class_decl) & valid_ctor_flags);
   int i = 0, artificial = 0;
   tree decl, ctor_name;
   char buffer [80];
@@ -9961,7 +9965,7 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl,
 
              /* Check on accessibility here */
              if (not_accessible_p (current_class, field_decl,
-                                   DECL_CONTEXT (field_decl), from_super))
+                                   *type_found, from_super))
                return not_accessible_field_error (qual_wfl,field_decl);    
              check_deprecation (qual_wfl, field_decl);
 
@@ -10047,10 +10051,13 @@ static int
 not_accessible_p (tree reference, tree member, tree where, int 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;
+  bool is_static = false;
+  if (TREE_CODE (member) == FIELD_DECL ||
+      TREE_CODE (member) == VAR_DECL)
+    is_static = FIELD_STATIC (member);
+  else
+    is_static = METHOD_STATIC (member);
 
   /* Access always granted for members declared public */
   if (access_flag & ACC_PUBLIC)
@@ -10069,26 +10076,34 @@ not_accessible_p (tree reference, tree member, tree where, int from_super)
       if (from_super)
        return 0;
 
-      /* If where is active, access was made through a
-        qualifier. Access is granted if the type of the qualifier is
-        or is a sublass of the type the access made from (6.6.2.1.)  */
-      if (where && !inherits_from_p (reference, where))
-       return 1;
-
-      /* Otherwise, access is granted if occurring from the class where
-        member is declared or a subclass of it. Find the right
-        context to perform the check */
-      if (PURE_INNER_CLASS_TYPE_P (reference))
+      /* If WHERE is active, access was made through a qualifier. For 
+         non-static members, access is granted if the type of the qualifier 
+        is or is a sublass of the type the access is made from (6.6.2.1.)  */
+      if (where && !is_static)
         {
-          while (INNER_CLASS_TYPE_P (reference))
+         while (reference)
             {
-              if (inherits_from_p (reference, DECL_CONTEXT (member)))
-                return 0;
-              reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
-            }
+             if (inherits_from_p (where, reference))
+               return 0;
+             if (PURE_INNER_CLASS_TYPE_P (reference))
+               reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+             else
+               break;
+           }
+         return 1;
+       }
+
+      /* Otherwise, access is granted if occurring from within the class
+         where member is declared, or a subclass of it.  */
+      while (reference)
+        {
+          if (inherits_from_p (reference, DECL_CONTEXT (member)))
+            return 0;
+         if (PURE_INNER_CLASS_TYPE_P (reference))
+            reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+         else
+           break;
         }
-      if (inherits_from_p (reference, DECL_CONTEXT (member)))
-       return 0;
       return 1;
     }
 
@@ -10097,9 +10112,8 @@ not_accessible_p (tree reference, tree member, tree where, int from_super)
      it for innerclasses too. */
   if (access_flag & ACC_PRIVATE)
     {
-      if (reference == DECL_CONTEXT (member))
-       return 0;
-      if (enclosing_context_p (reference, DECL_CONTEXT (member)))
+      if (reference == DECL_CONTEXT (member) ||
+          common_enclosing_context_p (DECL_CONTEXT (member), reference))
        return 0;
       return 1;
     }
@@ -10506,8 +10520,6 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
        IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
       const char *const what = (DECL_CONSTRUCTOR_P (list)
                                ? "constructor" : "method");
-      /* FIXME: WFL yields the wrong message here but I don't know
-        what else to use.  */
       parse_error_context (wfl,
                           "Can't access %s %s `%s.%s' from `%s'",
                           access, what, klass, fct_name, refklass);
@@ -12343,6 +12355,10 @@ build_super_invocation (tree mdecl)
   else
     {
       tree super_wfl = build_wfl_node (super_identifier_node);
+      /* This is called after parsing is done, so the parser context
+         won't be accurate. Set location info from current_class decl. */
+      tree class_wfl = lookup_cl (TYPE_NAME (current_class));
+      EXPR_WFL_LINECOL (super_wfl) = EXPR_WFL_LINECOL (class_wfl);
       tree a = NULL_TREE, t;
       /* If we're dealing with an anonymous class, pass the arguments
          of the crafted constructor along. */
@@ -13922,7 +13938,7 @@ build_incomplete_class_ref (int location, tree class_name)
          /* We want the generated inner class inside the outermost class. */
          GET_CPC_LIST() = cpc;
          t = build_wfl_node (DECL_NAME (TYPE_NAME (object_type_node)));
-         inner = create_anonymous_class (0, t);
+         inner = create_anonymous_class (t);
          target_class = TREE_TYPE (inner);
          end_class_declaration (1);
          GET_CPC_LIST() = cpc_list;