parse.y (<type_declaration>): Do maybe_generate_clinit last.
authorAlexandre Petit-Bianco <apbianco@sendai.cygnus.com>
Sat, 12 Dec 1998 20:04:35 +0000 (12:04 -0800)
committerPer Bothner <bothner@gcc.gnu.org>
Sat, 12 Dec 1998 20:04:35 +0000 (12:04 -0800)

* parse.y (<type_declaration>):  Do maybe_generate_clinit last.
(register_fields):  If a static fields has an initializer, just
chain it on ctxp->static_initialized, and handle later.
(java_complete_expand_methods):  Force <clinit> first.
(resolve_expression_name, resolve_field_access):  Just get DECL_INITIAL
- it's already been completed.
(patch_initialized_static_field):  New function.
(java_complete_field):  Call it.

From-SVN: r24274

gcc/java/parse.y

index 1e0f0f4d938ea9de79f5e8e0d857c7a34204269e..5bc2b6e1ec65c9b2a311758286fd975300258cdb 100644 (file)
@@ -237,6 +237,7 @@ static tree patch_new_array_init PROTO ((tree, tree));
 static tree maybe_build_array_element_wfl PROTO ((tree));
 static int array_constructor_check_entry PROTO ((tree, tree));
 static char *purify_type_name PROTO ((char *));
+static tree patch_initialized_static_field PROTO ((tree));
 
 /* Number of error found so far. */
 int java_error_count; 
@@ -609,8 +610,8 @@ type_import_on_demand_declaration:
 type_declaration:
        class_declaration
                {
-                 maybe_generate_clinit ();
                  maybe_generate_finit ();
+                 maybe_generate_clinit ();
                  $$ = $1;
                }
 |      interface_declaration
@@ -3133,34 +3134,24 @@ register_fields (flags, type, variable_list)
          /* The field is declared static */
          if (flags & ACC_STATIC)
            {
-             if (flags & ACC_FINAL)
-               {
-                 if (DECL_LANG_SPECIFIC (field_decl) == NULL)
-                   DECL_LANG_SPECIFIC (field_decl) = (struct lang_decl *)
-                     permalloc (sizeof (struct lang_decl_var));
-                 DECL_LOCAL_STATIC_VALUE (field_decl) = 
-                   TREE_OPERAND (init, 1);
-                 if (TREE_CONSTANT (TREE_OPERAND (init, 1)))
-                   DECL_INITIAL (field_decl) = TREE_OPERAND (init, 1);
-               }
-             /* Otherwise, the field should be initialized in <clinit>. 
-                This field is remembered so we can generate <clinit> later */
-             else
-               {
-                 INITIALIZED_P (field_decl) = 1;
-                 TREE_CHAIN (init) = ctxp->static_initialized;
-                 ctxp->static_initialized = init;
-               }
+             /* We include the field and its initialization part into
+                a list used to generate <clinit>. After <clinit> is
+                walked, fields initialization will be processed and
+                fields initialized with know constants will be taken
+                out of <clinit> and have ther DECL_INITIAL set
+                appropriately. */
+             TREE_CHAIN (init) = ctxp->static_initialized;
+             ctxp->static_initialized = init;
            }
          /* A non-static field declared with an immediate initialization is
             to be initialized in <init>, if any.  This field is remembered
             to be processed at the time of the generation of <init>. */
          else
            {
-             INITIALIZED_P (field_decl) = 1;
              TREE_CHAIN (init) = ctxp->non_static_initialized;
              ctxp->non_static_initialized = init;
            }
+         INITIALIZED_P (field_decl) = 1;
        }
     }
   lineno = saved_lineno;
@@ -5582,6 +5573,16 @@ java_complete_expand_methods ()
       /* Initialize a new constant pool */
       init_outgoing_cpool ();
 
+      /* We want <clinit> (if any) to be processed first. */
+      decl = tree_last (TYPE_METHODS (class_type));
+      if (decl && DECL_NAME (decl) == clinit_identifier_node)
+       {
+         tree list = nreverse (TYPE_METHODS (class_type));
+         list = TREE_CHAIN (list);
+         TREE_CHAIN (decl) = NULL_TREE;
+         TYPE_METHODS (class_type) = chainon (decl, nreverse (list));
+       }
+
       /* Don't process function bodies in interfaces */
       if (!CLASS_INTERFACE (TYPE_NAME (current_class)))
        for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
