More C++ improvements (pointers to members, qualified names). See ChangeLog.

This commit is contained in:
Per Bothner 1992-03-20 21:57:17 +00:00
parent 52963fb7e9
commit 01be69139e
6 changed files with 569 additions and 374 deletions

View File

@ -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) Thu Mar 19 13:54:11 1992 Fred Fish (fnf@cygnus.com)
* coffread.c, mipsread.c, xcoffread.c, coffread.c, dbxread.c, * coffread.c, mipsread.c, xcoffread.c, coffread.c, dbxread.c,

View File

@ -120,7 +120,7 @@ static int
parse_number PARAMS ((char *, int, int, YYSTYPE *)); parse_number PARAMS ((char *, int, int, YYSTYPE *));
%} %}
%type <voidval> exp exp1 type_exp start variable %type <voidval> exp exp1 type_exp start variable qualified_name
%type <tval> type typebase %type <tval> type typebase
%type <tvec> nonempty_typelist %type <tvec> nonempty_typelist
/* %type <bval> block */ /* %type <bval> block */
@ -257,6 +257,13 @@ exp : exp ARROW name
write_exp_elt_opcode (STRUCTOP_PTR); } 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 exp : exp ARROW '*' exp
{ write_exp_elt_opcode (STRUCTOP_MPTR); } { write_exp_elt_opcode (STRUCTOP_MPTR); }
; ;
@ -267,6 +274,14 @@ exp : exp '.' name
write_exp_elt_opcode (STRUCTOP_STRUCT); } 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 exp : exp '.' '*' exp
{ write_exp_elt_opcode (STRUCTOP_MEMBER); } { write_exp_elt_opcode (STRUCTOP_MEMBER); }
; ;
@ -549,7 +564,7 @@ variable: block COLONCOLON name
write_exp_elt_opcode (OP_VAR_VALUE); } write_exp_elt_opcode (OP_VAR_VALUE); }
; ;
variable: typebase COLONCOLON name qualified_name: typebase COLONCOLON name
{ {
struct type *type = $1; struct type *type = $1;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT if (TYPE_CODE (type) != TYPE_CODE_STRUCT
@ -565,6 +580,7 @@ variable: typebase COLONCOLON name
| typebase COLONCOLON '~' name | typebase COLONCOLON '~' name
{ {
struct type *type = $1; struct type *type = $1;
struct stoken tmp_token;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION) && TYPE_CODE (type) != TYPE_CODE_UNION)
error ("`%s' is not defined as an aggregate type.", error ("`%s' is not defined as an aggregate type.",
@ -574,12 +590,19 @@ variable: typebase COLONCOLON name
error ("invalid destructor `%s::~%s'", error ("invalid destructor `%s::~%s'",
type_name_no_tag (type), $4.ptr); 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_opcode (OP_SCOPE);
write_exp_elt_type (type); write_exp_elt_type (type);
write_exp_string ($4); write_exp_string (tmp_token);
write_exp_elt_opcode (OP_SCOPE); write_exp_elt_opcode (OP_SCOPE);
write_exp_elt_opcode (UNOP_LOGNOT);
} }
;
variable: qualified_name
| COLONCOLON name | COLONCOLON name
{ {
char *name = copy_name ($2); char *name = copy_name ($2);

View File

@ -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 along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h" #include "defs.h"
#include "symtab.h" #include "symtab.h"
#include "gdbtypes.h"
#include "value.h" #include "value.h"
#include "expression.h" #include "expression.h"
#include "target.h" #include "target.h"
#include "frame.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, /* 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); struct expression *expr = parse_expression (exp);
register CORE_ADDR addr; register CORE_ADDR addr;
register struct cleanup *old_chain register struct cleanup *old_chain =
= make_cleanup (free_current_contents, &expr); make_cleanup (free_current_contents, &expr);
addr = value_as_pointer (evaluate_expression (expr)); addr = value_as_pointer (evaluate_expression (expr));
do_cleanups (old_chain); 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); struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0);
register CORE_ADDR addr; register CORE_ADDR addr;
register struct cleanup *old_chain register struct cleanup *old_chain =
= make_cleanup (free_current_contents, &expr); make_cleanup (free_current_contents, &expr);
addr = value_as_pointer (evaluate_expression (expr)); addr = value_as_pointer (evaluate_expression (expr));
do_cleanups (old_chain); do_cleanups (old_chain);
@ -104,21 +134,6 @@ static value evaluate_subexp_for_address ();
static value evaluate_subexp_for_sizeof (); static value evaluate_subexp_for_sizeof ();
static value evaluate_subexp_with_coercion (); 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 value
evaluate_expression (exp) evaluate_expression (exp)
struct expression *exp; struct expression *exp;
@ -149,6 +164,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
int tem; int tem;
register int pc, pc2, oldpos; register int pc, pc2, oldpos;
register value arg1, arg2, arg3; register value arg1, arg2, arg3;
struct type *type;
int nargs; int nargs;
value *argvec; value *argvec;
@ -161,8 +177,10 @@ evaluate_subexp (expect_type, exp, pos, noside)
tem = strlen (&exp->elts[pc + 2].string); tem = strlen (&exp->elts[pc + 2].string);
(*pos) += 3 + ((tem + sizeof (union exp_element)) (*pos) += 3 + ((tem + sizeof (union exp_element))
/ sizeof (union exp_element)); / sizeof (union exp_element));
arg1 = value_static_field (exp->elts[pc + 1].type, arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
&exp->elts[pc + 2].string, -1); exp->elts[pc + 1].type,
&exp->elts[pc + 2].string,
expect_type);
if (arg1 == NULL) if (arg1 == NULL)
error ("There is no field named %s", &exp->elts[pc + 2].string); error ("There is no field named %s", &exp->elts[pc + 2].string);
return arg1; return arg1;
@ -448,35 +466,28 @@ evaluate_subexp (expect_type, exp, pos, noside)
case STRUCTOP_MEMBER: case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside); arg1 = evaluate_subexp_for_address (exp, pos, noside);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); goto handle_pointer_to_member;
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);
case STRUCTOP_MPTR: case STRUCTOP_MPTR:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
handle_pointer_to_member:
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP) if (noside == EVAL_SKIP)
goto nosideret; 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. */ /* Now, convert these values to an address. */
if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
|| (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER arg1);
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD)) arg3 = value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
error ("non-pointer-to-member value used in pointer-to-member construct"); value_as_long (arg1) + value_as_long (arg2));
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); return value_ind (arg3);
bad_pointer_to_member:
error("non-pointer-to-member value used in pointer-to-member construct");
case BINOP_ASSIGN: case BINOP_ASSIGN:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); 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. */ /* C++: check for and handle destructor names. */
op = exp->elts[*pos].opcode; 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); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP) if (noside == EVAL_SKIP)
goto nosideret; goto nosideret;
@ -795,19 +802,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
goto nosideret; goto nosideret;
} }
if (op == OP_SCOPE) return evaluate_subexp_for_address (exp, pos, noside);
{
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);
case UNOP_SIZEOF: case UNOP_SIZEOF:
if (noside == EVAL_SKIP) if (noside == EVAL_SKIP)

