From 01be69139ed994faaf4119d193bec3816e4c9a09 Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Fri, 20 Mar 1992 21:57:17 +0000 Subject: [PATCH] More C++ improvements (pointers to members, qualified names). See ChangeLog. --- gdb/ChangeLog | 32 ++++ gdb/c-exp.y | 31 +++- gdb/eval.c | 119 +++++++------- gdb/valops.c | 247 +++++++++++++++------------- gdb/value.h | 436 ++++++++++++++++++++++++++++++++++++-------------- gdb/values.c | 78 +-------- 6 files changed, 569 insertions(+), 374 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6fb9b11d9e..346d718950 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,35 @@ +Thu Mar 19 18:49:45 1992 Per Bothner (bothner@cygnus.com) + + More C++ improvements (pointers to members, qualified names). + * c-exp.y: Support exp.type::name and exp->type::name + syntaxes. (Unfortunately, doesn't work for static members.) + * c-exp.y, eval.c: Make type::~type work better. + * eval.c (evaluate_subexp: OP_SCOPE): Replace use of + value_static_field by value_struct_elt_for_reference. + * eval.c (evaluate_subexp): Merge code for STRUCTOP_MEMBER + and STRUCTOP_MPTR; cast arg1 to domain-type of arg2. + * eval.c (evaluate_subexp): Remove special case for UNOP_ADDR + for OP_SCOPE operand; no point in it now that we use lazy + reading of values, and use "reference to member" objects. + * gdbtypes.h: Clarify comment. + * valops.c: Change value_struct_elt_for_address to return + a reference (or variable), rather than a pointer. Change + the name to value_struct_elt_for_reference to reflect this. + Returning a reference instead of a address provides a + generalization, since we can use the routine for both + class::name as well as &class::name. + Also, recurse to handle multiple inheritance properly. + * valprint.c: Moved code to print pointer-to-members + to new function point_class_member. This allows a + "reference-to-member" to be printed using the same code. + * valprint.c (type_print_varspec_prefix): Avoid printing + "struct " for domains of class-member types. + * valops.c (search_struct_field): Inline code for simplified + version of value_static_field (which can then be deleted). + * value.h: Rename value_struct_elt_for_address to + value_struct_elt_for_reference. Delete value_static_field. + * values.c: Remove no longer used function value_static_field. + Thu Mar 19 13:54:11 1992 Fred Fish (fnf@cygnus.com) * coffread.c, mipsread.c, xcoffread.c, coffread.c, dbxread.c, diff --git a/gdb/c-exp.y b/gdb/c-exp.y index c1316431b5..bbf66e00c8 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -120,7 +120,7 @@ static int parse_number PARAMS ((char *, int, int, YYSTYPE *)); %} -%type exp exp1 type_exp start variable +%type exp exp1 type_exp start variable qualified_name %type type typebase %type nonempty_typelist /* %type block */ @@ -257,6 +257,13 @@ exp : exp ARROW name write_exp_elt_opcode (STRUCTOP_PTR); } ; +exp : exp ARROW qualified_name + { /* exp->type::name becomes exp->*(&type::name) */ + /* Note: this doesn't work if name is a + static member! FIXME */ + write_exp_elt_opcode (UNOP_ADDR); + write_exp_elt_opcode (STRUCTOP_MPTR); } + ; exp : exp ARROW '*' exp { write_exp_elt_opcode (STRUCTOP_MPTR); } ; @@ -267,6 +274,14 @@ exp : exp '.' name write_exp_elt_opcode (STRUCTOP_STRUCT); } ; +exp : exp '.' qualified_name + { /* exp.type::name becomes exp.*(&type::name) */ + /* Note: this doesn't work if name is a + static member! FIXME */ + write_exp_elt_opcode (UNOP_ADDR); + write_exp_elt_opcode (STRUCTOP_MEMBER); } + ; + exp : exp '.' '*' exp { write_exp_elt_opcode (STRUCTOP_MEMBER); } ; @@ -549,7 +564,7 @@ variable: block COLONCOLON name write_exp_elt_opcode (OP_VAR_VALUE); } ; -variable: typebase COLONCOLON name +qualified_name: typebase COLONCOLON name { struct type *type = $1; if (TYPE_CODE (type) != TYPE_CODE_STRUCT @@ -565,6 +580,7 @@ variable: typebase COLONCOLON name | typebase COLONCOLON '~' name { struct type *type = $1; + struct stoken tmp_token; if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) error ("`%s' is not defined as an aggregate type.", @@ -574,12 +590,19 @@ variable: typebase COLONCOLON name error ("invalid destructor `%s::~%s'", type_name_no_tag (type), $4.ptr); + tmp_token.ptr = (char*) alloca ($4.length + 2); + tmp_token.length = $4.length + 1; + tmp_token.ptr[0] = '~'; + memcpy (tmp_token.ptr+1, $4.ptr, $4.length); + tmp_token.ptr[tmp_token.length] = 0; write_exp_elt_opcode (OP_SCOPE); write_exp_elt_type (type); - write_exp_string ($4); + write_exp_string (tmp_token); write_exp_elt_opcode (OP_SCOPE); - write_exp_elt_opcode (UNOP_LOGNOT); } + ; + +variable: qualified_name | COLONCOLON name { char *name = copy_name ($2); diff --git a/gdb/eval.c b/gdb/eval.c index aff3a3a1c1..c4ba5abb43 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -17,15 +17,45 @@ 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 "symtab.h" +#include "gdbtypes.h" #include "value.h" #include "expression.h" #include "target.h" #include "frame.h" -#define NULL_TYPE ((struct type *)0) +/* Values of NOSIDE argument to eval_subexp. */ +enum noside +{ EVAL_NORMAL, + EVAL_SKIP, /* Only effect is to increment pos. */ + EVAL_AVOID_SIDE_EFFECTS /* Don't modify any variables or + call any functions. The value + returned will have the correct + type, and will have an + approximately correct lvalue + type (inaccuracy: anything that is + listed as being in a register in + the function in which it was + declared will be lval_register). */ +}; + +/* Prototypes for local functions. */ + +static value +evaluate_subexp_for_sizeof PARAMS ((struct expression *, int *)); + +static value +evaluate_subexp_with_coercion PARAMS ((struct expression *, int *, + enum noside)); + +static value +evaluate_subexp_for_address PARAMS ((struct expression *, int *, + enum noside)); + +static value +evaluate_subexp PARAMS ((struct type *, struct expression *, int *, + enum noside)); /* Parse the string EXP as a C expression, evaluate it, @@ -37,8 +67,8 @@ parse_and_eval_address (exp) { struct expression *expr = parse_expression (exp); register CORE_ADDR addr; - register struct cleanup *old_chain - = make_cleanup (free_current_contents, &expr); + register struct cleanup *old_chain = + make_cleanup (free_current_contents, &expr); addr = value_as_pointer (evaluate_expression (expr)); do_cleanups (old_chain); @@ -54,8 +84,8 @@ parse_and_eval_address_1 (expptr) { struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0); register CORE_ADDR addr; - register struct cleanup *old_chain - = make_cleanup (free_current_contents, &expr); + register struct cleanup *old_chain = + make_cleanup (free_current_contents, &expr); addr = value_as_pointer (evaluate_expression (expr)); do_cleanups (old_chain); @@ -104,21 +134,6 @@ static value evaluate_subexp_for_address (); static value evaluate_subexp_for_sizeof (); static value evaluate_subexp_with_coercion (); -/* Values of NOSIDE argument to eval_subexp. */ -enum noside -{ EVAL_NORMAL, - EVAL_SKIP, /* Only effect is to increment pos. */ - EVAL_AVOID_SIDE_EFFECTS /* Don't modify any variables or - call any functions. The value - returned will have the correct - type, and will have an - approximately correct lvalue - type (inaccuracy: anything that is - listed as being in a register in - the function in which it was - declared will be lval_register). */ -}; - value evaluate_expression (exp) struct expression *exp; @@ -149,6 +164,7 @@ evaluate_subexp (expect_type, exp, pos, noside) int tem; register int pc, pc2, oldpos; register value arg1, arg2, arg3; + struct type *type; int nargs; value *argvec; @@ -161,8 +177,10 @@ evaluate_subexp (expect_type, exp, pos, noside) tem = strlen (&exp->elts[pc + 2].string); (*pos) += 3 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); - arg1 = value_static_field (exp->elts[pc + 1].type, - &exp->elts[pc + 2].string, -1); + arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type, + exp->elts[pc + 1].type, + &exp->elts[pc + 2].string, + expect_type); if (arg1 == NULL) error ("There is no field named %s", &exp->elts[pc + 2].string); return arg1; @@ -448,35 +466,28 @@ evaluate_subexp (expect_type, exp, pos, noside) case STRUCTOP_MEMBER: arg1 = evaluate_subexp_for_address (exp, pos, noside); - arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); - if (noside == EVAL_SKIP) - goto nosideret; - /* Now, convert these values to an address. */ - if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR - || ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) - != TYPE_CODE_MEMBER) - && (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) - != TYPE_CODE_METHOD))) - error ("non-pointer-to-member value used in pointer-to-member construct"); - arg3 = value_from_longest ( - lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))), - value_as_long (arg1) + value_as_long (arg2)); - return value_ind (arg3); - + goto handle_pointer_to_member; case STRUCTOP_MPTR: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + handle_pointer_to_member: arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; + if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR) + goto bad_pointer_to_member; + type = TYPE_TARGET_TYPE (VALUE_TYPE (arg2)); + 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. */ - if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR - || (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER - && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD)) - error ("non-pointer-to-member value used in pointer-to-member construct"); - arg3 = value_from_longest ( - lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))), - value_as_long (arg1) + value_as_long (arg2)); + arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)), + arg1); + arg3 = value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + value_as_long (arg1) + value_as_long (arg2)); return value_ind (arg3); + bad_pointer_to_member: + error("non-pointer-to-member value used in pointer-to-member construct"); case BINOP_ASSIGN: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); @@ -732,10 +743,6 @@ evaluate_subexp (expect_type, exp, pos, noside) /* C++: check for and handle destructor names. */ op = exp->elts[*pos].opcode; - /* FIXME-tiemann: this is a cop-out. */ - if (op == OP_SCOPE) - error ("destructor in eval"); - arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; @@ -795,19 +802,7 @@ evaluate_subexp (expect_type, exp, pos, noside) goto nosideret; } - if (op == OP_SCOPE) - { - char *name = &exp->elts[pc+3].string; - int temm = strlen (name); - struct type *domain = exp->elts[pc+2].type; - (*pos) += 2 + (temm + sizeof (union exp_element)) / sizeof (union exp_element); - arg1 = value_struct_elt_for_address (domain, expect_type, name); - if (arg1) - return arg1; - error ("no field `%s' in structure", name); - } - else - return evaluate_subexp_for_address (exp, pos, noside); + return evaluate_subexp_for_address (exp, pos, noside); case UNOP_SIZEOF: if (noside == EVAL_SKIP) diff --git a/gdb/valops.c b/gdb/valops.c index 83d6ec89c9..1213e9ed18 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -17,9 +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 "symtab.h" +#include "gdbtypes.h" #include "value.h" #include "frame.h" #include "inferior.h" @@ -29,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, @@ -238,7 +257,7 @@ 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); + (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), @@ -450,7 +469,6 @@ value value_addr (arg1) value arg1; { - extern value value_copy (); struct type *type = VALUE_TYPE (arg1); if (TYPE_CODE (type) == TYPE_CODE_REF) { @@ -543,7 +561,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; @@ -588,7 +606,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; @@ -599,7 +617,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; @@ -941,13 +959,13 @@ 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\"."); } @@ -988,9 +1006,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; @@ -1016,10 +1045,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, @@ -1076,23 +1103,23 @@ search_struct_method (name, arg1, args, offset, static_memfuncp, type) for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) { - value v; + value v, v2; + 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) error ("virtual baseclass botch"); - v = search_struct_method (name, v2, args, 0, - static_memfuncp, TYPE_BASECLASS (type, i)); - if (v) return v; - else continue; + base_offset = 0; } - - v = search_struct_method (name, arg1, args, - TYPE_BASECLASS_BITPOS (type, i) / 8, + else + { + v2 = arg1; + base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8; + } + v = search_struct_method (name, v2, args, base_offset, static_memfuncp, TYPE_BASECLASS (type, i)); if (v) return v; } @@ -1234,7 +1261,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; @@ -1272,7 +1299,7 @@ check_field_in (type, name) int check_field (arg1, name) - register const value arg1; + register value arg1; const char *name; { register struct type *t; @@ -1296,70 +1323,56 @@ check_field (arg1, name) return check_field_in (t, name); } -/* C++: Given an aggregate type DOMAIN, and a member name NAME, +/* 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". This function is only used - to resolve user expressions of the form "&class::member". */ + "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, curtype, name, intype) + struct type *domain, *curtype, *intype; 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 && TYPE_CODE (t) != TYPE_CODE_UNION) - error ("Internal error: non-aggregate type to value_struct_elt_for_address"); + error ("Internal error: non-aggregate type to value_struct_elt_for_reference"); - baseclass = t; - - 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)), + (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)) @@ -1371,55 +1384,59 @@ value_struct_elt_for_address (domain, intype, name) 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; - - 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_pointer_type ( - lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), - baseclass)), - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); - } - 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; + 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)), + (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); + } + else + { + struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), + 0, VAR_NAMESPACE, 0, NULL); + 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; } } } - if (TYPE_N_BASECLASSES (t) == 0) - break; - - t = TYPE_BASECLASS (t, 0); + for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--) + { + v = value_struct_elt_for_reference (domain, + TYPE_BASECLASS (t, i), + name, + intype); + if (v) + return v; } return 0; } diff --git a/gdb/value.h b/gdb/value.h index a6840d17f7..7333578b27 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #if !defined (VALUE_H) #define VALUE_H 1 + /* * The structure which defines the type of a value. It should never * be possible for a program lval value to survive over a call to the inferior @@ -120,7 +121,9 @@ typedef struct value *value; #define VALUE_CONTENTS_RAW(val) ((char *) (val)->aligner.contents) #define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\ VALUE_CONTENTS_RAW(val)) -extern int value_fetch_lazy (); +extern int +value_fetch_lazy PARAMS ((value val)); + #define VALUE_LVAL(val) (val)->lval #define VALUE_ADDRESS(val) (val)->location.address #define VALUE_INTERNALVAR(val) (val)->location.internalvar @@ -178,124 +181,287 @@ struct internalvar char *name; value value; }; + #include "symtab.h" -LONGEST value_as_long ( -#ifdef __STDC__ - value -#endif - ); -double value_as_double ( -#ifdef __STDC__ - value -#endif - ); -CORE_ADDR value_as_pointer ( -#ifdef __STDC__ - value -#endif - ); -LONGEST unpack_long ( -#ifdef __STDC__ - struct type *, char * -#endif - ); -double unpack_double ( -#ifdef __STDC__ - struct type *, char *, int * -#endif - ); -CORE_ADDR unpack_pointer ( -#ifdef __STDC__ - struct type *, char * -#endif - ); -long unpack_field_as_long (); -value value_from_longest (); -value value_from_double (); -value value_at (); -value value_at_lazy (); -value value_from_register (); -value value_of_variable (); -value value_of_register (); -value read_var_value (); -value locate_var_value (); -value allocate_value (); -value allocate_repeat_value (); -value value_mark (); -void value_free_to_mark (); -value value_string (); +#include "gdbtypes.h" +#include "expression.h" -value value_binop (); -value value_add (); -value value_sub (); -value value_coerce_array (); -value value_coerce_function (); -value value_ind (); -value value_addr (); -value value_assign (); -value value_neg (); -value value_lognot (); -value value_struct_elt (), value_struct_elt_for_address (); -value value_field (), value_primitive_field (); -value value_cast (); -value value_zero (); -value value_repeat (); -value value_subscript (); -value value_from_vtable_info (); +#ifdef __STDC__ +struct frame_info; +#endif -value value_being_returned (); -int using_struct_return (); -void set_return_value (); +extern void +print_address_demangle PARAMS ((CORE_ADDR, FILE *, int)); -value evaluate_expression (); -value evaluate_type (); -value parse_and_eval (); -value parse_to_comma_and_eval (); -struct type *parse_and_eval_type (); -extern CORE_ADDR parse_and_eval_address (); -extern CORE_ADDR parse_and_eval_address_1 (); +extern LONGEST +value_as_long PARAMS ((value val)); -value access_value_history (); -value value_of_internalvar (); -void set_internalvar (); -void set_internalvar_component (); -struct internalvar *lookup_internalvar (); +extern double +value_as_double PARAMS ((value val)); -int value_equal (); -int value_less (); -int value_zerop (); +extern CORE_ADDR +value_as_pointer PARAMS ((value val)); + +extern LONGEST +unpack_long PARAMS ((struct type *type, char *valaddr)); + +extern double +unpack_double PARAMS ((struct type *type, char *valaddr, int *invp)); + +extern CORE_ADDR +unpack_pointer PARAMS ((struct type *type, char *valaddr)); + +extern long +unpack_field_as_long PARAMS ((struct type *type, char *valaddr, + int fieldno)); + +extern value +value_from_longest PARAMS ((struct type *type, LONGEST num)); + +extern value +value_from_double PARAMS ((struct type *type, double num)); + +extern value +value_at PARAMS ((struct type *type, CORE_ADDR addr)); + +extern value +value_at_lazy PARAMS ((struct type *type, CORE_ADDR addr)); + +/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ +extern value +value_from_register PARAMS ((struct type *type, int regnum, + struct frame_info * frame)); + +extern value +value_of_variable PARAMS ((struct symbol *var)); + +extern value +value_of_register PARAMS ((int regnum)); + +/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ +extern value +read_var_value PARAMS ((struct symbol *var, struct frame_info *frame)); + +/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ +extern value +locate_var_value PARAMS ((struct symbol *var, struct frame_info *frame)); + +extern value +allocate_value PARAMS ((struct type *type)); + +extern value +allocate_repeat_value PARAMS ((struct type *type, int count)); + +extern value +value_mark PARAMS ((void)); + +extern void +value_free_to_mark PARAMS ((value mark)); + +extern value +value_string PARAMS ((char *ptr, int len)); + +extern value +value_binop PARAMS ((value arg1, value arg2, enum exp_opcode op)); + +extern value +value_add PARAMS ((value arg1, value arg2)); + +extern value +value_sub PARAMS ((value arg1, value arg2)); + +extern value +value_coerce_array PARAMS ((value arg1)); + +extern value +value_coerce_function PARAMS ((value arg1)); + +extern value +value_ind PARAMS ((value arg1)); + +extern value +value_addr PARAMS ((value arg1)); + +extern value +value_assign PARAMS ((value toval, value fromval)); + +extern value +value_neg PARAMS ((value arg1)); + +extern value +value_lognot PARAMS ((value arg1)); + +extern value +value_struct_elt PARAMS ((value *argp, value *args, char *name, + int *static_memfuncp, char *err)); + +extern value +value_struct_elt_for_reference PARAMS ((struct type *domain, + struct type *curtype, + char *name, + struct type *intype)); + +extern value +value_field PARAMS ((value arg1, int fieldno)); + +extern value +value_primitive_field PARAMS ((value arg1, int offset, int fieldno, + struct type *arg_type)); + +extern value +value_cast PARAMS ((struct type *type, value arg2)); + +extern value +value_zero PARAMS ((struct type *type, enum lval_type lv)); + +extern value +value_repeat PARAMS ((value arg1, int count)); + +extern value +value_subscript PARAMS ((value array, value idx)); + +extern value +value_from_vtable_info PARAMS ((value arg, struct type *type)); + +extern value +value_being_returned PARAMS ((struct type *valtype, + char retbuf[REGISTER_BYTES], + int struct_return)); + +extern int +using_struct_return PARAMS ((value function, CORE_ADDR funcaddr, + struct type *value_type, int gcc_p)); + +extern void +set_return_value PARAMS ((value val)); + +extern value +evaluate_expression PARAMS ((struct expression *exp)); + +extern value +evaluate_type PARAMS ((struct expression *exp)); + +extern value +parse_and_eval PARAMS ((char *exp)); + +extern value +parse_to_comma_and_eval PARAMS ((char **expp)); + +extern struct type * +parse_and_eval_type PARAMS ((char *p, int length)); + +extern CORE_ADDR +parse_and_eval_address PARAMS ((char *exp)); + +extern CORE_ADDR +parse_and_eval_address_1 PARAMS ((char **expptr)); + +extern value +access_value_history PARAMS ((int num)); + +extern value +value_of_internalvar PARAMS ((struct internalvar *var)); + +extern void +set_internalvar PARAMS ((struct internalvar *var, value val)); + +extern void +set_internalvar_component PARAMS ((struct internalvar *var, int offset, + int bitpos, int bitsize, + value newvalue)); + +extern struct internalvar * +lookup_internalvar PARAMS ((char *name)); + +extern int +value_equal PARAMS ((value arg1, value arg2)); + +extern int +value_less PARAMS ((value arg1, value arg2)); + +extern int +value_zerop PARAMS ((value arg1)); /* C++ */ -value value_of_this (); -value value_static_field (); -value value_x_binop (); -value value_x_unop (); -value value_fn_field (); -value value_virtual_fn_field (); -int binop_user_defined_p (); -int unop_user_defined_p (); -int typecmp (); -void fill_in_vptr_fieldno (); -int destructor_name_p (); + +extern value +value_of_this PARAMS ((int complain)); + +extern value +value_x_binop PARAMS ((value arg1, value arg2, enum exp_opcode op, + enum exp_opcode otherop)); + +extern value +value_x_unop PARAMS ((value arg1, enum exp_opcode op)); + +extern value +value_fn_field PARAMS ((struct fn_field *f, int j)); + +extern value +value_virtual_fn_field PARAMS ((value arg1, struct fn_field *f, int j, + struct type *type)); + +extern int +binop_user_defined_p PARAMS ((enum exp_opcode op, value arg1, value arg2)); + +extern int +unop_user_defined_p PARAMS ((enum exp_opcode op, value arg1)); + +extern int +typecmp PARAMS ((int staticp, struct type *t1[], value t2[])); + +extern int +destructor_name_p PARAMS ((const char *name, const struct type *type)); #define value_free(val) free (val) -void free_all_values (); -void release_value (); -int record_latest_value (); -void registers_changed (); -void read_register_bytes (); -void write_register_bytes (); -void read_register_gen (); -CORE_ADDR read_register (); -void write_register (); -void supply_register (); -void get_saved_register (); +extern void +free_all_values PARAMS ((void)); -void modify_field (); -void type_print (); -void type_print_1 (); +extern void +release_value PARAMS ((value val)); + +extern int +record_latest_value PARAMS ((value val)); + +extern void +registers_changed PARAMS ((void)); + +extern void +read_register_bytes PARAMS ((int regbyte, char *myaddr, int len)); + +extern void +write_register_bytes PARAMS ((int regbyte, char *myaddr, int len)); + +extern void +read_register_gen PARAMS ((int regno, char *myaddr)); + +extern CORE_ADDR +read_register PARAMS ((int regno)); + +extern void +write_register PARAMS ((int regno, int val)); + +extern void +supply_register PARAMS ((int regno, char *val)); + +/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ +extern void +get_saved_register PARAMS ((char *raw_buffer, int *optimized, + CORE_ADDR *addrp, struct frame_info *frame, + int regnum, enum lval_type *lval)); + +extern void +modify_field PARAMS ((char *addr, int fieldval, int bitpos, int bitsize)); + +extern void +type_print PARAMS ((struct type *type, char *varstring, FILE *stream, + int show)); + +extern void +type_print_1 PARAMS ((struct type *type, char *varstring, FILE *stream, + int show, int level)); /* Possibilities for prettyprint parameters to routines which print things. */ @@ -306,17 +472,53 @@ enum val_prettyprint { Val_pretty_default }; -char *baseclass_addr (); -void print_floating (); -int value_print (); -int val_print (); -void print_variable_value (); -void typedef_print (); -char *internalvar_name (); -void clear_value_history (); -void clear_internalvars (); +extern char * +baseclass_addr PARAMS ((struct type *type, int index, char *valaddr, + value *valuep, int *errp)); + +extern void +print_floating PARAMS ((char *valaddr, struct type *type, FILE *stream)); + +extern int +value_print PARAMS ((value val, FILE *stream, int format, + enum val_prettyprint pretty)); + +extern int +val_print PARAMS ((struct type *type, char *valaddr, CORE_ADDR address, + FILE *stream, int format, int deref_ref, + int recurse, enum val_prettyprint pretty)); + +/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ +extern void +print_variable_value PARAMS ((struct symbol *var, struct frame_info *frame, + FILE *stream)); extern value -call_function_by_hand PARAMS ((value, int value *)); +value_arg_coerce PARAMS ((value)); -#endif /* value.h not already included. */ +extern int +check_field PARAMS ((value, const char *)); + +extern void +typedef_print PARAMS ((struct type *type, struct symbol *new, FILE *stream)); + +extern char * +internalvar_name PARAMS ((struct internalvar *var)); + +extern void +clear_value_history PARAMS ((void)); + +extern void +clear_internalvars PARAMS ((void)); + +/* From values.c */ + +extern value +value_copy PARAMS ((value)); + +/* From valops.c */ + +extern value +call_function_by_hand PARAMS ((value, int, value *)); + +#endif /* !defined (VALUE_H) */ diff --git a/gdb/values.c b/gdb/values.c index bb5fa68c29..3dc1accff4 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1101,81 +1101,6 @@ value_from_vtable_info (arg, type) return value_headof (arg, 0, type); } -/* The value of a static class member does not depend - on its instance, only on its type. If FIELDNO >= 0, - then fieldno is a valid field number and is used directly. - Otherwise, FIELDNAME is the name of the field we are - searching for. If it is not a static field name, an - error is signaled. TYPE is the type in which we look for the - static field member. - - Return zero if we couldn't find anything; the caller may signal - an error in that case. */ - -value -value_static_field (type, fieldname, fieldno) - register struct type *type; - char *fieldname; - register int fieldno; -{ - register value v; - struct symbol *sym; - char *phys_name; - - if (fieldno < 0) - { - char **physnames; - struct symbol **sym_arr; - /* Look for static field. */ - int i; - for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) - if (! strcmp (TYPE_FIELD_NAME (type, i), fieldname)) - { - if (TYPE_FIELD_STATIC (type, i)) - { - fieldno = i; - goto found; - } - else - error ("field `%s' is not static", fieldname); - } - for (; i > 0; i--) - { - v = value_static_field (TYPE_BASECLASS (type, i), fieldname, -1); - if (v != 0) - return v; - } - - sym_arr = (struct symbol **) - alloca(TYPE_NFN_FIELDS_TOTAL (type) * sizeof(struct symbol*)); - physnames = (char **) - alloca (TYPE_NFN_FIELDS_TOTAL (type) * sizeof(char*)); - /* Note: This does duplicate work, since find_methods does a - recursive search *and* so does value_static_field. FIXME */ - i = find_methods (type, fieldname, physnames, sym_arr); - if (i > 1) - error ("Cannot get value of overloaded method \"%s\"", fieldname); - else if (i) - { - struct symbol *sym = sym_arr[0]; - value val = read_var_value (sym, (FRAME) 0); - if (val == 0) - error ("Address of method \"%s\" is unknown (possibly inlined).", - fieldname); - return val; - } - error("there is no field named %s", fieldname); - } - - found: - phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); - 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); - - type = TYPE_FIELD_TYPE (type, fieldno); - return value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); -} - /* Compute the address of the baseclass which is the INDEXth baseclass of class TYPE. The TYPE base of the object is at VALADDR. @@ -1343,7 +1268,8 @@ value_from_longest (type, num) /* FIXME, we assume that pointers have the same form and byte order as integers, and that all pointers have the same form. */ if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM || - code == TYPE_CODE_CHAR || code == TYPE_CODE_PTR) + code == TYPE_CODE_CHAR || code == TYPE_CODE_PTR || + code == TYPE_CODE_REF) { if (len == sizeof (char)) * (char *) VALUE_CONTENTS_RAW (val) = num;