This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Java: miscellaneous fixes.


I'm checking in the following patch to fix:

  - A bug in the code reading UTF-8 strings from bytecode,
  - A bug in the bytecode generator when emitting `invokeinterface.'
  - Several front-end problems: error resilience, method checking,
    EH checks, declaration of field with innerclass array type, class name
    clashes and local finals.

./A

2000-08-10  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* class.c (maybe_layout_super_class): Fixed indentation.
	* java-tree.h (CLASS_METHOD_CHECKED_P): New macro.
	(java_check_methods): New function declaration.
	* jcf-parse.c (get_constant): Let `char_len' go up to 3. Use `str'
	instead of `str_ptr'.
	* jcf-write.c (generate_bytecode_insns): Emit number the of args
	of a `invokeinterface' at the right time.
	* parse.h (WFL_STRIP_BRACKET): New macro.
	(SET_TYPE_FOR_RESOLUTION): Use it.
	* parse.y (build_unresolved_array_type): Reuse `type_or_wfl.'
	(check_class_interface_creation): Don't check for cross package
	innerclass name clashes.
	(method_header): Behave properly if MDECL is `error_mark_node.'
	(method_declarator): Return `error_mark_node' if bogus current
	class.
	(resolve_class): Apply WFL_STRIP_BRACKET on `cl' if necessary.
	(resolve_and_layout): New local `decl_type', set and used. Call
	java_check_methods.
	(java_check_methods): New method.
	(java_layout_classes): Use it.
	(resolve_qualified_expression_name): No EH check necessary in
	access$<n>.
	(java_complete_lhs): Use VAR_DECL's DECL_INITIAL when evaluating
	`case' statement.
	(patch_assignment): Set DECL_INITIAL on integral final local.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/class.c,v