@@ -5659,7 +5660,7 @@ java_complete_expand_method (mdecl)
       if ((block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body))
          && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE)
        missing_return_error (current_function_decl);
-      
+
       /* Don't go any further if we've found error(s) during the
          expansion */
       if (!java_error_count)
@@ -5975,8 +5976,8 @@ resolve_expression_name (id, orig)
                  return error_mark_node;
                }
              /* The field is final. We may use its value instead */
-             if (fs && FIELD_FINAL (decl))
-               value = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl));
+             if (fs && FIELD_FINAL (decl) && DECL_INITIAL (decl))
+               value = DECL_INITIAL (decl);
 
              /* Otherwise build what it takes to access the field */
              decl = build_field_ref ((fs ? NULL_TREE : current_this),
@@ -6049,9 +6050,9 @@ resolve_field_access (qual_wfl, field_decl, field_type)
       if (FIELD_FINAL (decl) 
          && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
          && DECL_LANG_SPECIFIC (decl)
-         && DECL_LOCAL_STATIC_VALUE (decl))
+         && DECL_INITIAL (decl))
        {
-         field_ref = java_complete_tree (DECL_LOCAL_STATIC_VALUE (decl));
+         field_ref = DECL_INITIAL (decl);
          static_final_found = 1;
        }
       else
@@ -7765,6 +7766,15 @@ java_complete_tree (node)
        TREE_OPERAND (node, 1) = nn;
       node = patch_assignment (node, wfl_op1, wfl_op2);
       CAN_COMPLETE_NORMALLY (node) = 1;
+
+      /* Before returning the node, in the context of a static field
+         assignment in <clinit>, we may want to carray further
+         optimizations. (VAR_DECL means it's a static field. See
+         add_field. */
+      if (DECL_NAME (current_function_decl) == clinit_identifier_node
+         && TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL)
+       node = patch_initialized_static_field (node);
+
       return node;
 
     case MULT_EXPR:
@@ -8161,7 +8171,8 @@ static int
 check_final_assignment (lvalue, wfl)
      tree lvalue, wfl;
 {
-  if (DECL_P (lvalue) && FIELD_FINAL (lvalue))
+  if (DECL_P (lvalue) && FIELD_FINAL (lvalue) &&
+      DECL_NAME (current_function_decl) != clinit_identifier_node)
     {
       parse_error_context 
         (wfl, "Can't assign a value to the final variable `%s'",
@@ -8323,6 +8334,30 @@ patch_assignment (node, wfl_op1, wfl_op2)
   return node;
 }
 
+/* Optimize static (final) field initialized upon declaration.
+     - If the field is static final and is assigned to a primitive
+       constant type, then set its DECL_INITIAL to the value.
+     - More to come.  */
+
+static tree
+patch_initialized_static_field (node)
+     tree node;
+{
+  tree field = TREE_OPERAND (node, 0);
+  tree value = TREE_OPERAND (node, 1);
+
+  if (FIELD_FINAL (field) && TREE_CONSTANT (value)
+      && JPRIMITIVE_TYPE_P (TREE_TYPE (value)))
+    {
+      if (DECL_LANG_SPECIFIC (field) == NULL)
+       DECL_LANG_SPECIFIC (field) = (struct lang_decl *)
+         permalloc (sizeof (struct lang_decl_var));
+      DECL_INITIAL (field) = value;
+      return empty_stmt_node;
+    }
+  return node;
+}
+
 /* Check that type SOURCE can be cast into type DEST. If the cast
    can't occur at all, return 0 otherwise 1. This function is used to
    produce accurate error messages on the reasons why an assignment
@@ -9392,7 +9427,7 @@ patch_unaryop (node, wfl_op)
   /* There are cases where node has been replaced by something else
      and we don't end up returning here: UNARY_PLUS_EXPR,
      CONVERT_EXPR, {POST,PRE}{INCR,DECR}EMENT_EXPR. */
-  TREE_OPERAND (node, 0) = op;
+  TREE_OPERAND (node, 0) = fold (op);
   TREE_TYPE (node) = prom_type;
   return fold (node);
 }
@@ -10547,7 +10582,7 @@ patch_try_statement (node)
           CATCH_EXPR           (catch node)
             BLOCK              (with the decl of the parameter)
                COMPOUND_EXPR
-                 MODIFIY_EXPR   (assignemnt of the catch parameter)
+                 MODIFY_EXPR   (assignment of the catch parameter)
                 BLOCK          (catch clause block)
            LABEL_DECL          (where to return after finally (if any))