OSDN Git Service

* gimplify.c (gimplify_type_sizes) [POINTER_TYPE, REFERENCE_TYPE]:
[pf3gnuchains/gcc-fork.git] / gcc / java / check-init.c
index c4e3948..6eb1f16 100644 (file)
@@ -1,5 +1,6 @@
 /* Code to test for "definitive [un]assignment".
-   Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free Software Foundation,
+   Inc.
 
 This file is part of GCC.
 
@@ -15,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -36,7 +37,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 /* The basic idea is that we assign each local variable declaration
    and each blank final field an index, and then we pass around
    bitstrings, where the (2*i)'th bit is set if decl whose DECL_BIT_INDEX
-   is i is definitely assigned, and the the (2*i=1)'th bit is set if 
+   is i is definitely assigned, and the (2*i=1)'th bit is set if 
    decl whose DECL_BIT_INDEX is i is definitely unassigned */
 
 /* One segment of a bitstring. */
@@ -76,8 +77,6 @@ static int start_current_locals = 0;
 
 static int num_current_words;
 
-static tree wfl;
-
 #define COPYN(DST, SRC, NWORDS) memcpy (DST, SRC, NWORDS * sizeof(word))
 #define COPY(DST, SRC) COPYN (DST, SRC, num_current_words)
 
@@ -164,6 +163,11 @@ static void check_final_reassigned (tree, words);
 static tree
 get_variable_decl (tree exp)
 {
+  /* A static field can be wrapped in a COMPOUND_EXPR where the first
+     argument initializes the class.  */
+  if (TREE_CODE (exp) == COMPOUND_EXPR)
+    exp = extract_field_decl (exp);
+
   if (TREE_CODE (exp) == VAR_DECL)
     {
       if (! TREE_STATIC (exp) ||  FIELD_FINAL (exp))
@@ -191,15 +195,58 @@ get_variable_decl (tree exp)
            return op1;
        }
     }
+  else if (TREE_CODE (exp) == INDIRECT_REF)
+    {
+      /* For indirect dispatch, look for an expression of the form 
+      (indirect_ref (+ (array_ref otable <N>) this)).  
+      FIXME: it would probably be better to generate a JAVA_FIELD_REF
+      expression that gets converted to OTABLE access at
+      gimplification time.  */
+      exp = TREE_OPERAND (exp, 0);
+      if (TREE_CODE (exp) == PLUS_EXPR)
+       {
+         tree op0 = TREE_OPERAND (exp, 0);
+         STRIP_NOPS (op0);
+         if (TREE_CODE (op0) == ARRAY_REF)
+           {
+             tree table = TREE_OPERAND (op0, 0);
+             if (TREE_CODE (table) == VAR_DECL
+                 && DECL_LANG_SPECIFIC (table)
+                 && DECL_OWNER (table) 
+                 && TYPE_OTABLE_DECL (DECL_OWNER (table)) == table)
+               {
+                 HOST_WIDE_INT index 
+                   = TREE_INT_CST_LOW (TREE_OPERAND (op0, 1));
+                 tree otable_methods 
+                   = TYPE_OTABLE_METHODS (DECL_OWNER (table));
+                 tree element;
+                 for (element = otable_methods; 
+                      element; 
+                      element = TREE_CHAIN (element))
+                   {
+                     if (index == 1)
+                       {
+                         tree purpose = TREE_PURPOSE (element);
+                         if (TREE_CODE (purpose) == FIELD_DECL)
+                           return purpose;
+                         else
+                           return NULL_TREE;
+                       }
+                     --index;
+                   }
+               }
+           }
+       }
+    }
+
   return NULL_TREE;
 }
 
 static void
 final_assign_error (tree name)
 {
-  static const char format[]
-    = "can't reassign a value to the final variable '%s'";
-  parse_error_context (wfl, format, IDENTIFIER_POINTER (name));
+  error ("Can't reassign a value to the final variable %qs",
+        IDENTIFIER_POINTER (name));
 }
 
 static void
@@ -210,7 +257,8 @@ check_final_reassigned (tree decl, words before)
      assigned must be reported as errors */
   if (DECL_FINAL (decl) && index != -2
       && (index < loop_current_locals /* I.e. -1, or outside current loop. */
-         || ! UNASSIGNED_P (before, index)))
+          || (DECL_LOCAL_FINAL_IUD (decl) ? ASSIGNED_P (before, index)
+              : ! UNASSIGNED_P (before, index))))
     {
       final_assign_error (DECL_NAME (decl));
     }
@@ -337,27 +385,6 @@ check_bool_init (tree exp, words before, words when_false, words when_true)
     case TRUTH_NOT_EXPR:
       check_bool_init (TREE_OPERAND (exp, 0), before, when_true, when_false);
       return;