retrieving revision 1.73
diff -u -p -r1.73 class.c
--- class.c	2000/08/02 17:01:13	1.73
+++ class.c	2000/08/11 21:31:47
@@ -1748,8 +1748,7 @@ maybe_layout_super_class (super_class, t
 {
   if (TREE_CODE (super_class) == RECORD_TYPE)
     {
-      if (!CLASS_LOADED_P (super_class) 
-	  && CLASS_FROM_SOURCE_P (super_class))
+      if (!CLASS_LOADED_P (super_class) && CLASS_FROM_SOURCE_P (super_class))
 	safe_layout_class (super_class);
       if (!CLASS_LOADED_P (super_class))
 	load_class (super_class, 1);
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.h,v
retrieving revision 1.76
diff -u -p -r1.76 java-tree.h
--- java-tree.h	2000/07/21 00:01:43	1.76
+++ java-tree.h	2000/08/11 21:31:51
@@ -52,6 +52,7 @@ struct JCF;
       QUALIFIED_P (in IDENTIFIER_NODE)
       PRIMARY_P (in EXPR_WITH_FILE_LOCATION)
       MODIFY_EXPR_FROM_INITIALIZATION_P (in MODIFY_EXPR)
+      CLASS_METHOD_CHECKED_P (in RECORD_TYPE) 
    3: IS_AN_IMPORT_ON_DEMAND_P (in IDENTIFIER_NODE)
       RESOLVE_PACKAGE_NAME_P (in EXPR_WITH_FILE_LOCATION)
       SWITCH_HAS_DEFAULT (in SWITCH_EXPR)
@@ -788,6 +789,7 @@ extern tree get_boehm_type_descriptor PA
 extern unsigned long java_hash_hash_tree_node PARAMS ((hash_table_key));
 extern boolean java_hash_compare_tree_node PARAMS ((hash_table_key, 
 						    hash_table_key));
+extern void java_check_methods PARAMS ((tree));
 
 /* We use ARGS_SIZE_RTX to indicate that gcc/expr.h has been included
    to declare `enum expand_modifier'. */
@@ -998,6 +1000,8 @@ extern tree *type_map;
 /* True if EXPR (a MODIFY_EXPR in that case) is the result of variable
    initialization during its declaration */
 #define MODIFY_EXPR_FROM_INITIALIZATION_P(EXPR) TREE_LANG_FLAG_2 (EXPR)
+
+#define CLASS_METHOD_CHECKED_P(EXPR) TREE_LANG_FLAG_2 (EXPR)
 
 /* True if EXPR (a WFL in that case) resolves into an expression name */
 #define RESOLVE_EXPRESSION_NAME_P(WFL) TREE_LANG_FLAG_0 (WFL)
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-parse.c,v
retrieving revision 1.50
diff -u -p -r1.50 jcf-parse.c
--- jcf-parse.c	2000/07/27 11:13:51	1.50
+++ jcf-parse.c	2000/08/11 21:31:53
@@ -341,8 +341,8 @@ get_constant (jcf, index)
 	for (str_len = 0; i > 0; str_len++)
 	  {
 	    int char_len = UT8_CHAR_LENGTH (*str);
-	    if (char_len < 0 || char_len > 2 || char_len > i)
-	      fatal ("bad string constant");
+	    if (char_len < 0 || char_len > 3 || char_len > i)
+ 	      fatal ("bad string constant");
 	    str += char_len;
 	    i -= char_len;
 	  }
@@ -368,7 +368,7 @@ get_constant (jcf, index)
 		char_value = (char_value << 6) | (*str++ & 0x3F);
 		break;
 	      case 3:
-		char_value = *str_ptr++ & 0x0F;
+		char_value = *str++ & 0x0F;
 		char_value = (char_value << 6) | (*str++ & 0x3F);
 		char_value = (char_value << 6) | (*str++ & 0x3F);
 		break;
Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-write.c,v
retrieving revision 1.65
diff -u -p -r1.65 jcf-write.c
--- jcf-write.c	2000/07/13 19:23:57	1.65
+++ jcf-write.c	2000/08/11 21:32:00
@@ -2561,9 +2561,13 @@ generate_bytecode_insns (exp, target, st
 		  TREE_TYPE (TREE_TYPE (TREE_VALUE (TREE_OPERAND (exp, 1))));
 	      }
 	    index = find_methodref_index (&state->cpool, f);
-	    if (interface)
-	      DECL_CONTEXT (f) = saved_context;
 	    OP2 (index);
+	    if (interface)
+	      {
+		DECL_CONTEXT (f) = saved_context;
+		OP1 (nargs);
+		OP1 (0);
+	      }
 	    f = TREE_TYPE (TREE_TYPE (f));
 	    if (TREE_CODE (f) != VOID_TYPE)
 	      {
@@ -2572,11 +2576,6 @@ generate_bytecode_insns (exp, target, st
 		  emit_pop (size, state);
 		else
 		  NOTE_PUSH (size);
-	      }
-	    if (interface)
-	      {
-		OP1 (nargs);
-		OP1 (0);
 	      }
 	    break;
 	  }
Index: parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.56
diff -u -p -r1.56 parse.h
--- parse.h	2000/07/21 18:11:52	1.56
+++ parse.h	2000/08/11 21:32:03
@@ -535,27 +535,50 @@ typedef struct _jdeplist {
    java.lang.Object.  */
 #define SET_TYPE_FOR_RESOLUTION(TYPE, SAVE, CHAIN)			\
   {									\
-    tree returned_type;							\
+    tree _returned_type;						\
     (CHAIN) = 0;							\
     if (TREE_TYPE (GET_CPC ()) == object_type_node			\
-	&& TREE_CODE (TYPE) == EXPR_WITH_FILE_LOCATION 			\
+	&& TREE_CODE (TYPE) == EXPR_WITH_FILE_LOCATION			\
 	&& EXPR_WFL_NODE (TYPE) == unqualified_object_id_node)		\
       (TYPE) = object_type_node;					\
     else								\
       {									\
-	if (unresolved_type_p (type, &returned_type))			\
+	if (unresolved_type_p (type, &_returned_type))			\
 	  {								\
-	    if (returned_type)						\
-	      (TYPE) = returned_type;					\
+	    if (_returned_type)						\
+	      (TYPE) = _returned_type;					\
 	    else							\
 	      {								\
-		(SAVE) = (TYPE);					\
+	        tree _type;						\
+                WFL_STRIP_BRACKET (_type, TYPE);			\
+		(SAVE) = (_type);					\
 		(TYPE) = obtain_incomplete_type (TYPE);			\
 		CHAIN = 1;						\
 	      }								\
 	  }								\
       }									\
   }
+
+#define WFL_STRIP_BRACKET(TARGET, TYPE)					\
+{									\
+  tree __type = (TYPE);							\
+  if (TYPE && TREE_CODE (TYPE) == EXPR_WITH_FILE_LOCATION)		\
+    {									\
+      tree _node = EXPR_WFL_NODE (TYPE);				\
+      const char *_ptr = IDENTIFIER_POINTER (_node);			\
+      const char *_ref = _ptr;						\
+      while (_ptr[0] == '[')						\
+	  _ptr++;							\
+      if (_ref != _ptr)							\
+	{								\
+	  tree _new = copy_node (TYPE);					\
+	  EXPR_WFL_NODE (_new) = get_identifier (_ptr);			\
+	  __type = _new;						\
+	}								\
+    }									\
+  (TARGET) = __type;							\
+}
+
 /* Promote a type if it won't be registered as a patch */
 #define PROMOTE_RECORD_IF_COMPLETE(TYPE, IS_INCOMPLETE)		\
   {								\
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.199
diff -u -p -r1.199 parse.y
--- parse.y	2000/08/08 03:33:36	1.199
+++ parse.y	2000/08/11 21:32:37
@@ -3265,10 +3265,8 @@ build_unresolved_array_type (type_or_wfl
 		 IDENTIFIER_POINTER (EXPR_WFL_NODE (type_or_wfl)),
 		 IDENTIFIER_LENGTH (EXPR_WFL_NODE (type_or_wfl)));
   ptr = obstack_finish (&temporary_obstack);
-  return build_expr_wfl (get_identifier (ptr),
-			 EXPR_WFL_FILENAME (type_or_wfl),
-			 EXPR_WFL_LINENO (type_or_wfl),
-			 EXPR_WFL_COLNO (type_or_wfl));
+  EXPR_WFL_NODE (type_or_wfl) = get_identifier (ptr);
+  return type_or_wfl;
 }
 
 static void
@@ -3303,7 +3301,8 @@ check_class_interface_creation (is_inter
        - Can't be imported by a single type import
        - Can't already exists in the package */
   if (IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (raw_name)
-      && (node = find_name_in_single_imports (raw_name)))
+      && (node = find_name_in_single_imports (raw_name))
+      && !CPC_INNER_P ())
     {
       parse_error_context 
 	(cl, "%s name `%s' clashes with imported type `%s'",
@@ -4260,14 +4259,18 @@ method_header (flags, type, mdecl, throw
      int flags;
      tree type, mdecl, throws;
 {
-  tree meth = TREE_VALUE (mdecl);
-  tree id = TREE_PURPOSE (mdecl);
   tree type_wfl = NULL_TREE;
   tree meth_name = NULL_TREE;
   tree current, orig_arg, this_class = NULL;
+  tree id, meth;
   int saved_lineno;
   int constructor_ok = 0, must_chain;
   int count;
+
+  if (mdecl == error_mark_node)
+    return error_mark_node;
+  meth = TREE_VALUE (mdecl);
+  id = TREE_PURPOSE (mdecl);
   
   check_modifiers_consistency (flags);
 
@@ -4665,6 +4668,9 @@ method_declarator (id, list)
 
   patch_stage = JDEP_NO_PATCH;
 
+  if (GET_CPC () == error_mark_node)
+    return error_mark_node;
+
   /* If we're dealing with an inner class constructor, we hide the
      this$<n> decl in the name field of its parameter declaration.  We
      also might have to hide the outer context local alias
@@ -5391,7 +5397,10 @@ resolve_class (enclosing, class_type, de
   while (name[0] == '[')
     name++;
   if (base != name)
-    TYPE_NAME (class_type) = get_identifier (name);
+    {
+      TYPE_NAME (class_type) = get_identifier (name);
+      WFL_STRIP_BRACKET (cl, cl);
+    }
 
   /* 2- Resolve the bare type */
   if (!(resolved_type_decl = do_resolve_class (enclosing, class_type, 
@@ -5562,7 +5571,7 @@ resolve_and_layout (something, cl)
      tree something;
      tree cl;
 {
-  tree decl;
+  tree decl, decl_type;
 
   /* Don't do that on the current class */
   if (something == current_class)
@@ -5605,13 +5614,14 @@ resolve_and_layout (something, cl)
     return NULL_TREE;
 
   /* Resolve and layout if necessary */
-  layout_class_methods (TREE_TYPE (decl));
-  /* Check methods, but only once */
-  if (CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) 
-      && !CLASS_LOADED_P (TREE_TYPE (decl)))
-    CHECK_METHODS (decl);
-  if (TREE_TYPE (decl) != current_class && !CLASS_LOADED_P (TREE_TYPE (decl)))
-    safe_layout_class (TREE_TYPE (decl));
+  decl_type = TREE_TYPE (decl);
+  layout_class_methods (decl_type);
+  /* Check methods */
+  if (CLASS_FROM_SOURCE_P (decl_type))
+    java_check_methods (decl);
+  /* Layout the type if necessary */ 
+  if (decl_type != current_class && !CLASS_LOADED_P (decl_type))
+    safe_layout_class (decl_type);
 
   return decl;
 }
@@ -5957,6 +5967,23 @@ check_method_types_complete (decl)
   return 1;
 }
 
+/* Visible interface to check methods contained in CLASS_DECL */
+
+void
+java_check_methods (class_decl)
+     tree class_decl;
+{
+  if (CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)))
+    return;
+
+  if (CLASS_INTERFACE (class_decl))
+    java_check_abstract_methods (class_decl);
+  else
+    java_check_regular_methods (class_decl);
+  
+  CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)) = 1;
+}
+
 /* Check all the methods of CLASS_DECL. Methods are first completed
    then checked according to regular method existance rules.  If no
    constructor for CLASS_DECL were encountered, then build its
@@ -7288,7 +7315,7 @@ java_layout_classes ()
   /* Then check the methods of all parsed classes */
   for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
     if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
-      CHECK_METHODS (TREE_VALUE (current));
+      java_check_methods (TREE_VALUE (current));
   java_parse_abort_on_error ();
 
   for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
@@ -8951,8 +8978,10 @@ resolve_qualified_expression_name (wfl, 
 	     instantiation using a primary qualified by a `new' */
 	  RESTORE_THIS_AND_CURRENT_CLASS;
 
-	  /* EH check */
-	  if (location)
+	  /* EH check. No check on access$<n> functions */
+	  if (location 
+	      && !OUTER_FIELD_ACCESS_IDENTIFIER_P 
+	            (DECL_NAME (current_function_decl)))
 	    check_thrown_exceptions (location, ret_decl);
 
 	  /* If the previous call was static and this one is too,
@@ -10988,6 +11017,8 @@ java_complete_lhs (node)
       /* Multiple instance of a case label bearing the same
 	 value is checked during code generation. The case
 	 expression is allright so far. */
+      if (TREE_CODE (cn) == VAR_DECL)
+	cn = DECL_INITIAL (cn);
       TREE_OPERAND (node, 0) = cn;
       TREE_TYPE (node) = void_type_node;
       CAN_COMPLETE_NORMALLY (node) = 1;
@@ -12035,6 +12066,19 @@ patch_assignment (node, wfl_op1, wfl_op2
 	  else
 	    lvalue = build (COMPOUND_EXPR, lhs_type, check, lvalue);
 	}
+    }
+
+  /* Final locals can be used as case values in switch
+     statement. Prepare them for this eventuality. */
+  if (TREE_CODE (lvalue) == VAR_DECL 
+      && LOCAL_FINAL (lvalue)
+      && TREE_CONSTANT (new_rhs)
+      && IDENTIFIER_LOCAL_VALUE (DECL_NAME (lvalue))
+      && JINTEGRAL_TYPE_P (TREE_TYPE (lvalue))
+      )
+    {
+      TREE_CONSTANT (lvalue) = 1;
+      DECL_INITIAL (lvalue) = new_rhs;
     }
 
   TREE_OPERAND (node, 0) = lvalue;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]