This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
patch to suppress build_class_init for compile-time-constant
- To: java-patches at gcc dot gnu dot org
- Subject: patch to suppress build_class_init for compile-time-constant
- From: Per Bothner <per at bothner dot com>
- Date: 01 Apr 2001 15:14:29 -0700
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/