View File

@ -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 along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h" #include "defs.h"
#include "symtab.h" #include "symtab.h"
#include "gdbtypes.h"
#include "value.h" #include "value.h"
#include "frame.h" #include "frame.h"
#include "inferior.h" #include "inferior.h"
@ -29,7 +29,26 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <errno.h> #include <errno.h>
/* Local functions. */ /* 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. /* 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, 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 */ int v; /* FIXME, this won't work for large bitfields */
read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
&v, sizeof v); (char *) &v, sizeof v);
modify_field ((char *) &v, (int) value_as_long (fromval), modify_field ((char *) &v, (int) value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
@ -450,7 +469,6 @@ value
value_addr (arg1) value_addr (arg1)
value arg1; value arg1;
{ {
extern value value_copy ();
struct type *type = VALUE_TYPE (arg1); struct type *type = VALUE_TYPE (arg1);
if (TYPE_CODE (type) == TYPE_CODE_REF) if (TYPE_CODE (type) == TYPE_CODE_REF)
{ {
@ -543,7 +561,7 @@ push_bytes (sp, buffer, len)
/* Push onto the stack the specified value VALUE. */ /* Push onto the stack the specified value VALUE. */
CORE_ADDR static CORE_ADDR
value_push (sp, arg) value_push (sp, arg)
register CORE_ADDR sp; register CORE_ADDR sp;
value arg; value arg;
@ -588,7 +606,7 @@ value_arg_coerce (arg)
/* Push the value ARG, first coercing it as an argument /* Push the value ARG, first coercing it as an argument
to a C function. */ to a C function. */
CORE_ADDR static CORE_ADDR
value_arg_push (sp, arg) value_arg_push (sp, arg)
register CORE_ADDR sp; register CORE_ADDR sp;
value arg; value arg;
@ -599,7 +617,7 @@ value_arg_push (sp, arg)
/* Determine a function's address and its return type from its value. /* Determine a function's address and its return type from its value.
Calls error() if the function is not valid for calling. */ Calls error() if the function is not valid for calling. */
CORE_ADDR static CORE_ADDR
find_function_addr (function, retval_type) find_function_addr (function, retval_type)
value function; value function;
struct type **retval_type; struct type **retval_type;
@ -941,13 +959,13 @@ value_string (ptr, len)
} }
else else
{ {
register int j; struct minimal_symbol *msymbol;
j = lookup_misc_func ("malloc"); msymbol = lookup_minimal_symbol ("malloc", (struct objfile *) NULL);
if (j >= 0) if (msymbol != NULL)
val = value_from_longest ( val =
lookup_pointer_type (lookup_function_type ( value_from_longest (lookup_pointer_type (lookup_function_type (
lookup_pointer_type (builtin_type_char))), lookup_pointer_type (builtin_type_char))),
(LONGEST) misc_function_vector[j].address); (LONGEST) msymbol -> address);
else else
error ("String constants require the program to have a function \"malloc\"."); 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)) if (t_field_name && !strcmp (t_field_name, name))
{ {
value v = (TYPE_FIELD_STATIC (type, i) value v;
? value_static_field (type, name, i) if (TYPE_FIELD_STATIC (type, i))
: value_primitive_field (arg1, offset, i, type)); {
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) if (v == 0)
error("there is no field named %s", name); error("there is no field named %s", name);
return v; return v;
@ -1016,10 +1045,8 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
return v2; return v2;
v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i), v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i),
looking_for_baseclass); looking_for_baseclass);
if (v) return v;
else continue;
} }
if (found_baseclass) else if (found_baseclass)
v = value_primitive_field (arg1, offset, i, type); v = value_primitive_field (arg1, offset, i, type);
else else
v = search_struct_field (name, arg1, 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--) for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
{ {
value v; value v, v2;
int base_offset;
if (BASETYPE_VIA_VIRTUAL (type, i)) if (BASETYPE_VIA_VIRTUAL (type, i))
{ {
value v2;
baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset, baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset,
&v2, (int *)NULL); &v2, (int *)NULL);
if (v2 == 0) if (v2 == 0)
error ("virtual baseclass botch"); error ("virtual baseclass botch");
v = search_struct_method (name, v2, args, 0, base_offset = 0;
static_memfuncp, TYPE_BASECLASS (type, i));
if (v) return v;
else continue;
} }
else
v = search_struct_method (name, arg1, args, {
TYPE_BASECLASS_BITPOS (type, i) / 8, 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)); static_memfuncp, TYPE_BASECLASS (type, i));
if (v) return v; if (v) return v;
} }
@ -1234,7 +1261,7 @@ destructor_name_p (name, type)
static int static int
check_field_in (type, name) check_field_in (type, name)
register struct type *type; register struct type *type;
char *name; const char *name;
{ {
register int i; register int i;
@ -1272,7 +1299,7 @@ check_field_in (type, name)
int int
check_field (arg1, name) check_field (arg1, name)
register const value arg1; register value arg1;
const char *name; const char *name;
{ {
register struct type *t; register struct type *t;
@ -1296,70 +1323,56 @@ check_field (arg1, name)
return check_field_in (t, 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" return the address of this member as a "pointer to member"
type. If INTYPE is non-null, then it will be the type type. If INTYPE is non-null, then it will be the type
of the member we are looking for. This will help us resolve of the member we are looking for. This will help us resolve
"pointers to member functions". This function is only used "pointers to member functions". This function is used
to resolve user expressions of the form "&class::member". */ to resolve user expressions of the form "DOMAIN::NAME". */
value value
value_struct_elt_for_address (domain, intype, name) value_struct_elt_for_reference (domain, curtype, name, intype)
struct type *domain, *intype; struct type *domain, *curtype, *intype;
char *name; char *name;
{ {
register struct type *t = domain; register struct type *t = curtype;
register int i; register int i;
value v; 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) && 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; for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
while (t)
{ {
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 (TYPE_FIELD_STATIC (t, i))
if (t_field_name && !strcmp (t_field_name, name))
{ {
if (TYPE_FIELD_STATIC (t, i)) char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i);
{ struct symbol *sym =
char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i); lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
struct symbol *sym = if (! sym)
lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); error (
if (! sym) "Internal error: could not find physical static variable named %s",
error ( phys_name);
"Internal error: could not find physical static variable named %s", return value_at (SYMBOL_TYPE (sym),
phys_name); (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
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));
} }
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 /* C++: If it was not found as a data field, then try to
return it as a pointer to a method. */ return it as a pointer to a method. */
t = baseclass;
/* Destructors are a special case. */ /* Destructors are a special case. */
if (destructor_name_p (name, t)) 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) while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
intype = TYPE_TARGET_TYPE (intype); 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); while (j--)
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); if (TYPE_FN_FIELD_TYPE (f, j) == intype)
break;
if (intype == 0 && j > 1) if (j < 0)
error ("non-unique member `%s' requires type instantiation", name); error ("no member function matches that type instantiation");
if (intype) }
{ else
while (j--) j = 0;
if (TYPE_FN_FIELD_TYPE (f, j) == intype)
break; if (TYPE_FN_FIELD_STUB (f, j))
if (j < 0) check_stub_method (t, i, j);
error ("no member function matches that type instantiation"); if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
} {
else return value_from_longest
j = 0; (lookup_reference_type
(lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
if (TYPE_FN_FIELD_STUB (f, j)) domain)),
check_stub_method (t, i, j); (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) }
{ else
return value_from_longest ( {
lookup_pointer_type ( struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), 0, VAR_NAMESPACE, 0, NULL);
baseclass)), v = read_var_value (s, 0);
(LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); #if 0
} VALUE_TYPE (v) = lookup_reference_type
else (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
{ domain));
struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), #endif
0, VAR_NAMESPACE, 0, NULL); return v;
v = locate_var_value (s, 0);
VALUE_TYPE (v) = lookup_pointer_type (
lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
baseclass));
return v;
} }
} }
} }
if (TYPE_N_BASECLASSES (t) == 0) for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
break; {
v = value_struct_elt_for_reference (domain,
t = TYPE_BASECLASS (t, 0); TYPE_BASECLASS (t, i),
name,
intype);
if (v)
return v;
} }
return 0; return 0;
} }