-    case MODIFY_EXPR:
-      {
-       tree tmp = TREE_OPERAND (exp, 0);
-       if ((tmp = get_variable_decl (tmp)) != NULL_TREE)
-         {
-           int index;
-           check_bool_init (TREE_OPERAND (exp, 1), before,
-                            when_false, when_true);
-           check_final_reassigned (tmp, before);
-           index = DECL_BIT_INDEX (tmp);
-           if (index >= 0)
-             {
-               SET_ASSIGNED (when_false, index);
-               SET_ASSIGNED (when_true, index);
-               CLEAR_UNASSIGNED (when_false, index);
-               CLEAR_UNASSIGNED (when_true, index);
-             }
-           break;
-         }
-      }
-      goto do_default;
 
     case BIT_AND_EXPR:
     case BIT_IOR_EXPR:
@@ -390,8 +417,8 @@ check_bool_init (tree exp, words before, words when_false, words when_true)
          COPY (when_true, before);
        }
       break;
+
     default:
-    do_default:
       check_init (exp, before);
       COPY (when_false, before);
       COPY (when_true, before);
@@ -471,7 +498,10 @@ static void
 check_init (tree exp, words before)
 {
   tree tmp;
+  location_t save_location = input_location;
  again:
+  if (EXPR_HAS_LOCATION (exp))
+    input_location = EXPR_LOCATION (exp);
   switch (TREE_CODE (exp))
     {
     case VAR_DECL:
@@ -485,10 +515,7 @@ check_init (tree exp, words before)
          if (! LOCAL_CLASS_INITIALIZATION_FLAG_P (exp)
              && index >= 0 && ! ASSIGNED_P (before, index))
            {
-             parse_error_context 
-               (wfl, "Variable `%s' may not have been initialized",
-                IDENTIFIER_POINTER (DECL_NAME (exp)));
-             /* Suppress further errors. */
+             error ("variable %qD may not have been initialized", exp);
              DECL_BIT_INDEX (exp) = -2;
            }
        }
@@ -501,9 +528,7 @@ check_init (tree exp, words before)
          int index = DECL_BIT_INDEX (tmp);
          if (index >= 0 && ! ASSIGNED_P (before, index))
            {
-             parse_error_context 
-               (wfl, "variable '%s' may not have been initialized",
-                IDENTIFIER_POINTER (DECL_NAME (tmp)));
+             error ("variable %qD may not have been initialized", tmp);
              /* Suppress further errors. */
              DECL_BIT_INDEX (tmp) = -2;
            }
@@ -531,6 +556,7 @@ check_init (tree exp, words before)
             definitely assigned when once we checked the whole
             function. */
          if (! STATIC_CLASS_INIT_OPT_P () /* FIXME */
+             && ! DECL_FINAL (tmp)
              && index >= start_current_locals
              && index == num_current_locals - 1)
            {
@@ -638,7 +664,7 @@ check_init (tree exp, words before)
        END_ALTERNATIVES (before, alt);
        loop_current_locals = save_loop_current_locals;
        start_current_locals = save_start_current_locals;
-       return;
+       break;
       }
     case EXIT_EXPR:
       {
@@ -646,14 +672,13 @@ check_init (tree exp, words before)
        DECLARE_BUFFERS(when_true, 2);
        words when_false = when_true + num_current_words;
 #ifdef ENABLE_JC1_CHECKING
-       if (TREE_CODE (alt->block) != LOOP_EXPR)
-         abort ();
+       gcc_assert (TREE_CODE (alt->block) == LOOP_EXPR);
 #endif
        check_bool_init (TREE_OPERAND (exp, 0), before, when_false, when_true);
        done_alternative (when_true, alt);
        COPY (before, when_false);
        RELEASE_BUFFERS(when_true);
-       return;
+       break;
       }
     case LABELED_BLOCK_EXPR:
       {
@@ -664,7 +689,7 @@ check_init (tree exp, words before)
          check_init (LABELED_BLOCK_BODY (exp), before);
        done_alternative (before, &alt);
        END_ALTERNATIVES (before, alt);
-       return;
+       break;
       }
     case EXIT_BLOCK_EXPR:
       {
@@ -674,7 +699,7 @@ check_init (tree exp, words before)
          alt = alt->outer;
        done_alternative (before, alt);
        SET_ALL (before);
-       return;
+       break;
       }
     case SWITCH_EXPR:
       {
@@ -691,7 +716,7 @@ check_init (tree exp, words before)
          done_alternative (alt.saved, &alt);
        FREE_BUFFER(alt.saved, buf);
        END_ALTERNATIVES (before, alt);
-       return;
+       break;
       }
     case CASE_EXPR:
     case DEFAULT_EXPR:
@@ -733,7 +758,7 @@ check_init (tree exp, words before)
          }
        END_ALTERNATIVES (before, alt);
       }
