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


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

patch to suppress build_class_init for compile-time-constant


I was getting error messages when compiling a switch statement whose
cases for final static constant fields.  The compiler was failing to
recognize these as constants because it had already wrapped them in
build_class_init.  This should not be done if a static field is final
*and* it is initialized by a compile-time constant.  (I also fixed
some places that checked for a static final field - but did not check
that it was being initialized by a compile-time-constant.)

Any objections before I check this in?  I am a little surprised why I
ran into this - I would have assumed it would have been caught
earlier.  (However, not the bug would only be triggered by code that
references constants from some *other* class.)

Note this is also a performance improvement, as well as a subtle
correctness fix, since the code no longer emits incorrect code to
initialize the class. 

2001-04-01  Per Bothner  <per@bothner.com>

	* java-tree.h (CONSTANT_VALUE_P):  New macro.
	* jcf-write.c (generate_classfile):  Use CONSTANT_VALUE_P.
	* parse.y (maybe_build_class_init_for_field):  New static function.
	(resolve_expression_name, resolve_field_access):  Use
	maybe_build_class_init_for_field instead of build_class_init 
	This does not do the init if the field is compile-time-constant.
	(resolve_field_access):  Simplify.

	* parse.y (fold_constant_for_init):  Merge test into switch.

Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.97.2.6
diff -u -p -r1.97.2.6 java-tree.h
--- java-tree.h	2001/03/24 01:16:02	1.97.2.6
+++ java-tree.h	2001/04/01 22:02:24
@@ -827,6 +827,13 @@ struct lang_identifier
 	   ggc_alloc_cleared (sizeof (struct lang_decl_var)));	\
     }
 
+/* A ConstantExpression, after folding and name resolution. */
+#define CONSTANT_VALUE_P(NODE) \
+  (TREE_CODE (NODE) == STRING_CST \
+   || (TREE_CODE (NODE) == INTEGER_CST \
+       && TREE_CODE (TREE_TYPE (NODE)) != POINTER_TYPE) \
+   || TREE_CODE (NODE) == REAL_CST)
+
 /* For a local VAR_DECL, holds the index into a words bitstring that
    specifies if this decl is definitively assigned.
    A DECL_BIT_INDEX of -1 means we no longer care. */
Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.72.2.3
diff -u -p -r1.72.2.3 jcf-write.c
--- jcf-write.c	2001/03/24 01:16:02	1.72.2.3
+++ jcf-write.c	2001/04/01 22:02:26
@@ -2888,11 +2888,7 @@ generate_classfile (clas, state)
 			      build_java_signature (TREE_TYPE (part)));
       PUT2(i);
       have_value = DECL_INITIAL (part) != NULL_TREE 
-	&& FIELD_STATIC (part)
-	&& (TREE_CODE (DECL_INITIAL (part)) == STRING_CST
-	    || (TREE_CODE (DECL_INITIAL (part)) == INTEGER_CST
-		&& TREE_CODE (TREE_TYPE (DECL_INITIAL (part))) != POINTER_TYPE)
-	    || TREE_CODE (DECL_INITIAL (part)) == REAL_CST);
+	&& FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part));
       if (have_value)
 	attr_count++;
 
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.251.2.12
diff -u -p -r1.251.2.12 parse.y
--- parse.y	2001/03/28 19:20:29	1.251.2.12
+++ parse.y	2001/04/01 22:02:35
@@ -329,6 +329,7 @@ static tree build_dot_class_method PARAM
 static tree build_dot_class_method_invocation PARAMS ((tree));
 static void create_new_parser_context PARAMS ((int));
 static void mark_parser_ctxt PARAMS ((void *));
+static tree maybe_build_class_init_for_field PARAMS ((tree, tree));
 
 /* Number of error found so far. */
 int java_error_count; 
@@ -8869,8 +8870,8 @@ resolve_expression_name (id, orig)
 	      /* Otherwise build what it takes to access the field */
 	      access = build_field_ref ((fs ? NULL_TREE : current_this),
 					DECL_CONTEXT (decl), name);
-	      if (fs && !flag_emit_class_files && !flag_emit_xref)
-		access = build_class_init (DECL_CONTEXT (access), access);
+	      if (fs)
+		access = maybe_build_class_init_for_field (decl, access);
 	      /* We may be asked to save the real field access node */
 	      if (orig)
 		*orig = access;
@@ -8954,29 +8955,16 @@ resolve_field_access (qual_wfl, field_de
     field_ref = decl;
   else if (JDECL_P (decl))
     {
-      int static_final_found = 0;
       if (!type_found)
 	type_found = DECL_CONTEXT (decl);
-      is_static = JDECL_P (decl) && FIELD_STATIC (decl);
-      if (CLASS_FINAL_VARIABLE_P (decl)
-	  && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
-	  && DECL_INITIAL (decl))
-	{
-	  /* When called on a FIELD_DECL of the right (primitive)
-	     type, java_complete_tree will try to substitue the decl
-	     for it's initial value. */
-	  field_ref = java_complete_tree (decl);
-	  static_final_found = 1;
-	}
-      else
-	field_ref = build_field_ref ((is_static && !flag_emit_xref? 
-				      NULL_TREE : where_found), 
-				     type_found, DECL_NAME (decl));
+      is_static = FIELD_STATIC (decl);
+      field_ref = build_field_ref ((is_static && !flag_emit_xref? 
+				    NULL_TREE : where_found), 
+				   type_found, DECL_NAME (decl));
       if (field_ref == error_mark_node)
 	return error_mark_node;
-      if (is_static && !static_final_found 
-	  && !flag_emit_class_files && !flag_emit_xref)
-	field_ref = build_class_init (DECL_CONTEXT (decl), field_ref);
+      if (is_static)
+	field_ref = maybe_build_class_init_for_field (decl, field_ref);
     }
   else
     field_ref = decl;
@@ -15508,6 +15496,29 @@ patch_conditional_expr (node, wfl_cond, 
   return node;
 }
 
+/* Wrap EXPR with code to initialize DECL's class, if appropriate. */
+
+static tree
+maybe_build_class_init_for_field (decl, expr)
+    tree decl, expr;
+{
+  tree clas = DECL_CONTEXT (decl);
+  if (flag_emit_class_files || flag_emit_xref)
+    return expr;
+
+  if (TREE_CODE (decl) == VAR_DECL && FIELD_STATIC (decl)
+      && FIELD_FINAL (decl))
+    {
+      tree init = DECL_INITIAL (decl);
+      if (init != NULL_TREE)
+	init = fold_constant_for_init (init, decl);
+      if (init != NULL_TREE && CONSTANT_VALUE_P (init))
+	return expr;
+    }
+
+  return build_class_init (clas, expr);
+}
+
 /* Try to constant fold NODE.
    If NODE is not a constant expression, return NULL_EXPR.
    CONTEXT is a static final VAR_DECL whose initializer we are folding. */
@@ -15520,11 +15531,13 @@ fold_constant_for_init (node, context)
   tree op0, op1, val;
   enum tree_code code = TREE_CODE (node);
 
-  if (code == STRING_CST || code == INTEGER_CST || code == REAL_CST)
-    return node;
-
   switch (code)
     {
+    case STRING_CST:
+    case INTEGER_CST:
+    case REAL_CST:
+      return node;
+
     case PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR:

-- 
	--Per Bothner
per@bothner.com   http://www.bothner.com/~per/


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