diff options
author | Daniel Jacobowitz <drow@false.org> | 2007-01-03 18:05:45 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2007-01-03 18:05:45 +0000 |
commit | 0d5de0100fd9c669790851af4f9f50704a24b453 (patch) | |
tree | f24fc195c586568deff26d6561c24cd65f1fd186 /gdb/eval.c | |
parent | 9d6063994fbb0f0ec4fb8005f18bc84768592368 (diff) | |
download | gdb-0d5de0100fd9c669790851af4f9f50704a24b453.zip gdb-0d5de0100fd9c669790851af4f9f50704a24b453.tar.gz gdb-0d5de0100fd9c669790851af4f9f50704a24b453.tar.bz2 |
* NEWS: Mention pointer to member improvements.
* Makefile.in (gnu-v3-abi.o): Delete special rule.
(eval.o, gnu-v3-abi.o, ia64-tdep.o): Update.
* ada-valprint.c (ada_print_scalar): Update for new type codes.
* c-typeprint.c (c_print_type): Update for new type codes.
(c_type_print_varspec_prefix, c_type_print_varspec_suffix)
(c_type_print_base): Likewise.
(c_type_print_args): Rewrite.
* c-valprint.c (c_val_print): Update for new type codes. Remove
support for references to members. Treat methods like functions.
* cp-abi.c (cplus_print_method_ptr, cplus_method_ptr_size)
(cplus_make_method_ptr, cplus_method_ptr_to_value): New.
* cp-abi.h (cplus_print_method_ptr, cplus_method_ptr_size)
(cplus_make_method_ptr, cplus_method_ptr_to_value): New prototypes.
(struct cp_abi_ops): Add corresponding members.
* cp-valprint.c (cp_print_class_method): Delete.
(cp_find_class_member): New function.
(cp_print_class_member): Use it. Simplify support for bogus
member pointers.
* dwarf2read.c (quirk_gcc_member_function_pointer): Use
lookup_methodptr_type.
(read_tag_ptr_to_member_type): Likewise, and lookup_memberptr_type.
* eval.c (evaluate_subexp_standard): Implement EVAL_SKIP for
OP_SCOPE. Update call to value_aggregate_elt. Rewrite member
pointer support.
(evaluate_subexp_for_address): Handle OP_SCOPE explicitly. Handle
references returned by user defined operators.
* f-typeprint.c (f_print_type, f_type_print_varspec_prefix)
(f_type_print_varspec_suffix): Remove support for member pointers.
* gdbtypes.c (lookup_memberptr_type): Renamed from lookup_member_type
and adjusted.
(smash_to_memberptr_type): Likewise, from smash_to_member_type.
(lookup_methodptr_type): New.
(rank_one_type): Adjust for TYPE_CODE_MEMBERPTR.
(recursive_dump_type): Update for new types.
* gdbtypes.h (enum type_code): Replace TYPE_CODE_MEMBER with
TYPE_CODE_MEMBERPTR and TYPE_CODE_METHODPTR.
(lookup_memberptr_type, lookup_methodptr_type)
(smash_to_memberptr_type): New prototypes.
(smash_to_method_type): Formatting fix.
(lookup_member_type, smash_to_member_type): Delete prototypes.
* gnu-v3-abi.c (gnuv3_get_vtable, gnuv3_get_virtual_fn): New.
Do not rely on debug information for the vptr or the method's
enclosing type. Handle function descriptors for IA64.
(gnuv3_virtual_fn_field): Rewrite using the new functions.
(gnuv3_find_method_in, gnuv3_print_method_ptr)
(gnuv3_method_ptr_size, gnuv3_make_method_ptr)
(gnuv3_method_ptr_to_value): New.
(init_gnuv3_ops): Set new members of gnu_v3_abi_ops.
* hpread.c (hpread_type_lookup): Update for new types.
* infcall.c (value_arg_coerce): Likewise.
* m2-typeprint.c (m2_print_type): Remove explicit support
for member pointers.
* m2-valprint.c (m2_val_print): Likewise.
* p-typeprint.c (pascal_type_print_varspec_prefix)
(pascal_type_print_varspec_suffix, pascal_type_print_base): Likewise.
* p-valprint.c (pascal_val_print): Likewise.
(pascal_object_print_class_method, pascal_object_print_class_member):
Delete.
* p-lang.h (pascal_object_print_class_method)
(pascal_object_print_class_member): Delete prototypes.
* stabsread.c (read_type): Update for new types.
* typeprint.c (print_type_scalar): Likewise.
* valops.c (value_struct_elt_for_reference, value_namespace_elt)
(value_maybe_namespace_elt, value_aggregate_elt): Add want_address
argument. Construct a pointer to member if the address of a
function or data member is requested.
(value_cast_pointers): Don't modify the input value.
(value_cast): Adjust pointer to member handling for new types.
Allow null pointer to member constants. Don't modify the input
value.
(value_ind): Remove pointer to member check. Handle function
descriptors for function pointers.
(value_struct_elt, value_find_oload_method_list, check_field):
Remove pointer to member checks.
* value.c (unpack_long): Allow pointers to data members.
(value_from_longest): Allow member pointers.
* value.h (value_aggregate_elt): Add want_address.
* varobj.c (c_variable_editable): Remove check for members.
* gdbarch.sh: Add vtable_function_descriptors and vbit_in_delta.
* ia64-tdep.c (ia64_convert_from_func_ptr_addr): Handle descriptors
in virtual tables.
(ia64_gdbarch_init): Call set_gdbarch_vtable_function_descriptors.
* c-lang.h (cp_print_class_method): Delete prototype.
* arm-tdep.c (arm_gdbarch_init): Call set_gdbarch_vbit_in_delta.
* mips-tdep.c (mips_gdbarch_init): Likewise.
* gdbarch.c, gdbarch.h: Regenerated.
* gdb.cp/classes.exp (test_pointers_to_class_members): Update expected
output. Test the types of members and member pointers.
* gdb.cp/inherit.exp (test_print_mi_member_types): Remove KFAILs for
gdb/2092.
* gdb.cp/member-ptr.exp: Search for a comment instead of a
statement. Enable for GCC. Update expected output for some tests
and add new tests. Remove obsolete GCC KFAILs. Allow GCC's class
layout.
* gdb.cp/member-ptr.cc (Padding, Padding::vspacer, Base, Base::get_x)
(Base::vget_base, Left, Left::vget, Right, Right::vget, Diamond)
(Diamond::vget_base): New.
(main): Add new tests.
* gdb.cp/printmethod.exp: Update expected output for member functions.
* gdb.cp/virtfunc.exp (test_virtual_calls): Add a KFAIL for
print pEe->D::vg().
Diffstat (limited to 'gdb/eval.c')
-rw-r--r-- | gdb/eval.c | 194 |
1 files changed, 88 insertions, 106 deletions
@@ -1,8 +1,8 @@ /* Evaluate expressions for GDB. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, - 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free - Software Foundation, Inc. + 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 + Free Software Foundation, Inc. This file is part of GDB. @@ -38,6 +38,8 @@ #include "parser-defs.h" #include "cp-support.h" +#include "gdb_assert.h" + /* This is defined in valops.c */ extern int overload_resolution; @@ -434,9 +436,11 @@ evaluate_subexp_standard (struct type *expect_type, case OP_SCOPE: tem = longest_to_int (exp->elts[pc + 2].longconst); (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1); + if (noside == EVAL_SKIP) + goto nosideret; arg1 = value_aggregate_elt (exp->elts[pc + 1].type, &exp->elts[pc + 3].string, - noside); + 0, noside); if (arg1 == NULL) error (_("There is no field named %s"), &exp->elts[pc + 3].string); return arg1; @@ -993,8 +997,6 @@ evaluate_subexp_standard (struct type *expect_type, argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 3)); if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { - LONGEST fnptr; - /* 1997-08-01 Currently we do not support function invocation via pointers-to-methods with HP aCC. Pointer does not point to the function, but possibly to some thunk. */ @@ -1027,41 +1029,18 @@ evaluate_subexp_standard (struct type *expect_type, arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); - fnptr = value_as_long (arg1); + if (TYPE_CODE (check_typedef (value_type (arg1))) + != TYPE_CODE_METHODPTR) + error (_("Non-pointer-to-member value used in pointer-to-member " + "construct")); - if (METHOD_PTR_IS_VIRTUAL (fnptr)) + if (noside == EVAL_AVOID_SIDE_EFFECTS) { - int fnoffset = METHOD_PTR_TO_VOFFSET (fnptr); - struct type *basetype; - struct type *domain_type = - TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (value_type (arg1))); - int i, j; - basetype = TYPE_TARGET_TYPE (value_type (arg2)); - if (domain_type != basetype) - arg2 = value_cast (lookup_pointer_type (domain_type), arg2); - basetype = TYPE_VPTR_BASETYPE (domain_type); - for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--) - { - struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i); - /* If one is virtual, then all are virtual. */ - if (TYPE_FN_FIELD_VIRTUAL_P (f, 0)) - for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j) - if ((int) TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset) - { - struct value *temp = value_ind (arg2); - arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0); - arg2 = value_addr (temp); - goto got_it; - } - } - if (i < 0) - error (_("virtual function at index %d not found"), fnoffset); + struct type *method_type = check_typedef (value_type (arg1)); + arg1 = value_zero (method_type, not_lval); } else - { - deprecated_set_value_type (arg1, lookup_pointer_type (TYPE_TARGET_TYPE (value_type (arg1)))); - } - got_it: + arg1 = cplus_method_ptr_to_value (&arg2, arg1); /* Now, say which argument to start evaluating from */ tem = 2; @@ -1396,57 +1375,60 @@ evaluate_subexp_standard (struct type *expect_type, } case STRUCTOP_MEMBER: - arg1 = evaluate_subexp_for_address (exp, pos, noside); + case STRUCTOP_MPTR: + if (op == STRUCTOP_MEMBER) + arg1 = evaluate_subexp_for_address (exp, pos, noside); + else + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); - /* With HP aCC, pointers to methods do not point to the function code */ - if (deprecated_hp_som_som_object_present && - (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR) && - (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg2))) == TYPE_CODE_METHOD)) - error (_("Pointers to methods not supported with HP aCC")); /* 1997-08-19 */ + if (noside == EVAL_SKIP) + goto nosideret; - mem_offset = value_as_long (arg2); - goto handle_pointer_to_member; + type = check_typedef (value_type (arg2)); + switch (TYPE_CODE (type)) + { + case TYPE_CODE_METHODPTR: + if (deprecated_hp_som_som_object_present) + { + /* With HP aCC, pointers to methods do not point to the + function code. */ + /* 1997-08-19 */ + error (_("Pointers to methods not supported with HP aCC")); + } - case STRUCTOP_MPTR: - arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); - arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (TYPE_TARGET_TYPE (type), not_lval); + else + { + arg2 = cplus_method_ptr_to_value (&arg1, arg2); + gdb_assert (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR); + return value_ind (arg2); + } - /* With HP aCC, pointers to methods do not point to the function code */ - if (deprecated_hp_som_som_object_present && - (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR) && - (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg2))) == TYPE_CODE_METHOD)) - error (_("Pointers to methods not supported with HP aCC")); /* 1997-08-19 */ + case TYPE_CODE_MEMBERPTR: + /* Now, convert these values to an address. */ + arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)), + arg1); - mem_offset = value_as_long (arg2); + mem_offset = value_as_long (arg2); + if (deprecated_hp_som_som_object_present) + { + /* HP aCC generates offsets that have bit #29 set; turn it off to get + a real offset to the member. */ + if (!mem_offset) /* no bias -> really null */ + error (_("Attempted dereference of null pointer-to-member")); + mem_offset &= ~0x20000000; + } - handle_pointer_to_member: - /* HP aCC generates offsets that have bit #29 set; turn it off to get - a real offset to the member. */ - if (deprecated_hp_som_som_object_present) - { - if (!mem_offset) /* no bias -> really null */ - error (_("Attempted dereference of null pointer-to-member")); - mem_offset &= ~0x20000000; + arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + value_as_long (arg1) + mem_offset); + return value_ind (arg3); + + default: + error (_("non-pointer-to-member value used in pointer-to-member construct")); } - if (noside == EVAL_SKIP) - goto nosideret; - type = check_typedef (value_type (arg2)); - if (TYPE_CODE (type) != TYPE_CODE_PTR) - goto bad_pointer_to_member; - type = check_typedef (TYPE_TARGET_TYPE (type)); - if (TYPE_CODE (type) == TYPE_CODE_METHOD) - error (_("not implemented: pointer-to-method in pointer-to-member construct")); - if (TYPE_CODE (type) != TYPE_CODE_MEMBER) - goto bad_pointer_to_member; - /* Now, convert these values to an address. */ - arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)), - arg1); - arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), - value_as_long (arg1) + mem_offset); - return value_ind (arg3); - bad_pointer_to_member: - error (_("non-pointer-to-member value used in pointer-to-member construct")); case BINOP_CONCAT: arg1 = evaluate_subexp_with_coercion (exp, pos, noside); @@ -1469,13 +1451,11 @@ evaluate_subexp_standard (struct type *expect_type, the implementation yet; but the pointer appears to point to a code sequence (thunk) in memory -- in any case it is *not* the address of the function as it would be in a naive implementation. */ - if ((TYPE_CODE (value_type (arg1)) == TYPE_CODE_PTR) && - (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_METHOD)) + if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_METHODPTR) error (_("Assignment to pointers to methods not implemented with HP aCC")); - /* HP aCC pointers to data members require a constant bias */ - if ((TYPE_CODE (value_type (arg1)) == TYPE_CODE_PTR) && - (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_MEMBER)) + /* HP aCC pointers to data members require a constant bias. */ + if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_MEMBERPTR) { unsigned int *ptr = (unsigned int *) value_contents (arg2); /* forces evaluation */ *ptr |= 0x20000000; /* set 29th bit */ @@ -1934,9 +1914,9 @@ evaluate_subexp_standard (struct type *expect_type, if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR) expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type)); arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if ((TYPE_TARGET_TYPE (value_type (arg1))) && - ((TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_METHOD) || - (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_MEMBER))) + type = check_typedef (value_type (arg1)); + if (TYPE_CODE (type) == TYPE_CODE_METHODPTR + || TYPE_CODE (type) == TYPE_CODE_MEMBERPTR) error (_("Attempt to dereference pointer to member without an object")); if (noside == EVAL_SKIP) goto nosideret; @@ -1967,22 +1947,15 @@ evaluate_subexp_standard (struct type *expect_type, if (noside == EVAL_SKIP) { - if (op == OP_SCOPE) - { - int temm = longest_to_int (exp->elts[pc + 3].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (temm + 1); - } - else - evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); goto nosideret; } else { struct value *retvalp = evaluate_subexp_for_address (exp, pos, noside); /* If HP aCC object, use bias for pointers to members */ - if (deprecated_hp_som_som_object_present && - (TYPE_CODE (value_type (retvalp)) == TYPE_CODE_PTR) && - (TYPE_CODE (TYPE_TARGET_TYPE (value_type (retvalp))) == TYPE_CODE_MEMBER)) + if (deprecated_hp_som_som_object_present + && TYPE_CODE (value_type (retvalp)) == TYPE_CODE_MEMBERPTR) { unsigned int *ptr = (unsigned int *) value_contents (retvalp); /* forces evaluation */ *ptr |= 0x20000000; /* set 29th bit */ @@ -2148,6 +2121,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, int pc; struct symbol *var; struct value *x; + int tem; pc = (*pos); op = exp->elts[pc].opcode; @@ -2162,15 +2136,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, if (unop_user_defined_p (op, x)) { x = value_x_unop (x, op, noside); - if (noside == EVAL_AVOID_SIDE_EFFECTS) - { - if (VALUE_LVAL (x) == lval_memory) - return value_zero (lookup_pointer_type (value_type (x)), - not_lval); - else - error (_("Attempt to take address of non-lval")); - } - return value_addr (x); + goto default_case_after_eval; } return x; @@ -2210,14 +2176,30 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, (var, block_innermost_frame (exp->elts[pc + 1].block)); + case OP_SCOPE: + tem = longest_to_int (exp->elts[pc + 2].longconst); + (*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1); + x = value_aggregate_elt (exp->elts[pc + 1].type, + &exp->elts[pc + 3].string, + 1, noside); + if (x == NULL) + error (_("There is no field named %s"), &exp->elts[pc + 3].string); + return x; + default: default_case: x = evaluate_subexp (NULL_TYPE, exp, pos, noside); + default_case_after_eval: if (noside == EVAL_AVOID_SIDE_EFFECTS) { + struct type *type = check_typedef (value_type (x)); + if (VALUE_LVAL (x) == lval_memory) return value_zero (lookup_pointer_type (value_type (x)), not_lval); + else if (TYPE_CODE (type) == TYPE_CODE_REF) + return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + not_lval); else error (_("Attempt to take address of non-lval")); } |