X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/06b6c733aedcaeaa7b54a7152e9d5e5dfdc6266f..b21b18e18d6d54c57d7726525185dd9cc30ad2b6:/gdb/valops.c diff --git a/gdb/valops.c b/gdb/valops.c index b4101b5a9a..791b0971ea 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1,5 +1,5 @@ /* Perform non-arithmetic operations on values, for GDB. - Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. This file is part of GDB. @@ -17,10 +17,9 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include "defs.h" -#include "param.h" #include "symtab.h" +#include "gdbtypes.h" #include "value.h" #include "frame.h" #include "inferior.h" @@ -30,7 +29,26 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include /* Local functions. */ -static value search_struct_field (); + +static CORE_ADDR +find_function_addr PARAMS ((value, struct type **)); + +static CORE_ADDR +value_push PARAMS ((CORE_ADDR, value)); + +static CORE_ADDR +value_arg_push PARAMS ((CORE_ADDR, value)); + +static value +search_struct_field PARAMS ((char *, value, int, struct type *, int)); + +static value +search_struct_method PARAMS ((char *, value *, value *, int, int *, + struct type *)); + +static int +check_field_in PARAMS ((struct type *, const char *)); + /* Cast value ARG2 to type TYPE and return as a value. More general than a C cast: accepts any two types of the same length, @@ -70,7 +88,7 @@ value_cast (type, arg2) offset the pointer rather than just change its type. */ struct type *t1 = TYPE_TARGET_TYPE (type); struct type *t2 = TYPE_TARGET_TYPE (VALUE_TYPE (arg2)); - if (TYPE_CODE (t1) == TYPE_CODE_STRUCT + if ( TYPE_CODE (t1) == TYPE_CODE_STRUCT && TYPE_CODE (t2) == TYPE_CODE_STRUCT && TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */ { @@ -112,7 +130,7 @@ value_zero (type, lv) { register value val = allocate_value (type); - bzero (VALUE_CONTENTS (val), TYPE_LENGTH (type)); + memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (type)); VALUE_LVAL (val) = lv; return val; @@ -163,6 +181,9 @@ value_at_lazy (type, addr) data from the user's process, and clears the lazy flag to indicate that the data in the buffer is valid. + If the value is zero-length, we avoid calling read_memory, which would + abort. We mark the value as fetched anyway -- all 0 bytes of it. + This function returns a value because it is used in the VALUE_CONTENTS macro as part of an expression, where a void would not work. The value is ignored. */ @@ -173,8 +194,9 @@ value_fetch_lazy (val) { CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val); - read_memory (addr, VALUE_CONTENTS_RAW (val), - TYPE_LENGTH (VALUE_TYPE (val))); + if (TYPE_LENGTH (VALUE_TYPE (val))) + read_memory (addr, VALUE_CONTENTS_RAW (val), + TYPE_LENGTH (VALUE_TYPE (val))); VALUE_LAZY (val) = 0; return 0; } @@ -194,6 +216,7 @@ value_assign (toval, fromval) int use_buffer = 0; COERCE_ARRAY (fromval); + COERCE_REF (toval); if (VALUE_LVAL (toval) != lval_internalvar) fromval = value_cast (type, fromval); @@ -209,7 +232,7 @@ value_assign (toval, fromval) int regno = VALUE_REGNO (toval); if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno)) fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval); - bcopy (VALUE_CONTENTS (fromval), virtual_buffer, + memcpy (virtual_buffer, VALUE_CONTENTS (fromval), REGISTER_VIRTUAL_SIZE (regno)); target_convert_from_virtual (regno, virtual_buffer, raw_buffer); use_buffer = REGISTER_RAW_SIZE (regno); @@ -234,8 +257,8 @@ value_assign (toval, fromval) { int v; /* FIXME, this won't work for large bitfields */ read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - &v, sizeof v); - modify_field (&v, (int) value_as_long (fromval), + (char *) &v, sizeof v); + modify_field ((char *) &v, (int) value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), (char *)&v, sizeof v); @@ -254,11 +277,11 @@ value_assign (toval, fromval) int v; read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - &v, sizeof v); - modify_field (&v, (int) value_as_long (fromval), + (char *) &v, sizeof v); + modify_field ((char *) &v, (int) value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - &v, sizeof v); + (char *) &v, sizeof v); } else if (use_buffer) write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), @@ -300,7 +323,7 @@ value_assign (toval, fromval) amount_copied += reg_size, regno++) { get_saved_register (buffer + amount_copied, - (int *)NULL, (CORE_ADDR)NULL, + (int *)NULL, (CORE_ADDR *)NULL, frame, regno, (enum lval_type *)NULL); } @@ -310,10 +333,10 @@ value_assign (toval, fromval) (int) value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); else if (use_buffer) - bcopy (raw_buffer, buffer + byte_offset, use_buffer); + memcpy (buffer + byte_offset, raw_buffer, use_buffer); else - bcopy (VALUE_CONTENTS (fromval), buffer + byte_offset, - TYPE_LENGTH (type)); + memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval), + TYPE_LENGTH (type)); /* Copy it back. */ for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset, @@ -356,8 +379,9 @@ value_assign (toval, fromval) } val = allocate_value (type); - bcopy (toval, val, VALUE_CONTENTS_RAW (val) - (char *) val); - bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type)); + memcpy (val, toval, VALUE_CONTENTS_RAW (val) - (char *) val); + memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval), + TYPE_LENGTH (type)); VALUE_TYPE (val) = type; return val; @@ -446,18 +470,26 @@ value value_addr (arg1) value arg1; { - - COERCE_REF(arg1); + struct type *type = VALUE_TYPE (arg1); + if (TYPE_CODE (type) == TYPE_CODE_REF) + { + /* Copy the value, but change the type from (T&) to (T*). + We keep the same location information, which is efficient, + and allows &(&X) to get the location containing the reference. */ + value arg2 = value_copy (arg1); + VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type)); + return arg2; + } if (VALUE_REPEATED (arg1) - || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY) + || TYPE_CODE (type) == TYPE_CODE_ARRAY) return value_coerce_array (arg1); - if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FUNC) + if (TYPE_CODE (type) == TYPE_CODE_FUNC) return value_coerce_function (arg1); if (VALUE_LVAL (arg1) != lval_memory) error ("Attempt to take address of value not located in memory."); - return value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)), + return value_from_longest (lookup_pointer_type (type), (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1))); } @@ -530,7 +562,7 @@ push_bytes (sp, buffer, len) /* Push onto the stack the specified value VALUE. */ -CORE_ADDR +static CORE_ADDR value_push (sp, arg) register CORE_ADDR sp; value arg; @@ -562,10 +594,11 @@ value_arg_coerce (arg) type = VALUE_TYPE (arg); if (TYPE_CODE (type) == TYPE_CODE_INT - && TYPE_LENGTH (type) < sizeof (int)) + && TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int)) return value_cast (builtin_type_int, arg); - if (type == builtin_type_float) + if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double)) return value_cast (builtin_type_double, arg); return arg; @@ -574,7 +607,7 @@ value_arg_coerce (arg) /* Push the value ARG, first coercing it as an argument to a C function. */ -CORE_ADDR +static CORE_ADDR value_arg_push (sp, arg) register CORE_ADDR sp; value arg; @@ -585,7 +618,7 @@ value_arg_push (sp, arg) /* Determine a function's address and its return type from its value. Calls error() if the function is not valid for calling. */ -CORE_ADDR +static CORE_ADDR find_function_addr (function, retval_type) value function; struct type **retval_type; @@ -659,7 +692,7 @@ call_function_by_hand (function, nargs, args) register int i; CORE_ADDR start_sp; /* CALL_DUMMY is an array of words (REGISTER_TYPE), but each word - in in host byte order. It is switched to target byte order before calling + is in host byte order. It is switched to target byte order before calling FIX_CALL_DUMMY. */ static REGISTER_TYPE dummy[] = CALL_DUMMY; REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)]; @@ -672,6 +705,9 @@ call_function_by_hand (function, nargs, args) CORE_ADDR funaddr; int using_gcc; + if (!target_has_execution) + noprocess(); + save_inferior_status (&inf_status, 1); old_chain = make_cleanup (restore_inferior_status, &inf_status); @@ -706,7 +742,7 @@ call_function_by_hand (function, nargs, args) /* Create a call sequence customized for this function and the number of arguments for it. */ - bcopy (dummy, dummy1, sizeof dummy); + memcpy (dummy1, dummy, sizeof dummy); for (i = 0; i < sizeof dummy / sizeof (REGISTER_TYPE); i++) SWAP_TARGET_AND_HOST (&dummy1[i], sizeof (REGISTER_TYPE)); FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, @@ -720,6 +756,7 @@ call_function_by_hand (function, nargs, args) /* Convex Unix prohibits executing in the stack segment. */ /* Hope there is empty room at the top of the text segment. */ { + extern CORE_ADDR text_end; static checked = 0; if (!checked) for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp) @@ -732,6 +769,7 @@ call_function_by_hand (function, nargs, args) } #else /* After text_end. */ { + extern CORE_ADDR text_end; int errcode; sp = old_sp; start_sp = text_end; @@ -891,7 +929,7 @@ value_string (ptr, len) register int c; /* Copy the string into COPY, processing escapes. - We could not conveniently process them in expread + We could not conveniently process them in the parser because the string there wants to be a substring of the input. */ while (i - ibeg < len) @@ -922,19 +960,19 @@ value_string (ptr, len) } else { - register int j; - j = lookup_misc_func ("malloc"); - if (j >= 0) - val = value_from_longest ( - lookup_pointer_type (lookup_function_type ( - lookup_pointer_type (builtin_type_char))), - (LONGEST) misc_function_vector[j].address); + struct minimal_symbol *msymbol; + msymbol = lookup_minimal_symbol ("malloc", (struct objfile *) NULL); + if (msymbol != NULL) + val = + value_from_longest (lookup_pointer_type (lookup_function_type ( + lookup_pointer_type (builtin_type_char))), + (LONGEST) msymbol -> address); else error ("String constants require the program to have a function \"malloc\"."); } blocklen = value_from_longest (builtin_type_int, (LONGEST) (len + 1)); - val = target_call_function (val, 1, &blocklen); + val = call_function_by_hand (val, 1, &blocklen); if (value_zerop (val)) error ("No memory available for string constant."); write_memory (value_as_pointer (val), copy, len + 1); @@ -944,7 +982,7 @@ value_string (ptr, len) /* Helper function used by value_struct_elt to recurse through baseclasses. Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes, - and treat the result as having type TYPE. + and search in it assuming it has (class) type TYPE. If found, return value, else return NULL. If LOOKING_FOR_BASECLASS, then instead of looking for struct fields, @@ -969,9 +1007,20 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) if (t_field_name && !strcmp (t_field_name, name)) { - value v = (TYPE_FIELD_STATIC (type, i) - ? value_static_field (type, name, i) - : value_primitive_field (arg1, offset, i, type)); + value v; + if (TYPE_FIELD_STATIC (type, i)) + { + char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i); + struct symbol *sym = + lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); + if (! sym) error ( + "Internal error: could not find physical static variable named %s", + phys_name); + v = value_at (TYPE_FIELD_TYPE (type, i), + (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); + } + else + v = value_primitive_field (arg1, offset, i, type); if (v == 0) error("there is no field named %s", name); return v; @@ -989,6 +1038,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) if (BASETYPE_VIA_VIRTUAL (type, i)) { value v2; + /* Fix to use baseclass_offset instead. FIXME */ baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset, &v2, (int *)NULL); if (v2 == 0) @@ -997,10 +1047,8 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) return v2; v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i), looking_for_baseclass); - if (v) return v; - else continue; } - if (found_baseclass) + else if (found_baseclass) v = value_primitive_field (arg1, offset, i, type); else v = search_struct_field (name, arg1, @@ -1014,13 +1062,13 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) /* Helper function used by value_struct_elt to recurse through baseclasses. Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes, - and treat the result as having type TYPE. + and search in it assuming it has (class) type TYPE. If found, return value, else return NULL. */ static value -search_struct_method (name, arg1, args, offset, static_memfuncp, type) +search_struct_method (name, arg1p, args, offset, static_memfuncp, type) char *name; - register value arg1, *args; + register value *arg1p, *args; int offset, *static_memfuncp; register struct type *type; { @@ -1039,16 +1087,16 @@ search_struct_method (name, arg1, args, offset, static_memfuncp, type) error ("cannot resolve overloaded method `%s'", name); while (j >= 0) { - if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) & TYPE_FLAG_STUB) + if (TYPE_FN_FIELD_STUB (f, j)) check_stub_method (type, i, j); if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j), TYPE_FN_FIELD_ARGS (f, j), args)) { if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - return (value)value_virtual_fn_field (arg1, f, j, type); + return (value)value_virtual_fn_field (arg1p, f, j, type, offset); if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp) *static_memfuncp = 1; - return (value)value_fn_field (arg1, i, j); + return (value)value_fn_field (arg1p, f, j, type, offset); } j--; } @@ -1058,24 +1106,26 @@ search_struct_method (name, arg1, args, offset, static_memfuncp, type) for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) { value v; + int base_offset; if (BASETYPE_VIA_VIRTUAL (type, i)) { - value v2; - baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset, - &v2, (int *)NULL); - if (v2 == 0) + base_offset = + baseclass_offset (type, i, *arg1p, offset); + if (base_offset == -1) error ("virtual baseclass botch"); - v = search_struct_method (name, v2, args, 0, - static_memfuncp, TYPE_BASECLASS (type, i)); - if (v) return v; - else continue; } - - v = search_struct_method (name, arg1, args, - TYPE_BASECLASS_BITPOS (type, i) / 8, + else + { + base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8; + } + v = search_struct_method (name, arg1p, args, base_offset + offset, static_memfuncp, TYPE_BASECLASS (type, i)); - if (v) return v; + if (v) + { +/* *arg1p = arg1_tmp;*/ + return v; + } } return NULL; } @@ -1122,7 +1172,7 @@ value_struct_elt (argp, args, name, static_memfuncp, err) if (TYPE_CODE (t) == TYPE_CODE_MEMBER) error ("not implemented: member type in value_struct_elt"); - if (TYPE_CODE (t) != TYPE_CODE_STRUCT + if ( TYPE_CODE (t) != TYPE_CODE_STRUCT && TYPE_CODE (t) != TYPE_CODE_UNION) error ("Attempt to extract a component of a value that is not a %s.", err); @@ -1146,7 +1196,7 @@ value_struct_elt (argp, args, name, static_memfuncp, err) if (destructor_name_p (name, t)) error ("Cannot get value of destructor"); - v = search_struct_method (name, *argp, args, 0, static_memfuncp, t); + v = search_struct_method (name, argp, args, 0, static_memfuncp, t); if (v == 0) { @@ -1163,8 +1213,9 @@ value_struct_elt (argp, args, name, static_memfuncp, err) if (!args[1]) { /* destructors are a special case. */ - return (value)value_fn_field (*argp, 0, - TYPE_FN_FIELDLIST_LENGTH (t, 0)); + return (value)value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, 0), + TYPE_FN_FIELDLIST_LENGTH (t, 0), + 0, 0); } else { @@ -1172,7 +1223,7 @@ value_struct_elt (argp, args, name, static_memfuncp, err) } } else - v = search_struct_method (name, *argp, args, 0, static_memfuncp, t); + v = search_struct_method (name, argp, args, 0, static_memfuncp, t); if (v == 0) { @@ -1192,17 +1243,14 @@ value_struct_elt (argp, args, name, static_memfuncp, err) if NAME is inappropriate for TYPE, an error is signaled. */ int destructor_name_p (name, type) - char *name; - struct type *type; + const char *name; + const struct type *type; { /* destructors are a special case. */ if (name[0] == '~') { char *dname = type_name_no_tag (type); - - if (! TYPE_HAS_DESTRUCTOR (type)) - error ("type `%s' does not have destructor defined", dname); if (strcmp (dname, name+1)) error ("name of destructor must equal name of class"); else @@ -1218,7 +1266,7 @@ destructor_name_p (name, type) static int check_field_in (type, name) register struct type *type; - char *name; + const char *name; { register int i; @@ -1257,7 +1305,7 @@ check_field_in (type, name) int check_field (arg1, name) register value arg1; - char *name; + const char *name; { register struct type *t; @@ -1273,129 +1321,142 @@ check_field (arg1, name) if (TYPE_CODE (t) == TYPE_CODE_MEMBER) error ("not implemented: member type in check_field"); - if (TYPE_CODE (t) != TYPE_CODE_STRUCT + if ( TYPE_CODE (t) != TYPE_CODE_STRUCT && TYPE_CODE (t) != TYPE_CODE_UNION) error ("Internal error: `this' is not an aggregate"); return check_field_in (t, name); } -/* C++: Given an aggregate type DOMAIN, and a member name NAME, - return the address of this member as a pointer to member +/* C++: Given an aggregate type CURTYPE, and a member name NAME, + return the address of this member as a "pointer to member" type. If INTYPE is non-null, then it will be the type of the member we are looking for. This will help us resolve - pointers to member functions. */ + "pointers to member functions". This function is used + to resolve user expressions of the form "DOMAIN::NAME". */ value -value_struct_elt_for_address (domain, intype, name) - struct type *domain, *intype; +value_struct_elt_for_reference (domain, offset, curtype, name, intype) + struct type *domain, *curtype, *intype; + int offset; char *name; { - register struct type *t = domain; + register struct type *t = curtype; register int i; value v; - struct type *baseclass; - - if (TYPE_CODE (t) != TYPE_CODE_STRUCT + if ( TYPE_CODE (t) != TYPE_CODE_STRUCT && TYPE_CODE (t) != TYPE_CODE_UNION) - error ("Internal error: non-aggregate type to value_struct_elt_for_address"); - - baseclass = t; + error ("Internal error: non-aggregate type to value_struct_elt_for_reference"); - while (t) + for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) { - for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) + char *t_field_name = TYPE_FIELD_NAME (t, i); + + if (t_field_name && !strcmp (t_field_name, name)) { - char *t_field_name = TYPE_FIELD_NAME (t, i); - if (t_field_name && !strcmp (t_field_name, name)) + if (TYPE_FIELD_STATIC (t, i)) { - if (TYPE_FIELD_STATIC (t, i)) - { - char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i); - struct symbol *sym = - lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); - if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name); - return value_from_longest ( - lookup_pointer_type (TYPE_FIELD_TYPE (t, i)), - (LONGEST)SYMBOL_BLOCK_VALUE (sym)); - } - if (TYPE_FIELD_PACKED (t, i)) - error ("pointers to bitfield members not allowed"); - - return value_from_longest ( - lookup_pointer_type ( - lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass)), - (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3)); + char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i); + struct symbol *sym = + lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); + if (! sym) + error ( + "Internal error: could not find physical static variable named %s", + phys_name); + return value_at (SYMBOL_TYPE (sym), + (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); } + if (TYPE_FIELD_PACKED (t, i)) + error ("pointers to bitfield members not allowed"); + + return value_from_longest + (lookup_reference_type (lookup_member_type (TYPE_FIELD_TYPE (t, i), + domain)), + offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3)); } - - if (TYPE_N_BASECLASSES (t) == 0) - break; - - t = TYPE_BASECLASS (t, 0); } /* C++: If it was not found as a data field, then try to return it as a pointer to a method. */ - t = baseclass; /* Destructors are a special case. */ if (destructor_name_p (name, t)) { - error ("pointers to destructors not implemented yet"); + error ("member pointers to destructors not implemented yet"); } /* Perform all necessary dereferencing. */ while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR) intype = TYPE_TARGET_TYPE (intype); - while (t) + for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) { - for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) + if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name)) { - if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name)) + int j = TYPE_FN_FIELDLIST_LENGTH (t, i); + struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); + + if (intype == 0 && j > 1) + error ("non-unique member `%s' requires type instantiation", name); + if (intype) { - int j = TYPE_FN_FIELDLIST_LENGTH (t, i); - struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); - - if (intype == 0 && j > 1) - error ("non-unique member `%s' requires type instantiation", name); - if (intype) - { - while (j--) - if (TYPE_FN_FIELD_TYPE (f, j) == intype) - break; - if (j < 0) - error ("no member function matches that type instantiation"); - } - else - j = 0; - - check_stub_method (t, i, j); - if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + while (j--) + if (TYPE_FN_FIELD_TYPE (f, j) == intype) + break; + if (j < 0) + error ("no member function matches that type instantiation"); + } + else + j = 0; + + if (TYPE_FN_FIELD_STUB (f, j)) + check_stub_method (t, i, j); + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + { + return value_from_longest + (lookup_reference_type + (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), + domain)), + METHOD_PTR_FROM_VOFFSET((LONGEST) TYPE_FN_FIELD_VOFFSET (f, j))); + } + else + { + struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), + 0, VAR_NAMESPACE, 0, NULL); + if (s == NULL) { - return value_from_longest ( - lookup_pointer_type ( - lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), - baseclass)), - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); + v = 0; } else { - struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), - 0, VAR_NAMESPACE, 0, NULL); - v = locate_var_value (s, 0); - VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass)); - return v; + v = read_var_value (s, 0); +#if 0 + VALUE_TYPE (v) = lookup_reference_type + (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), + domain)); +#endif } + return v; } } + } + for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--) + { + value v; + int base_offset; - if (TYPE_N_BASECLASSES (t) == 0) - break; - - t = TYPE_BASECLASS (t, 0); + if (BASETYPE_VIA_VIRTUAL (t, i)) + base_offset = 0; + else + base_offset = TYPE_BASECLASS_BITPOS (t, i) / 8; + v = value_struct_elt_for_reference (domain, + offset + base_offset, + TYPE_BASECLASS (t, i), + name, + intype); + if (v) + return v; } return 0; }