aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/verify-impl.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2005-02-22 18:14:37 +0000
committerTom Tromey <tromey@gcc.gnu.org>2005-02-22 18:14:37 +0000
commit84b6a4d217b2762af5b223afc35c56d4c91e9d00 (patch)
tree50a948b2042b828a734df573abcc30e89cb95cfc /gcc/java/verify-impl.c
parentde646917966153fb997aff63928c9f3bfcb613f3 (diff)
downloadgcc-84b6a4d217b2762af5b223afc35c56d4c91e9d00.zip
gcc-84b6a4d217b2762af5b223afc35c56d4c91e9d00.tar.gz
gcc-84b6a4d217b2762af5b223afc35c56d4c91e9d00.tar.bz2
re PR java/20056 ('verification failed: incompatible type on stack' with --indirect-dispatch)
PR java/20056: * verify-impl.c (EITHER): New define. (types_compatible): Handle it. (check_field_constant): Use it. From-SVN: r95404
Diffstat (limited to 'gcc/java/verify-impl.c')
-rw-r--r--gcc/java/verify-impl.c55
1 files changed, 38 insertions, 17 deletions
diff --git a/gcc/java/verify-impl.c b/gcc/java/verify-impl.c
index bd681d2..ae585c8 100644
--- a/gcc/java/verify-impl.c
+++ b/gcc/java/verify-impl.c
@@ -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;
}