-    return;
+    break;
 
     case TRY_FINALLY_EXPR:
       {
@@ -744,7 +769,7 @@ check_init (tree exp, words before)
        UNION (before, before, tmp);
        RELEASE_BUFFERS(tmp);
       }
-      return;
+      break;
 
     case RETURN_EXPR:
     case THROW_EXPR:
@@ -755,7 +780,7 @@ check_init (tree exp, words before)
     case ERROR_MARK:
     never_continues:
       SET_ALL (before);
-      return;
+      break;
       
     case COND_EXPR:
     case TRUTH_ANDIF_EXPR:
@@ -770,7 +795,7 @@ check_init (tree exp, words before)
       break;
 
     case NOP_EXPR:
-      if (exp == empty_stmt_node)
+      if (IS_EMPTY_STMT (exp))
        break;
       /* ... else fall through ... */
     case UNARY_PLUS_EXPR:
@@ -781,6 +806,7 @@ check_init (tree exp, words before)
     case TRUTH_NOT_EXPR:
     case BIT_NOT_EXPR:
     case CONVERT_EXPR:
+    case VIEW_CONVERT_EXPR:
     case BIT_FIELD_REF:
     case FLOAT_EXPR:
     case FIX_TRUNC_EXPR:
@@ -802,7 +828,14 @@ check_init (tree exp, words before)
     case POSTINCREMENT_EXPR:
       tmp = get_variable_decl (TREE_OPERAND (exp, 0));
       if (tmp != NULL_TREE && DECL_FINAL (tmp))
-       final_assign_error (DECL_NAME (tmp));      
+       final_assign_error (DECL_NAME (tmp));
+      else if (TREE_CODE (tmp = TREE_OPERAND (exp, 0)) == COMPONENT_REF)
+        {
+          /* Take care of array length accesses too.  */
+          tree decl = TREE_OPERAND (tmp, 1);
+          if (DECL_FINAL (decl))
+            final_assign_error (DECL_NAME (decl));
+        }
 
       /* Avoid needless recursion.  */
       exp = TREE_OPERAND (exp, 0);
@@ -810,7 +843,7 @@ check_init (tree exp, words before)
 
     case SAVE_EXPR:
       if (IS_INIT_CHECKED (exp))
-       return;
+       break;
       IS_INIT_CHECKED (exp) = 1;
       exp = TREE_OPERAND (exp, 0);
       goto again;
@@ -846,6 +879,12 @@ check_init (tree exp, words before)
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
     case EXACT_DIV_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
     binop:
       check_init (TREE_OPERAND (exp, 0), before);
       /* Avoid needless recursion, especially for COMPOUND_EXPR. */
@@ -857,6 +896,7 @@ check_init (tree exp, words before)
     case INTEGER_CST:
     case REAL_CST:
     case STRING_CST:
+    case DECL_EXPR:
     case JAVA_EXC_OBJ_EXPR:
       break;
 
@@ -878,25 +918,28 @@ check_init (tree exp, words before)
 
     case NEW_ARRAY_INIT:
       {
-       tree x = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
-       for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
-         check_init (TREE_VALUE (x), before);
+       tree value;
+       unsigned HOST_WIDE_INT idx;
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
+                                   idx, value)
+         check_init (value, before);
       }
       break;
 
     case EXPR_WITH_FILE_LOCATION:
       {
        location_t saved_location = input_location;
-       tree saved_wfl = wfl;
        tree body = EXPR_WFL_NODE (exp);
-       if (body == empty_stmt_node)
+       if (IS_EMPTY_STMT (body))
          break;
-       wfl = exp;
+#ifdef USE_MAPPED_LOCATION
+       input_location = EXPR_LOCATION (exp);
+#else
        input_filename = EXPR_WFL_FILENAME (exp);
        input_line = EXPR_WFL_LINENO (exp);
+#endif
        check_init (body, before);
        input_location = saved_location;
-       wfl = saved_wfl;
       }
       break;
       
@@ -905,6 +948,7 @@ check_init (tree exp, words before)
        ("internal error in check-init: tree code not implemented: %s",
         tree_code_name [(int) TREE_CODE (exp)]);
     }
+  input_location = save_location;
 }
 
 void
@@ -974,7 +1018,7 @@ check_for_initialization (tree body, tree mdecl)
              if (index >= 0 && ! ASSIGNED_P (before, index))
                {
                  if (! is_finit_method)
-                   error ("%Jfinal field '%D' may not have been initialized",
+                   error ("%Jfinal field %qD may not have been initialized",
                            decl, decl);
                }
              else if (is_finit_method)