public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Patch: Java: Fix PR 8618
@ 2004-07-10  7:23 Bryce McKinlay
  2004-07-10  7:51 ` Per Bothner
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Bryce McKinlay @ 2004-07-10  7:23 UTC (permalink / raw)
  To: java-patches, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1015 bytes --]

This patch fixes several problems with access checks on private, 
package-private, and protected members, particularly from inner classes:

- The not_accessible_p() function was set up to always allow access to 
anything from an inner class.
- Implicit constructor bodies were not created with the correct line 
number info, resulting in the wrong bit of code being printed on error 
messages.
- Implicit constructors should inherit access flags from their enclosing 
type.
- resolve_qualified_expression_name was passing the wrong "where" 
argument to not_accessible_p. This parameter should be the type of the 
qualifier, not the type in which the target member was found.

The patch fixes PR java/8618 and gives 21 Jacks XPASSes. I have 1 Jacks 
regression (8.1.2-runtime-1), however this existed before my patch - see 
PR 16327. That test also fails on gcj 3.3, so I'm not sure why the 
failure only recently started showing up in Jacks.

I've build most of RHUG with this patch applied.

OK to commit?

Bryce


[-- Attachment #2: gcj-access-check.patch --]
[-- Type: text/x-patch, Size: 12607 bytes --]

2004-07-09  Bryce McKinlay  <mckinlay@redhat.com>

	PR java/8618, PR java/9369
	* 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.

Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.196
diff -u -r1.196 class.c
--- class.c	9 Jul 2004 23:26:01 -0000	1.196
+++ class.c	10 Jul 2004 02:56:00 -0000
@@ -587,12 +587,34 @@
   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: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.209
diff -u -r1.209 java-tree.h
--- java-tree.h	9 Jul 2004 18:36:02 -0000	1.209
+++ java-tree.h	10 Jul 2004 02:56:00 -0000
@@ -1238,6 +1238,7 @@
 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: jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.150
diff -u -r1.150 jcf-write.c
--- jcf-write.c	7 Jul 2004 10:21:01 -0000	1.150
+++ jcf-write.c	10 Jul 2004 02:56:01 -0000
@@ -2903,6 +2903,22 @@
   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 @@
 
       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: parse.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.h,v
retrieving revision 1.97
diff -u -r1.97 parse.h
--- parse.h	21 Jun 2004 12:37:46 -0000	1.97
+++ parse.h	10 Jul 2004 02:56:01 -0000
@@ -842,7 +842,7 @@
 	    != 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: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.490
diff -u -r1.490 parse.y
--- parse.y	7 Jul 2004 10:21:01 -0000	1.490
+++ parse.y	10 Jul 2004 02:56:04 -0000
@@ -320,7 +320,7 @@
 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 @@
 
 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 @@
 
 		}
 |	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 @@
     }
 }
 
+/* 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 @@
   /* 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 @@
 
   /* 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 @@
 {
   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 @@
 
 	      /* 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 @@
 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 @@
       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 @@
      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 @@
 	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 @@
   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 @@
 	  /* 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;

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2004-07-10 18:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-10  7:23 Patch: Java: Fix PR 8618 Bryce McKinlay
2004-07-10  7:51 ` Per Bothner
2004-07-10 12:53 ` Andreas Tobler
2004-07-10 13:21   ` Eric Botcazou
2004-07-10 18:28   ` Bryce McKinlay
2004-07-10 16:30 ` Andreas Schwab
2004-07-10 16:43   ` Andreas Tobler
2004-07-10 17:22     ` Bryce McKinlay
2004-07-10 22:55 ` Ranjit Mathew
2004-07-10 23:28 ` Graham Stott

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).