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
This commit is contained in:
Tom Tromey 2005-02-22 18:14:37 +00:00 committed by Tom Tromey
parent de64691796
commit 84b6a4d217
2 changed files with 45 additions and 17 deletions

View 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:

View 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;
}