From 1870a43b3e9ab55bc5b29284c64be32d08989bf3 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 19 Feb 2005 01:14:17 +0000 Subject: [PATCH] re PR java/20056 ('verification failed: incompatible type on stack' with --indirect-dispatch) PR java/20056: * verify-glue.c (vfy_class_has_field): New function. * verify.h (vfy_class_has_field): Declare. * verify-impl.c (check_field_constant): Added 'putfield' argument. (verify_instructions_0): Updated. (types_equal): New function. From-SVN: r95258 --- gcc/java/ChangeLog | 10 ++++++++++ gcc/java/verify-glue.c | 17 +++++++++++++++- gcc/java/verify-impl.c | 45 ++++++++++++++++++++++++++++++------------ gcc/java/verify.h | 4 +++- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 02d12c161b9..84a0e78af1c 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,13 @@ +2005-02-18 Tom Tromey + + PR java/20056: + * verify-glue.c (vfy_class_has_field): New function. + * verify.h (vfy_class_has_field): Declare. + * verify-impl.c (check_field_constant): Added 'putfield' + argument. + (verify_instructions_0): Updated. + (types_equal): New function. + 2005-02-14 Tom Tromey PR java/19921: diff --git a/gcc/java/verify-glue.c b/gcc/java/verify-glue.c index b2cd9156cd0..5d480e88d68 100644 --- a/gcc/java/verify-glue.c +++ b/gcc/java/verify-glue.c @@ -1,5 +1,5 @@ /* Glue to interface gcj with bytecode verifier. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -385,6 +385,21 @@ vfy_null_type (void) return TYPE_NULL; } +bool +vfy_class_has_field (vfy_jclass klass, vfy_string name, + vfy_string signature) +{ + tree field = TYPE_FIELDS (klass); + while (field != NULL_TREE) + { + if (DECL_NAME (field) == name + && build_java_signature (TREE_TYPE (field)) == signature) + return true; + field = TREE_CHAIN (field); + } + return false; +} + int vfy_fail (const char *message, int pc, vfy_jclass ignore1 ATTRIBUTE_UNUSED, vfy_method *ignore2 ATTRIBUTE_UNUSED) diff --git a/gcc/java/verify-impl.c b/gcc/java/verify-impl.c index ee8f426e5a3..376f7494860 100644 --- a/gcc/java/verify-impl.c +++ b/gcc/java/verify-impl.c @@ -738,6 +738,20 @@ types_compatible (type *t, type *k) return ref_compatible (t->klass, k->klass); } +/* Return true if two types are equal. Only valid for reference + types. */ +static bool +types_equal (type *t1, type *t2) +{ + if (t1->key != reference_type || t1->key != uninitialized_reference_type + || t2->key != reference_type || t2->key != uninitialized_reference_type) + return false; + /* Only single-ref types are allowed. */ + if (t1->klass->ref_next || t2->klass->ref_next) + return false; + return refs_equal (t1->klass, t2->klass); +} + static bool type_isvoid (type *t) { @@ -2117,9 +2131,10 @@ handle_field_or_method (int index, int expected, return check_class_constant (class_index); } -/* Return field's type, compute class' type if requested. */ +/* Return field's type, compute class' type if requested. If + PUTFIELD is true, use the special 'putfield' semantics. */ static type -check_field_constant (int index, type *class_type) +check_field_constant (int index, type *class_type, bool putfield) { vfy_string name, field_type; const char *typec; @@ -2137,6 +2152,17 @@ check_field_constant (int index, type *class_type) init_type_from_string (&t, field_type); else init_type_from_tag (&t, get_type_val_for_signature (typec[0])); + + /* We have an obscure special case here: we can use `putfield' on a + field declared in this class, even if `this' has not yet been + initialized. */ + if (putfield + && ! type_initialized (&vfr->current_state->this_type) + && 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); + return t; } @@ -2971,15 +2997,15 @@ verify_instructions_0 (void) invalidate_pc (); break; case op_getstatic: - push_type_t (check_field_constant (get_ushort (), NULL)); + push_type_t (check_field_constant (get_ushort (), NULL, false)); break; case op_putstatic: - pop_type_t (check_field_constant (get_ushort (), NULL)); + pop_type_t (check_field_constant (get_ushort (), NULL, false)); break; case op_getfield: { type klass; - type field = check_field_constant (get_ushort (), &klass); + type field = check_field_constant (get_ushort (), &klass, false); pop_type_t (klass); push_type_t (field); } @@ -2987,15 +3013,8 @@ verify_instructions_0 (void) case op_putfield: { type klass; - type field = check_field_constant (get_ushort (), &klass); + type field = check_field_constant (get_ushort (), &klass, true); pop_type_t (field); - - /* We have an obscure special case here: we can use - `putfield' on a field declared in this class, even if - `this' has not yet been initialized. */ - if (! type_initialized (&vfr->current_state->this_type) - && vfr->current_state->this_type.pc == SELF) - type_set_uninitialized (&klass, SELF); pop_type_t (klass); } break; diff --git a/gcc/java/verify.h b/gcc/java/verify.h index 3553d357960..b23a08a9888 100644 --- a/gcc/java/verify.h +++ b/gcc/java/verify.h @@ -1,5 +1,5 @@ /* Declarations to interface gcj with bytecode verifier. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -126,6 +126,8 @@ void vfy_note_stack_type (vfy_method *method, int pc, int slot, void vfy_note_local_type (vfy_method *method, int pc, int slot, vfy_jclass type); void vfy_note_instruction_seen (int pc); +bool vfy_class_has_field (vfy_jclass klass, vfy_string name, + vfy_string signature); #define GLOM(name, stuff) name ## stuff #define VFY_PRIMITIVE_CLASS(name) \ -- 2.30.2