View File

@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (VALUE_H) #if !defined (VALUE_H)
#define VALUE_H 1 #define VALUE_H 1
/* /*
* The structure which defines the type of a value. It should never * 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 * 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_RAW(val) ((char *) (val)->aligner.contents)
#define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\ #define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\
VALUE_CONTENTS_RAW(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_LVAL(val) (val)->lval
#define VALUE_ADDRESS(val) (val)->location.address #define VALUE_ADDRESS(val) (val)->location.address
#define VALUE_INTERNALVAR(val) (val)->location.internalvar #define VALUE_INTERNALVAR(val) (val)->location.internalvar
@ -178,124 +181,287 @@ struct internalvar
char *name; char *name;
value value; value value;
}; };
#include "symtab.h" #include "symtab.h"
LONGEST value_as_long ( #include "gdbtypes.h"
#ifdef __STDC__ #include "expression.h"
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 ();
value value_binop (); #ifdef __STDC__
value value_add (); struct frame_info;
value value_sub (); #endif
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 ();
value value_being_returned (); extern void
int using_struct_return (); print_address_demangle PARAMS ((CORE_ADDR, FILE *, int));
void set_return_value ();
value evaluate_expression (); extern LONGEST
value evaluate_type (); value_as_long PARAMS ((value val));
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 ();
value access_value_history (); extern double
value value_of_internalvar (); value_as_double PARAMS ((value val));
void set_internalvar ();
void set_internalvar_component ();
struct internalvar *lookup_internalvar ();
int value_equal (); extern CORE_ADDR
int value_less (); value_as_pointer PARAMS ((value val));
int value_zerop ();
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++ */ /* C++ */
value value_of_this ();
value value_static_field (); extern value
value value_x_binop (); value_of_this PARAMS ((int complain));
value value_x_unop ();
value value_fn_field (); extern value
value value_virtual_fn_field (); value_x_binop PARAMS ((value arg1, value arg2, enum exp_opcode op,
int binop_user_defined_p (); enum exp_opcode otherop));
int unop_user_defined_p ();
int typecmp (); extern value
void fill_in_vptr_fieldno (); value_x_unop PARAMS ((value arg1, enum exp_opcode op));
int destructor_name_p ();
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) #define value_free(val) free (val)
void free_all_values ();
void release_value ();
int record_latest_value ();
void registers_changed (); extern void
void read_register_bytes (); free_all_values PARAMS ((void));
void write_register_bytes ();
void read_register_gen ();
CORE_ADDR read_register ();
void write_register ();
void supply_register ();
void get_saved_register ();
void modify_field (); extern void
void type_print (); release_value PARAMS ((value val));
void type_print_1 ();
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 /* Possibilities for prettyprint parameters to routines which print
things. */ things. */
@ -306,17 +472,53 @@ enum val_prettyprint {
Val_pretty_default Val_pretty_default
}; };
char *baseclass_addr (); extern char *
void print_floating (); baseclass_addr PARAMS ((struct type *type, int index, char *valaddr,
int value_print (); value *valuep, int *errp));
int val_print ();
void print_variable_value (); extern void
void typedef_print (); print_floating PARAMS ((char *valaddr, struct type *type, FILE *stream));
char *internalvar_name ();
void clear_value_history (); extern int
void clear_internalvars (); 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 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) */

View File

@ -1101,81 +1101,6 @@ value_from_vtable_info (arg, type)
return value_headof (arg, 0, 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 /* Compute the address of the baseclass which is
the INDEXth baseclass of class TYPE. The TYPE base the INDEXth baseclass of class TYPE. The TYPE base
of the object is at VALADDR. 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 /* FIXME, we assume that pointers have the same form and byte order as
integers, and that all pointers have the same form. */ integers, and that all pointers have the same form. */
if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM || 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)) if (len == sizeof (char))
* (char *) VALUE_CONTENTS_RAW (val) = num; * (char *) VALUE_CONTENTS_RAW (val) = num;