re PR java/20056 ('verification failed: incompatible type on stack' with --indirect...
authorTom Tromey <tromey@redhat.com>
Tue, 22 Feb 2005 18:14:37 +0000 (18:14 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Tue, 22 Feb 2005 18:14:37 +0000 (18:14 +0000)
PR java/20056:
* verify-impl.c (EITHER): New define.
(types_compatible): Handle it.
(check_field_constant): Use it.

From-SVN: r95404

gcc/java/ChangeLog
gcc/java/verify-impl.c

index c1d48086be97c0f940cdea3ad5e7776ea696624e..54dc009a4b7626297a435c57afc6732173a2c8ea 100644 (file)
@@ -1,3 +1,10 @@
+2005-02-22  Tom Tromey  <tromey@redhat.com>
+
+       PR java/20056:
+       * verify-impl.c (EITHER): New define.
+       (types_compatible): Handle it.
+       (check_field_constant): Use it.
+
 2005-02-18  Tom Tromey  <tromey@redhat.com>
 
        PR java/20056:
index bd681d2bce06ac1e4bef8f0b8e868819e3792b2f..ae585c8d7dbc4382a8c7a7c705f71927839eb657 100644 (file)
@@ -539,16 +539,19 @@ struct type
   
      First, when constructing a new object, it is the PC of the
      `new' instruction which created the object.  We use the special
-     value UNINIT to mean that this is uninitialized, and the
-     special value SELF for the case where the current method is
-     itself the <init> method.
-
+     value UNINIT to mean that this is uninitialized.  The special
+     value SELF is used for the case where the current method is
+     itself the <init> method.  the special value EITHER is used
+     when we may optionally allow either an uninitialized or
+     initialized reference to match.
+  
      Second, when the key is return_address_type, this holds the PC
      of the instruction following the `jsr'.  */
   int pc;
 
-  #define UNINIT -2
-  #define SELF -1
+#define UNINIT -2
+#define SELF -1
+#define EITHER -3
 };
 
 #if 0
@@ -721,19 +724,33 @@ types_compatible (type *t, type *k)
   if (k->klass == NULL)
     verify_fail ("programmer error in type::compatible");
 
-  /* An initialized type and an uninitialized type are not
-     compatible.  */
-  if (type_initialized (t) != type_initialized (k))
-    return false;
-
-  /* Two uninitialized objects are compatible if either:
-     * The PCs are identical, or
-     * One PC is UNINIT.  */
-  if (type_initialized (t))
+  /* Handle the special 'EITHER' case, which is only used in a
+     special case of 'putfield'.  Note that we only need to handle
+     this on the LHS of a check.  */
+  if (! type_initialized (t) && t->pc == EITHER)
     {
-      if (t->pc != k->pc && t->pc != UNINIT && k->pc != UNINIT)
+      /* If the RHS is uninitialized, it must be an uninitialized
+        'this'.  */
+      if (! type_initialized (k) && k->pc != SELF)
        return false;
     }
+  else if (type_initialized (t) != type_initialized (k))
+    {
+      /* An initialized type and an uninitialized type are not
+        otherwise compatible.  */
+      return false;
+    }
+  else
+    {
+      /* Two uninitialized objects are compatible if either:
+       * The PCs are identical, or
+       * One PC is UNINIT.  */
+      if (type_initialized (t))
+       {
+         if (t->pc != k->pc && t->pc != UNINIT && k->pc != UNINIT)
+           return false;
+       }
+    }
 
   return ref_compatible (t->klass, k->klass);
 }
@@ -2162,7 +2179,11 @@ check_field_constant (int index, type *class_type, bool putfield)
       && vfr->current_state->this_type.pc == SELF
       && types_equal (&vfr->current_state->this_type, &ct)
       && vfy_class_has_field (vfr->current_class, name, field_type))
-    type_set_uninitialized (class_type, SELF);
+    /* Note that we don't actually know whether we're going to match
+       against 'this' or some other object of the same type.  So,
+       here we set things up so that it doesn't matter.  This relies
+       on knowing what our caller is up to.  */
+    type_set_uninitialized (class_type, EITHER);
 
   return t;
 }