/* Perform non-arithmetic operations on values, for GDB.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcmd.h"
#include "regcache.h"
#include "cp-abi.h"
+#include "block.h"
#include <errno.h>
#include "gdb_string.h"
+#include "gdb_assert.h"
/* Flag indicating HP compilers were used; needed to correctly handle some
value operations with HP aCC code/runtime. */
extern int overload_debug;
/* Local functions. */
-static int typecmp (int staticp, struct type *t1[], struct value *t2[]);
+static int typecmp (int staticp, int varargs, int nargs,
+ struct field t1[], struct value *t2[]);
static CORE_ADDR find_function_addr (struct value *, struct type **);
static struct value *value_arg_coerce (struct value *, struct type *, int);
static struct value *cast_into_complex (struct type *, struct value *);
static struct fn_field *find_method_list (struct value ** argp, char *method,
- int offset, int *static_memfuncp,
+ int offset,
struct type *type, int *num_fns,
struct type **basetype,
int *boffset);
The default is to stop in the frame where the signal was received. */
int unwind_on_signal_p = 0;
-\f
+/* How you should pass arguments to a function depends on whether it
+ was defined in K&R style or prototype style. If you define a
+ function using the K&R syntax that takes a `float' argument, then
+ callers must pass that argument as a `double'. If you define the
+ function using the prototype syntax, then you must pass the
+ argument as a `float', with no promotion.
+
+ Unfortunately, on certain older platforms, the debug info doesn't
+ indicate reliably how each function was defined. A function type's
+ TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
+ defined in prototype style. When calling a function whose
+ TYPE_FLAG_PROTOTYPED flag is clear, GDB consults this flag to decide
+ what to do.
+
+ For modern targets, it is proper to assume that, if the prototype
+ flag is clear, that can be trusted: `float' arguments should be
+ promoted to `double'. For some older targets, if the prototype
+ flag is clear, that doesn't tell us anything. The default is to
+ trust the debug information; the user can override this behavior
+ with "set coerce-float-to-double 0". */
+
+static int coerce_float_to_double;
+\f
/* Find the address of function name NAME in the inferior. */
struct value *
-find_function_in_inferior (char *name)
+find_function_in_inferior (const char *name)
{
register struct symbol *sym;
sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
value_allocate_space_in_inferior (int len)
{
struct value *blocklen;
- struct value *val = find_function_in_inferior ("malloc");
+ struct value *val = find_function_in_inferior (NAME_OF_MALLOC);
blocklen = value_from_longest (builtin_type_int, (LONGEST) len);
val = call_function_by_hand (val, 1, &blocklen);
value_zero (t1, not_lval), 0, t1, 1);
if (v)
{
- struct value *v2 = value_ind (arg2);
- VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v)
- + VALUE_OFFSET (v);
-
- /* JYG: adjust the new pointer value and
- embedded offset. */
- v2->aligner.contents[0] -= VALUE_EMBEDDED_OFFSET (v);
- VALUE_EMBEDDED_OFFSET (v2) = 0;
-
- v2 = value_addr (v2);
- VALUE_TYPE (v2) = type;
- return v2;
+ CORE_ADDR addr2 = value_as_address (arg2);
+ addr2 -= (VALUE_ADDRESS (v)
+ + VALUE_OFFSET (v)
+ + VALUE_EMBEDDED_OFFSET (v));
+ return value_from_pointer (type, addr2);
}
}
}
VALUE_POINTED_TO_OFFSET (arg2) = 0; /* pai: chk_val */
return arg2;
}
- else if (chill_varying_type (type))
- {
- struct type *range1, *range2, *eltype1, *eltype2;
- struct value *val;
- int count1, count2;
- LONGEST low_bound, high_bound;
- char *valaddr, *valaddr_data;
- /* For lint warning about eltype2 possibly uninitialized: */
- eltype2 = NULL;
- if (code2 == TYPE_CODE_BITSTRING)
- error ("not implemented: converting bitstring to varying type");
- if ((code2 != TYPE_CODE_ARRAY && code2 != TYPE_CODE_STRING)
- || (eltype1 = check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 1))),
- eltype2 = check_typedef (TYPE_TARGET_TYPE (type2)),
- (TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2)
- /* || TYPE_CODE (eltype1) != TYPE_CODE (eltype2) */ )))
- error ("Invalid conversion to varying type");
- range1 = TYPE_FIELD_TYPE (TYPE_FIELD_TYPE (type, 1), 0);
- range2 = TYPE_FIELD_TYPE (type2, 0);
- if (get_discrete_bounds (range1, &low_bound, &high_bound) < 0)
- count1 = -1;
- else
- count1 = high_bound - low_bound + 1;
- if (get_discrete_bounds (range2, &low_bound, &high_bound) < 0)
- count1 = -1, count2 = 0; /* To force error before */
- else
- count2 = high_bound - low_bound + 1;
- if (count2 > count1)
- error ("target varying type is too small");
- val = allocate_value (type);
- valaddr = VALUE_CONTENTS_RAW (val);
- valaddr_data = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
- /* Set val's __var_length field to count2. */
- store_signed_integer (valaddr, TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)),
- count2);
- /* Set the __var_data field to count2 elements copied from arg2. */
- memcpy (valaddr_data, VALUE_CONTENTS (arg2),
- count2 * TYPE_LENGTH (eltype2));
- /* Zero the rest of the __var_data field of val. */
- memset (valaddr_data + count2 * TYPE_LENGTH (eltype2), '\0',
- (count1 - count2) * TYPE_LENGTH (eltype2));
- return val;
- }
else if (VALUE_LVAL (arg2) == lval_memory)
{
return value_at_lazy (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2),
struct value *val;
char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
int use_buffer = 0;
+ struct frame_id old_frame;
if (!toval->modifiable)
error ("Left operand of assignment is not a modifiable lvalue.");
if (VALUE_REGNO (toval) >= 0)
{
int regno = VALUE_REGNO (toval);
- if (REGISTER_CONVERTIBLE (regno))
+ if (CONVERT_REGISTER_P (regno))
{
struct type *fromtype = check_typedef (VALUE_TYPE (fromval));
- REGISTER_CONVERT_TO_RAW (fromtype, regno,
- VALUE_CONTENTS (fromval), raw_buffer);
+ VALUE_TO_REGISTER (fromtype, regno, VALUE_CONTENTS (fromval), raw_buffer);
use_buffer = REGISTER_RAW_SIZE (regno);
}
}
+ /* Since modifying a register can trash the frame chain, and modifying memory
+ can trash the frame cache, we save the old frame and then restore the new
+ frame afterwards. */
+ old_frame = get_frame_id (deprecated_selected_frame);
+
switch (VALUE_LVAL (toval))
{
case lval_internalvar:
if (changed_len > (int) sizeof (LONGEST))
error ("Can't handle bitfields which don't fit in a %d bit word.",
- sizeof (LONGEST) * HOST_CHAR_BIT);
+ (int) sizeof (LONGEST) * HOST_CHAR_BIT);
read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
buffer, changed_len);
write_memory (changed_addr, dest_buffer, changed_len);
if (memory_changed_hook)
memory_changed_hook (changed_addr, changed_len);
+ target_changed_event ();
}
break;
- case lval_register:
- if (VALUE_BITSIZE (toval))
- {
- char buffer[sizeof (LONGEST)];
- int len =
- REGISTER_RAW_SIZE (VALUE_REGNO (toval)) - VALUE_OFFSET (toval);
-
- if (len > (int) sizeof (LONGEST))
- error ("Can't handle bitfields in registers larger than %d bits.",
- sizeof (LONGEST) * HOST_CHAR_BIT);
-
- if (VALUE_BITPOS (toval) + VALUE_BITSIZE (toval)
- > len * HOST_CHAR_BIT)
- /* Getting this right would involve being very careful about
- byte order. */
- error ("Can't assign to bitfields that cross register "
- "boundaries.");
-
- read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- buffer, len);
- modify_field (buffer, value_as_long (fromval),
- VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
- write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- buffer, len);
- }
- else if (use_buffer)
- write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- raw_buffer, use_buffer);
- else
- {
- /* Do any conversion necessary when storing this type to more
- than one register. */
-#ifdef REGISTER_CONVERT_FROM_TYPE
- memcpy (raw_buffer, VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
- REGISTER_CONVERT_FROM_TYPE (VALUE_REGNO (toval), type, raw_buffer);
- write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- raw_buffer, TYPE_LENGTH (type));
-#else
- write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
-#endif
- }
- /* Assigning to the stack pointer, frame pointer, and other
- (architecture and calling convention specific) registers may
- cause the frame cache to be out of date. We just do this
- on all assignments to registers for simplicity; I doubt the slowdown
- matters. */
- reinit_frame_cache ();
- break;
-
case lval_reg_frame_relative:
+ case lval_register:
{
/* value is stored in a series of registers in the frame
specified by the structure. Copy that value out, modify
it, and copy it back in. */
- int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));
- int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));
- int byte_offset = VALUE_OFFSET (toval) % reg_size;
- int reg_offset = VALUE_OFFSET (toval) / reg_size;
int amount_copied;
-
- /* Make the buffer large enough in all cases. */
- /* FIXME (alloca): Not safe for very large data types. */
- char *buffer = (char *) alloca (amount_to_copy
- + sizeof (LONGEST)
- + MAX_REGISTER_RAW_SIZE);
-
+ int amount_to_copy;
+ char *buffer;
+ int value_reg;
+ int reg_offset;
+ int byte_offset;
int regno;
struct frame_info *frame;
/* Figure out which frame this is in currently. */
- for (frame = get_current_frame ();
- frame && FRAME_FP (frame) != VALUE_FRAME (toval);
- frame = get_prev_frame (frame))
- ;
+ if (VALUE_LVAL (toval) == lval_register)
+ {
+ frame = get_current_frame ();
+ value_reg = VALUE_REGNO (toval);
+ }
+ else
+ {
+ for (frame = get_current_frame ();
+ frame && get_frame_base (frame) != VALUE_FRAME (toval);
+ frame = get_prev_frame (frame))
+ ;
+ value_reg = VALUE_FRAME_REGNUM (toval);
+ }
if (!frame)
error ("Value being assigned to is no longer active.");
- amount_to_copy += (reg_size - amount_to_copy % reg_size);
+ /* Locate the first register that falls in the value that
+ needs to be transfered. Compute the offset of the value in
+ that register. */
+ {
+ int offset;
+ for (reg_offset = value_reg, offset = 0;
+ offset + REGISTER_RAW_SIZE (reg_offset) <= VALUE_OFFSET (toval);
+ reg_offset++);
+ byte_offset = VALUE_OFFSET (toval) - offset;
+ }
- /* Copy it out. */
- for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
- amount_copied = 0);
+ /* Compute the number of register aligned values that need to
+ be copied. */
+ if (VALUE_BITSIZE (toval))
+ amount_to_copy = byte_offset + 1;
+ else
+ amount_to_copy = byte_offset + TYPE_LENGTH (type);
+
+ /* And a bounce buffer. Be slightly over generous. */
+ buffer = (char *) alloca (amount_to_copy
+ + MAX_REGISTER_RAW_SIZE);
+
+ /* Copy it in. */
+ for (regno = reg_offset, amount_copied = 0;
amount_copied < amount_to_copy;
- amount_copied += reg_size, regno++)
+ amount_copied += REGISTER_RAW_SIZE (regno), regno++)
{
- get_saved_register (buffer + amount_copied,
- (int *) NULL, (CORE_ADDR *) NULL,
- frame, regno, (enum lval_type *) NULL);
+ frame_register_read (frame, regno, buffer + amount_copied);
}
-
+
/* Modify what needs to be modified. */
if (VALUE_BITSIZE (toval))
- modify_field (buffer + byte_offset,
- value_as_long (fromval),
- VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ {
+ modify_field (buffer + byte_offset,
+ value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ }
else if (use_buffer)
- memcpy (buffer + byte_offset, raw_buffer, use_buffer);
+ {
+ memcpy (buffer + VALUE_OFFSET (toval), raw_buffer, use_buffer);
+ }
else
- memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
- TYPE_LENGTH (type));
+ {
+ memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
+ TYPE_LENGTH (type));
+ /* Do any conversion necessary when storing this type to
+ more than one register. */
+#ifdef REGISTER_CONVERT_FROM_TYPE
+ REGISTER_CONVERT_FROM_TYPE (value_reg, type,
+ (buffer + byte_offset));
+#endif
+ }
- /* Copy it back. */
- for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
- amount_copied = 0);
+ /* Copy it out. */
+ for (regno = reg_offset, amount_copied = 0;
amount_copied < amount_to_copy;
- amount_copied += reg_size, regno++)
+ amount_copied += REGISTER_RAW_SIZE (regno), regno++)
{
enum lval_type lval;
CORE_ADDR addr;
int optim;
-
+ int realnum;
+
/* Just find out where to put it. */
- get_saved_register ((char *) NULL,
- &optim, &addr, frame, regno, &lval);
-
+ frame_register (frame, regno, &optim, &lval, &addr, &realnum,
+ NULL);
+
if (optim)
error ("Attempt to assign to a value that was optimized out.");
if (lval == lval_memory)
- write_memory (addr, buffer + amount_copied, reg_size);
+ write_memory (addr, buffer + amount_copied,
+ REGISTER_RAW_SIZE (regno));
else if (lval == lval_register)
- write_register_bytes (addr, buffer + amount_copied, reg_size);
+ regcache_cooked_write (current_regcache, realnum,
+ (buffer + amount_copied));
else
error ("Attempt to assign to an unmodifiable value.");
}
if (register_changed_hook)
register_changed_hook (-1);
+ target_changed_event ();
+
}
break;
-
-
+
+
default:
error ("Left operand of assignment is not an lvalue.");
}
+ /* Assigning to the stack pointer, frame pointer, and other
+ (architecture and calling convention specific) registers may
+ cause the frame cache to be out of date. Assigning to memory
+ also can. We just do this on all assignments to registers or
+ memory, for simplicity's sake; I doubt the slowdown matters. */
+ switch (VALUE_LVAL (toval))
+ {
+ case lval_memory:
+ case lval_register:
+ case lval_reg_frame_relative:
+
+ reinit_frame_cache ();
+
+ /* Having destoroyed the frame cache, restore the selected frame. */
+
+ /* FIXME: cagney/2002-11-02: There has to be a better way of
+ doing this. Instead of constantly saving/restoring the
+ frame. Why not create a get_selected_frame() function that,
+ having saved the selected frame's ID can automatically
+ re-find the previously selected frame automatically. */
+
+ {
+ struct frame_info *fi = frame_find_by_id (old_frame);
+ if (fi != NULL)
+ select_frame (fi);
+ }
+
+ break;
+ default:
+ break;
+ }
+
/* If the field does not entirely fill a LONGEST, then zero the sign bits.
If the field is signed, and is negative, then sign extend. */
if ((VALUE_BITSIZE (toval) > 0)
if (!frame)
{
if (BLOCK_FUNCTION (b)
- && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)))
+ && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)))
error ("No frame is currently executing in block %s.",
- SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)));
+ SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)));
else
error ("No frame is currently executing in specified block");
}
val = read_var_value (var, frame);
if (!val)
- error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
+ error ("Address of symbol \"%s\" is unknown.", SYMBOL_PRINT_NAME (var));
return val;
}
to do. "long long" variables are rare enough that
BUILTIN_TYPE_LONGEST would seem to be a mistake. */
if (TYPE_CODE (base_type) == TYPE_CODE_INT)
- return value_at (builtin_type_int,
- (CORE_ADDR) value_as_long (arg1),
- VALUE_BFD_SECTION (arg1));
+ return value_at_lazy (builtin_type_int,
+ (CORE_ADDR) value_as_long (arg1),
+ VALUE_BFD_SECTION (arg1));
else if (TYPE_CODE (base_type) == TYPE_CODE_PTR)
{
struct type *enc_type;
return sp;
}
-#ifndef PUSH_ARGUMENTS
-#define PUSH_ARGUMENTS default_push_arguments
-#endif
-
CORE_ADDR
-default_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+legacy_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
{
/* ASSERT ( !struct_return); */
int i;
return sp;
}
-
-/* Functions to use for the COERCE_FLOAT_TO_DOUBLE gdbarch method.
-
- How you should pass arguments to a function depends on whether it
- was defined in K&R style or prototype style. If you define a
- function using the K&R syntax that takes a `float' argument, then
- callers must pass that argument as a `double'. If you define the
- function using the prototype syntax, then you must pass the
- argument as a `float', with no promotion.
-
- Unfortunately, on certain older platforms, the debug info doesn't
- indicate reliably how each function was defined. A function type's
- TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
- defined in prototype style. When calling a function whose
- TYPE_FLAG_PROTOTYPED flag is clear, GDB consults the
- COERCE_FLOAT_TO_DOUBLE gdbarch method to decide what to do.
-
- For modern targets, it is proper to assume that, if the prototype
- flag is clear, that can be trusted: `float' arguments should be
- promoted to `double'. You should register the function
- `standard_coerce_float_to_double' to get this behavior.
-
- For some older targets, if the prototype flag is clear, that
- doesn't tell us anything. So we guess that, if we don't have a
- type for the formal parameter (i.e., the first argument to
- COERCE_FLOAT_TO_DOUBLE is null), then we should promote it;
- otherwise, we should leave it alone. The function
- `default_coerce_float_to_double' provides this behavior; it is the
- default value, for compatibility with older configurations. */
-int
-default_coerce_float_to_double (struct type *formal, struct type *actual)
-{
- return formal == NULL;
-}
-
-
-int
-standard_coerce_float_to_double (struct type *formal, struct type *actual)
-{
- return 1;
-}
-
-
/* Perform the standard coercions that are specified
for arguments to be passed to C functions.
switch (TYPE_CODE (type))
{
case TYPE_CODE_REF:
- if (TYPE_CODE (arg_type) != TYPE_CODE_REF)
+ if (TYPE_CODE (arg_type) != TYPE_CODE_REF
+ && TYPE_CODE (arg_type) != TYPE_CODE_PTR)
{
arg = value_addr (arg);
VALUE_TYPE (arg) = param_type;
type = builtin_type_int;
break;
case TYPE_CODE_FLT:
- /* FIXME: We should always convert floats to doubles in the
- non-prototyped case. As many debugging formats include
- no information about prototyping, we have to live with
- COERCE_FLOAT_TO_DOUBLE for now. */
- if (!is_prototyped && COERCE_FLOAT_TO_DOUBLE (param_type, arg_type))
+ if (!is_prototyped && coerce_float_to_double)
{
if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
type = builtin_type_double;
type = lookup_pointer_type (type);
break;
case TYPE_CODE_ARRAY:
+ /* Arrays are coerced to pointers to their first element, unless
+ they are vectors, in which case we want to leave them alone,
+ because they are passed by value. */
if (current_language->c_style_arrays)
- type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ if (!TYPE_VECTOR (type))
+ type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
break;
case TYPE_CODE_UNDEF:
case TYPE_CODE_PTR:
ARGS is modified to contain coerced values. */
-static struct value *
-hand_function_call (struct value *function, int nargs, struct value **args)
+struct value *
+call_function_by_hand (struct value *function, int nargs, struct value **args)
{
register CORE_ADDR sp;
register int i;
static ULONGEST *dummy;
int sizeof_dummy1;
char *dummy1;
+ CORE_ADDR dummy_addr;
CORE_ADDR old_sp;
struct type *value_type;
unsigned char struct_return;
CORE_ADDR struct_addr = 0;
+ struct regcache *retbuf;
+ struct cleanup *retbuf_cleanup;
struct inferior_status *inf_status;
- struct cleanup *old_chain;
+ struct cleanup *inf_status_cleanup;
CORE_ADDR funaddr;
int using_gcc; /* Set to version of gcc in use, or zero if not gcc */
CORE_ADDR real_pc;
if (!target_has_execution)
noprocess ();
- inf_status = save_inferior_status (1);
- old_chain = make_cleanup_restore_inferior_status (inf_status);
+ /* Create a cleanup chain that contains the retbuf (buffer
+ containing the register values). This chain is create BEFORE the
+ inf_status chain so that the inferior status can cleaned up
+ (restored or discarded) without having the retbuf freed. */
+ retbuf = regcache_xmalloc (current_gdbarch);
+ retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
- /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
- (and POP_FRAME for restoring them). (At least on most machines)
- they are saved on the stack in the inferior. */
- PUSH_DUMMY_FRAME;
+ /* A cleanup for the inferior status. Create this AFTER the retbuf
+ so that this can be discarded or applied without interfering with
+ the regbuf. */
+ inf_status = save_inferior_status (1);
+ inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
- old_sp = sp = read_sp ();
+ if (DEPRECATED_PUSH_DUMMY_FRAME_P ())
+ {
+ /* DEPRECATED_PUSH_DUMMY_FRAME is responsible for saving the
+ inferior registers (and frame_pop() for restoring them). (At
+ least on most machines) they are saved on the stack in the
+ inferior. */
+ DEPRECATED_PUSH_DUMMY_FRAME;
+ }
+ else
+ {
+ /* FIXME: cagney/2003-02-26: Step zero of this little tinker is
+ to extract the generic dummy frame code from the architecture
+ vector. Hence this direct call.
+
+ A follow-on change is to modify this interface so that it takes
+ thread OR frame OR tpid as a parameter, and returns a dummy
+ frame handle. The handle can then be used further down as a
+ parameter SAVE_DUMMY_FRAME_TOS. Hmm, thinking about it, since
+ everything is ment to be using generic dummy frames, why not
+ even use some of the dummy frame code to here - do a regcache
+ dup and then pass the duped regcache, along with all the other
+ stuff, at one single point.
+
+ In fact, you can even save the structure's return address in the
+ dummy frame and fix one of those nasty lost struct return edge
+ conditions. */
+ generic_push_dummy_frame ();
+ }
+
+ old_sp = read_sp ();
+
+ /* Ensure that the initial SP is correctly aligned. */
+ if (gdbarch_frame_align_p (current_gdbarch))
+ {
+ /* NOTE: cagney/2002-09-18:
+
+ On a RISC architecture, a void parameterless generic dummy
+ frame (i.e., no parameters, no result) typically does not
+ need to push anything the stack and hence can leave SP and
+ FP. Similarly, a framelss (possibly leaf) function does not
+ push anything on the stack and, hence, that too can leave FP
+ and SP unchanged. As a consequence, a sequence of void
+ parameterless generic dummy frame calls to frameless
+ functions will create a sequence of effectively identical
+ frames (SP, FP and TOS and PC the same). This, not
+ suprisingly, results in what appears to be a stack in an
+ infinite loop --- when GDB tries to find a generic dummy
+ frame on the internal dummy frame stack, it will always find
+ the first one.
+
+ To avoid this problem, the code below always grows the stack.
+ That way, two dummy frames can never be identical. It does
+ burn a few bytes of stack but that is a small price to pay
+ :-). */
+ sp = gdbarch_frame_align (current_gdbarch, old_sp);
+ if (sp == old_sp)
+ {
+ if (INNER_THAN (1, 2))
+ /* Stack grows down. */
+ sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
+ else
+ /* Stack grows up. */
+ sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
+ }
+ gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
+ || (INNER_THAN (2, 1) && sp >= old_sp));
+ }
+ else
+ /* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how badly
+ aligned the SP is! Further, per comment above, if the generic
+ dummy frame ends up empty (because nothing is pushed) GDB won't
+ be able to correctly perform back traces. If a target is
+ having trouble with backtraces, first thing to do is add
+ FRAME_ALIGN() to its architecture vector. After that, try
+ adding SAVE_DUMMY_FRAME_TOS() and modifying
+ DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
+ generic dummy, it returns the current frame's base. */
+ sp = old_sp;
if (INNER_THAN (1, 2))
{
sp += sizeof_dummy1;
}
+ /* NOTE: cagney/2002-09-10: Don't bother re-adjusting the stack
+ after allocating space for the call dummy. A target can specify
+ a SIZEOF_DUMMY1 (via SIZEOF_CALL_DUMMY_WORDS) such that all local
+ alignment requirements are met. */
+
funaddr = find_function_addr (function, &value_type);
CHECK_TYPEDEF (value_type);
real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
value_type, using_gcc);
#else
- FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
- value_type, using_gcc);
+ if (FIX_CALL_DUMMY_P ())
+ {
+ /* gdb_assert (CALL_DUMMY_LOCATION == ON_STACK) true? */
+ FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, value_type,
+ using_gcc);
+ }
real_pc = start_sp;
#endif
- if (CALL_DUMMY_LOCATION == ON_STACK)
+ switch (CALL_DUMMY_LOCATION)
{
+ case ON_STACK:
+ dummy_addr = start_sp;
write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
- }
-
- if (CALL_DUMMY_LOCATION == BEFORE_TEXT_END)
- {
- /* 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 int checked = 0;
- if (!checked)
- for (start_sp = text_end - sizeof_dummy1; start_sp < text_end; ++start_sp)
- if (read_memory_integer (start_sp, 1) != 0)
- error ("text segment full -- no place to put call");
- checked = 1;
- sp = old_sp;
- real_pc = text_end - sizeof_dummy1;
- write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
- }
-
- if (CALL_DUMMY_LOCATION == AFTER_TEXT_END)
- {
- extern CORE_ADDR text_end;
- int errcode;
- sp = old_sp;
- real_pc = text_end;
- errcode = target_write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
- if (errcode != 0)
- error ("Cannot write text segment -- call_function failed");
- }
-
- if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
- {
+ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
+ generic_save_call_dummy_addr (start_sp, start_sp + sizeof_dummy1);
+ break;
+ case AT_ENTRY_POINT:
real_pc = funaddr;
+ dummy_addr = CALL_DUMMY_ADDRESS ();
+ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
+ /* NOTE: cagney/2002-04-13: The entry point is going to be
+ modified with a single breakpoint. */
+ generic_save_call_dummy_addr (CALL_DUMMY_ADDRESS (),
+ CALL_DUMMY_ADDRESS () + 1);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
}
#ifdef lint
sp = old_sp; /* It really is used, for some ifdef's... */
#endif
- if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- {
- i = 0;
- while (TYPE_CODE (TYPE_ARG_TYPES (ftype)[i]) != TYPE_CODE_VOID)
- i++;
- n_method_args = i;
- if (nargs < i)
- error ("too few arguments in method call");
- }
- else if (nargs < TYPE_NFIELDS (ftype))
+ if (nargs < TYPE_NFIELDS (ftype))
error ("too few arguments in function call");
for (i = nargs - 1; i >= 0; i--)
{
- /* Assume that methods are always prototyped, unless they are off the
- end (which we should only be allowing if there is a ``...'').
- FIXME. */
- if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- {
- if (i < n_method_args)
- args[i] = value_arg_coerce (args[i], TYPE_ARG_TYPES (ftype)[i], 1);
- else
- args[i] = value_arg_coerce (args[i], NULL, 0);
- }
+ int prototyped;
- /* If we're off the end of the known arguments, do the standard
- promotions. FIXME: if we had a prototype, this should only
- be allowed if ... were present. */
- if (i >= TYPE_NFIELDS (ftype))
- args[i] = value_arg_coerce (args[i], NULL, 0);
+ /* FIXME drow/2002-05-31: Should just always mark methods as
+ prototyped. Can we respect TYPE_VARARGS? Probably not. */
+ if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ prototyped = 1;
+ else
+ prototyped = TYPE_PROTOTYPED (ftype);
+ if (i < TYPE_NFIELDS (ftype))
+ args[i] = value_arg_coerce (args[i], TYPE_FIELD_TYPE (ftype, i),
+ prototyped);
else
- {
- param_type = TYPE_FIELD_TYPE (ftype, i);
- args[i] = value_arg_coerce (args[i], param_type, TYPE_PROTOTYPED (ftype));
- }
+ args[i] = value_arg_coerce (args[i], NULL, 0);
/*elz: this code is to handle the case in which the function to be called
has a pointer to function as parameter and the corresponding actual argument
In cc this is not a problem. */
if (using_gcc == 0)
- if (param_type)
+ if (param_type && TYPE_CODE (ftype) != TYPE_CODE_METHOD)
/* if this parameter is a pointer to function */
if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
- if (TYPE_CODE (param_type->target_type) == TYPE_CODE_FUNC)
+ if (TYPE_CODE (TYPE_TARGET_TYPE (param_type)) == TYPE_CODE_FUNC)
/* elz: FIXME here should go the test about the compiler used
to compile the target. We want to issue the error
message only if the compiler used was HP's aCC.
/* Reserve space for the return structure to be written on the
- stack, if necessary */
+ stack, if necessary. Make certain that the value is correctly
+ aligned. */
if (struct_return)
{
int len = TYPE_LENGTH (value_type);
if (STACK_ALIGN_P ())
- /* MVS 11/22/96: I think at least some of this stack_align
- code is really broken. Better to let PUSH_ARGUMENTS adjust
- the stack in a target-defined manner. */
+ /* NOTE: cagney/2003-03-22: Should rely on frame align, rather
+ than stack align to force the alignment of the stack. */
len = STACK_ALIGN (len);
if (INNER_THAN (1, 2))
{
- /* stack grows downward */
+ /* Stack grows downward. Align STRUCT_ADDR and SP after
+ making space for the return value. */
sp -= len;
+ if (gdbarch_frame_align_p (current_gdbarch))
+ sp = gdbarch_frame_align (current_gdbarch, sp);
struct_addr = sp;
}
else
{
- /* stack grows upward */
+ /* Stack grows upward. Align the frame, allocate space, and
+ then again, re-align the frame??? */
+ if (gdbarch_frame_align_p (current_gdbarch))
+ sp = gdbarch_frame_align (current_gdbarch, sp);
struct_addr = sp;
sp += len;
+ if (gdbarch_frame_align_p (current_gdbarch))
+ sp = gdbarch_frame_align (current_gdbarch, sp);
}
}
on other architectures. This is because all the alignment is
taken care of in the above code (ifdef REG_STRUCT_HAS_ADDR) and
in hppa_push_arguments */
- if (EXTRA_STACK_ALIGNMENT_NEEDED)
+ /* NOTE: cagney/2003-03-24: The below code is very broken. Given an
+ odd sized parameter the below will mis-align the stack. As was
+ suggested back in '96, better to let PUSH_ARGUMENTS handle it. */
+ if (DEPRECATED_EXTRA_STACK_ALIGNMENT_NEEDED)
{
/* MVS 11/22/96: I think at least some of this stack_align code
- is really broken. Better to let PUSH_ARGUMENTS adjust the
+ is really broken. Better to let push_dummy_call() adjust the
stack in a target-defined manner. */
if (STACK_ALIGN_P () && INNER_THAN (1, 2))
{
for (i = nargs - 1; i >= 0; i--)
len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
- if (CALL_DUMMY_STACK_ADJUST_P)
- len += CALL_DUMMY_STACK_ADJUST;
+ if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+ len += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
sp -= STACK_ALIGN (len) - len;
}
}
- sp = PUSH_ARGUMENTS (nargs, args, sp, struct_return, struct_addr);
+ /* Create the dummy stack frame. Pass in the call dummy address as,
+ presumably, the ABI code knows where, in the call dummy, the
+ return address should be pointed. */
+ if (gdbarch_push_dummy_call_p (current_gdbarch))
+ /* When there is no push_dummy_call method, should this code
+ simply error out. That would the implementation of this method
+ for all ABIs (which is probably a good thing). */
+ sp = gdbarch_push_dummy_call (current_gdbarch, current_regcache,
+ dummy_addr, nargs, args, sp, struct_return,
+ struct_addr);
+ else if (DEPRECATED_PUSH_ARGUMENTS_P ())
+ /* Keep old targets working. */
+ sp = DEPRECATED_PUSH_ARGUMENTS (nargs, args, sp, struct_return,
+ struct_addr);
+ else
+ sp = legacy_push_arguments (nargs, args, sp, struct_return, struct_addr);
- if (PUSH_RETURN_ADDRESS_P ())
+ if (DEPRECATED_PUSH_RETURN_ADDRESS_P ())
/* for targets that use no CALL_DUMMY */
/* There are a number of targets now which actually don't write
any CALL_DUMMY instructions into the target, but instead just
return-address register as appropriate. Formerly this has been
done in PUSH_ARGUMENTS, but that's overloading its
functionality a bit, so I'm making it explicit to do it here. */
- sp = PUSH_RETURN_ADDRESS (real_pc, sp);
+ sp = DEPRECATED_PUSH_RETURN_ADDRESS (real_pc, sp);
- if (STACK_ALIGN_P () && !INNER_THAN (1, 2))
+ /* NOTE: cagney/2003-03-23: Diable this code when there is a
+ push_dummy_call() method. Since that method will have already
+ handled any alignment issues, the code below is entirely
+ redundant. */
+ if (!gdbarch_push_dummy_call_p (current_gdbarch)
+ && STACK_ALIGN_P () && !INNER_THAN (1, 2))
{
/* If stack grows up, we must leave a hole at the bottom, note
that sp already has been advanced for the arguments! */
- if (CALL_DUMMY_STACK_ADJUST_P)
- sp += CALL_DUMMY_STACK_ADJUST;
+ if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+ sp += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
sp = STACK_ALIGN (sp);
}
/* MVS 11/22/96: I think at least some of this stack_align code is
really broken. Better to let PUSH_ARGUMENTS adjust the stack in
a target-defined manner. */
- if (CALL_DUMMY_STACK_ADJUST_P)
+ if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
if (INNER_THAN (1, 2))
{
/* stack grows downward */
- sp -= CALL_DUMMY_STACK_ADJUST;
+ sp -= DEPRECATED_CALL_DUMMY_STACK_ADJUST;
}
/* Store the address at which the structure is supposed to be
- written. Note that this (and the code which reserved the space
- above) assumes that gcc was used to compile this function. Since
- it doesn't cost us anything but space and if the function is pcc
- it will ignore this value, we will make that assumption.
-
- Also note that on some machines (like the sparc) pcc uses a
- convention like gcc's. */
-
- if (struct_return)
- STORE_STRUCT_RETURN (struct_addr, sp);
+ written. */
+ /* NOTE: 2003-03-24: Since PUSH_ARGUMENTS can (and typically does)
+ store the struct return address, this call is entirely redundant. */
+ if (struct_return && DEPRECATED_STORE_STRUCT_RETURN_P ())
+ DEPRECATED_STORE_STRUCT_RETURN (struct_addr, sp);
/* Write the stack pointer. This is here because the statements above
might fool with it. On SPARC, this write also stores the register
window into the right place in the new stack frame, which otherwise
wouldn't happen. (See store_inferior_registers in sparc-nat.c.) */
- write_sp (sp);
+ /* NOTE: cagney/2003-03-23: Disable this code when there is a
+ push_dummy_call() method. Since that method will have already
+ stored the stack pointer (as part of creating the fake call
+ frame), and none of the code following that code adjusts the
+ stack-pointer value, the below call is entirely redundant. */
+ if (DEPRECATED_DUMMY_WRITE_SP_P ())
+ DEPRECATED_DUMMY_WRITE_SP (sp);
if (SAVE_DUMMY_FRAME_TOS_P ())
SAVE_DUMMY_FRAME_TOS (sp);
{
- char *retbuf = (char*) alloca (REGISTER_BYTES);
char *name;
struct symbol *symbol;
symbol = find_pc_function (funaddr);
if (symbol)
{
- name = SYMBOL_SOURCE_NAME (symbol);
+ name = SYMBOL_PRINT_NAME (symbol);
}
else
{
if (msymbol)
{
- name = SYMBOL_SOURCE_NAME (msymbol);
+ name = SYMBOL_PRINT_NAME (msymbol);
}
}
if (name == NULL)
{
/* The user wants the context restored. */
- /* We must get back to the frame we were before the dummy call. */
- POP_FRAME;
+ /* We must get back to the frame we were before the dummy
+ call. */
+ frame_pop (get_current_frame ());
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's
a C++ name with arguments and stuff. */
{
/* The user wants to stay in the frame where we stopped (default).*/
- /* If we did the cleanups, we would print a spurious error
- message (Unable to restore previously selected frame),
- would write the registers from the inf_status (which is
- wrong), and would do other wrong things. */
- discard_cleanups (old_chain);
+ /* If we restored the inferior status (via the cleanup),
+ we would print a spurious error message (Unable to
+ restore previously selected frame), would write the
+ registers from the inf_status (which is wrong), and
+ would do other wrong things. */
+ discard_cleanups (inf_status_cleanup);
discard_inferior_status (inf_status);
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's
{
/* We hit a breakpoint inside the FUNCTION. */
- /* If we did the cleanups, we would print a spurious error
- message (Unable to restore previously selected frame),
- would write the registers from the inf_status (which is
- wrong), and would do other wrong things. */
- discard_cleanups (old_chain);
+ /* If we restored the inferior status (via the cleanup), we
+ would print a spurious error message (Unable to restore
+ previously selected frame), would write the registers from
+ the inf_status (which is wrong), and would do other wrong
+ things. */
+ discard_cleanups (inf_status_cleanup);
discard_inferior_status (inf_status);
/* The following error message used to say "The expression
}
/* If we get here the called FUNCTION run to completion. */
- do_cleanups (old_chain);
- /* Figure out the value returned by the function. */
-/* elz: I defined this new macro for the hppa architecture only.
- this gives us a way to get the value returned by the function from the stack,
- at the same address we told the function to put it.
- We cannot assume on the pa that r28 still contains the address of the returned
- structure. Usually this will be overwritten by the callee.
- I don't know about other architectures, so I defined this macro
- */
+ /* Restore the inferior status, via its cleanup. At this stage,
+ leave the RETBUF alone. */
+ do_cleanups (inf_status_cleanup);
+ /* Figure out the value returned by the function. */
+ /* elz: I defined this new macro for the hppa architecture only.
+ this gives us a way to get the value returned by the function
+ from the stack, at the same address we told the function to put
+ it. We cannot assume on the pa that r28 still contains the
+ address of the returned structure. Usually this will be
+ overwritten by the callee. I don't know about other
+ architectures, so I defined this macro */
#ifdef VALUE_RETURNED_FROM_STACK
if (struct_return)
- return (struct value *) VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
+ {
+ do_cleanups (retbuf_cleanup);
+ return VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
+ }
#endif
-
- return value_being_returned (value_type, retbuf, struct_return);
+ /* NOTE: cagney/2002-09-10: Only when the stack has been correctly
+ aligned (using frame_align()) do we can trust STRUCT_ADDR and
+ fetch the return value direct from the stack. This lack of
+ trust comes about because legacy targets have a nasty habit of
+ silently, and local to PUSH_ARGUMENTS(), moving STRUCT_ADDR.
+ For such targets, just hope that value_being_returned() can
+ find the adjusted value. */
+ if (struct_return && gdbarch_frame_align_p (current_gdbarch))
+ {
+ struct value *retval = value_at (value_type, struct_addr, NULL);
+ do_cleanups (retbuf_cleanup);
+ return retval;
+ }
+ else
+ {
+ struct value *retval = value_being_returned (value_type, retbuf,
+ struct_return);
+ do_cleanups (retbuf_cleanup);
+ return retval;
+ }
}
}
-struct value *
-call_function_by_hand (struct value *function, int nargs, struct value **args)
-{
- if (CALL_DUMMY_P)
- {
- return hand_function_call (function, nargs, args);
- }
- else
- {
- error ("Cannot invoke functions on this machine.");
- }
-}
-\f
-
-
/* Create a value for an array by allocating space in the inferior, copying
the data into that space, and then setting up an array value.
}
\f
/* See if we can pass arguments in T2 to a function which takes arguments
- of types T1. Both t1 and t2 are NULL-terminated vectors. If some
- arguments need coercion of some sort, then the coerced values are written
- into T2. Return value is 0 if the arguments could be matched, or the
- position at which they differ if not.
+ of types T1. T1 is a list of NARGS arguments, and T2 is a NULL-terminated
+ vector. If some arguments need coercion of some sort, then the coerced
+ values are written into T2. Return value is 0 if the arguments could be
+ matched, or the position at which they differ if not.
STATICP is nonzero if the T1 argument list came from a
- static member function.
+ static member function. T2 will still include the ``this'' pointer,
+ but it will be skipped.
For non-static member functions, we ignore the first argument,
which is the type of the instance variable. This is because we want
requested operation is type secure, shouldn't we? FIXME. */
static int
-typecmp (int staticp, struct type *t1[], struct value *t2[])
+typecmp (int staticp, int varargs, int nargs,
+ struct field t1[], struct value *t2[])
{
int i;
if (t2 == 0)
- return 1;
- if (staticp && t1 == 0)
- return t2[1] != 0;
- if (t1 == 0)
- return 1;
- if (TYPE_CODE (t1[0]) == TYPE_CODE_VOID)
- return 0;
- if (t1[!staticp] == 0)
- return 0;
- for (i = !staticp; t1[i] && TYPE_CODE (t1[i]) != TYPE_CODE_VOID; i++)
+ internal_error (__FILE__, __LINE__, "typecmp: no argument list");
+
+ /* Skip ``this'' argument if applicable. T2 will always include THIS. */
+ if (staticp)
+ t2 ++;
+
+ for (i = 0;
+ (i < nargs) && TYPE_CODE (t1[i].type) != TYPE_CODE_VOID;
+ i++)
{
struct type *tt1, *tt2;
+
if (!t2[i])
return i + 1;
- tt1 = check_typedef (t1[i]);
+
+ tt1 = check_typedef (t1[i].type);
tt2 = check_typedef (VALUE_TYPE (t2[i]));
+
if (TYPE_CODE (tt1) == TYPE_CODE_REF
/* We should be doing hairy argument matching, as below. */
&& (TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (tt1))) == TYPE_CODE (tt2)))
/* We should be doing much hairier argument matching (see section 13.2
of the ARM), but as a quick kludge, just check for the same type
code. */
- if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i])))
+ if (TYPE_CODE (t1[i].type) != TYPE_CODE (VALUE_TYPE (t2[i])))
return i + 1;
}
- if (!t1[i])
+ if (varargs || t2[i] == NULL)
return 0;
- return t2[i] ? i + 1 : 0;
+ return i + 1;
}
/* Helper function used by value_struct_elt to recurse through baseclasses.
{
struct value *v;
if (TYPE_FIELD_STATIC (type, i))
- v = value_static_field (type, i);
+ {
+ v = value_static_field (type, i);
+ if (v == 0)
+ error ("field %s is nonexistent or has been optimised out",
+ name);
+ }
else
- v = value_primitive_field (arg1, offset, i, type);
- if (v == 0)
- error ("there is no field named %s", name);
+ {
+ v = value_primitive_field (arg1, offset, i, type);
+ if (v == 0)
+ error ("there is no field named %s", name);
+ }
return v;
}
/* Look for a match through the fields of an anonymous union,
or anonymous struct. C++ provides anonymous unions.
- In the GNU Chill implementation of variant record types,
- each <alternative field> has an (anonymous) union type,
- each member of the union represents a <variant alternative>.
- Each <variant alternative> is represented as a struct,
- with a member for each <variant field>. */
+ In the GNU Chill (now deleted from GDB)
+ implementation of variant record types, each
+ <alternative field> has an (anonymous) union type,
+ each member of the union represents a <variant
+ alternative>. Each <variant alternative> is
+ represented as a struct, with a member for each
+ <variant field>. */
struct value *v;
int new_offset = offset;
- /* This is pretty gross. In G++, the offset in an anonymous
- union is relative to the beginning of the enclosing struct.
- In the GNU Chill implementation of variant records,
- the bitpos is zero in an anonymous union field, so we
+ /* This is pretty gross. In G++, the offset in an
+ anonymous union is relative to the beginning of the
+ enclosing struct. In the GNU Chill (now deleted
+ from GDB) implementation of variant records, the
+ bitpos is zero in an anonymous union field, so we
have to add the offset of the union here. */
if (TYPE_CODE (field_type) == TYPE_CODE_STRUCT
|| (TYPE_NFIELDS (field_type) > 0
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
name_matched = 1;
+ check_stub_method_group (type, i);
if (j > 0 && args == 0)
error ("cannot resolve overloaded method `%s': no arguments supplied", name);
- while (j >= 0)
+ else if (j == 0 && args == 0)
{
- 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_virtual_fn_field (arg1p, f, j, type, offset);
- if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
- *static_memfuncp = 1;
- v = value_fn_field (arg1p, f, j, type, offset);
- if (v != NULL)
- return v;
- }
- j--;
+ v = value_fn_field (arg1p, f, j, type, offset);
+ if (v != NULL)
+ return v;
}
+ else
+ while (j >= 0)
+ {
+ if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
+ TYPE_VARARGS (TYPE_FN_FIELD_TYPE (f, j)),
+ TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (f, j)),
+ TYPE_FN_FIELD_ARGS (f, j), args))
+ {
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ return value_virtual_fn_field (arg1p, f, j, type, offset);
+ if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
+ *static_memfuncp = 1;
+ v = value_fn_field (arg1p, f, j, type, offset);
+ if (v != NULL)
+ return v;
+ }
+ j--;
+ }
}
}
* ARGP is a pointer to a pointer to a value (the object)
* METHOD is a string containing the method name
* OFFSET is the offset within the value
- * STATIC_MEMFUNCP is set if the method is static
* TYPE is the assumed type of the object
* NUM_FNS is the number of overloaded instances
* BASETYPE is set to the actual type of the subobject where the method is found
static struct fn_field *
find_method_list (struct value **argp, char *method, int offset,
- int *static_memfuncp, struct type *type, int *num_fns,
+ struct type *type, int *num_fns,
struct type **basetype, int *boffset)
{
int i;
char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
{
- *num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ int len = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+
+ *num_fns = len;
*basetype = type;
*boffset = offset;
- return TYPE_FN_FIELDLIST1 (type, i);
+
+ /* Resolve any stub methods. */
+ check_stub_method_group (type, i);
+
+ return f;
}
}
base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
}
f = find_method_list (argp, method, base_offset + offset,
- static_memfuncp, TYPE_BASECLASS (type, i), num_fns, basetype, boffset);
+ TYPE_BASECLASS (type, i), num_fns, basetype,
+ boffset);
if (f)
return f;
}
* ARGP is a pointer to a pointer to a value (the object)
* METHOD is the method name
* OFFSET is the offset within the value contents
- * STATIC_MEMFUNCP is set if the method is static
* NUM_FNS is the number of overloaded instances
* BASETYPE is set to the type of the base subobject that defines the method
* BOFFSET is the offset of the base subobject which defines the method */
struct fn_field *
value_find_oload_method_list (struct value **argp, char *method, int offset,
- int *static_memfuncp, int *num_fns,
- struct type **basetype, int *boffset)
+ int *num_fns, struct type **basetype,
+ int *boffset)
{
struct type *t;
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Attempt to extract a component of a value that is not a struct or union");
- /* Assume it's not static, unless we see that it is. */
- if (static_memfuncp)
- *static_memfuncp = 0;
-
- return find_method_list (argp, method, 0, static_memfuncp, t, num_fns, basetype, boffset);
-
+ return find_method_list (argp, method, 0, t, num_fns, basetype, boffset);
}
/* Given an array of argument types (ARGTYPES) (which includes an
int boffset;
register int jj;
register int ix;
+ int static_offset;
+ struct cleanup *cleanups = NULL;
char *obj_type_name = NULL;
char *func_name = NULL;
/* Get the list of overloaded methods or functions */
if (method)
{
- int i;
- int len;
- struct type *domain;
obj_type_name = TYPE_NAME (VALUE_TYPE (obj));
/* Hack: evaluate_subexp_standard often passes in a pointer
value rather than the object itself, so try again */
obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (VALUE_TYPE (obj)));
fns_ptr = value_find_oload_method_list (&temp, name, 0,
- staticp,
&num_fns,
&basetype, &boffset);
if (!fns_ptr || !num_fns)
obj_type_name,
(obj_type_name && *obj_type_name) ? "::" : "",
name);
- domain = TYPE_DOMAIN_TYPE (fns_ptr[0].type);
- len = TYPE_NFN_FIELDS (domain);
- /* NOTE: dan/2000-03-10: This stuff is for STABS, which won't
- give us the info we need directly in the types. We have to
- use the method stub conversion to get it. Be aware that this
- is by no means perfect, and if you use STABS, please move to
- DWARF-2, or something like it, because trying to improve
- overloading using STABS is really a waste of time. */
- for (i = 0; i < len; i++)
- {
- int j;
- struct fn_field *f = TYPE_FN_FIELDLIST1 (domain, i);
- int len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
-
- for (j = 0; j < len2; j++)
- {
- if (TYPE_FN_FIELD_STUB (f, j) && (!strcmp_iw (TYPE_FN_FIELDLIST_NAME (domain,i),name)))
- check_stub_method (domain, i, j);
- }
- }
+ /* If we are dealing with stub method types, they should have
+ been resolved by find_method_list via value_find_oload_method_list
+ above. */
+ gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
}
else
{
int i = -1;
- func_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_NO_OPTS);
+ func_name = cplus_demangle (DEPRECATED_SYMBOL_NAME (fsym), DMGL_NO_OPTS);
/* If the name is NULL this must be a C-style function.
Just return the same symbol. */
}
oload_syms = make_symbol_overload_list (fsym);
+ cleanups = make_cleanup (xfree, oload_syms);
while (oload_syms[++i])
num_fns++;
if (!num_fns)
/* Consider each candidate in turn */
for (ix = 0; ix < num_fns; ix++)
{
+ static_offset = 0;
if (method)
{
- /* For static member functions, we won't have a this pointer, but nothing
- else seems to handle them right now, so we just pretend ourselves */
- nparms=0;
-
- if (TYPE_FN_FIELD_ARGS(fns_ptr,ix))
- {
- while (TYPE_CODE(TYPE_FN_FIELD_ARGS(fns_ptr,ix)[nparms]) != TYPE_CODE_VOID)
- nparms++;
- }
+ if (TYPE_FN_FIELD_STATIC_P (fns_ptr, ix))
+ static_offset = 1;
+ nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
}
else
{
parm_types = (struct type **) xmalloc (nparms * (sizeof (struct type *)));
for (jj = 0; jj < nparms; jj++)
parm_types[jj] = (method
- ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj])
+ ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
: TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), jj));
- /* Compare parameter types to supplied argument types */
- bv = rank_function (parm_types, nparms, arg_types, nargs);
+ /* Compare parameter types to supplied argument types. Skip THIS for
+ static methods. */
+ bv = rank_function (parm_types, nparms, arg_types + static_offset,
+ nargs - static_offset);
if (!oload_champ_bv)
{
fprintf_filtered (gdb_stderr,"Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
else
fprintf_filtered (gdb_stderr,"Overloaded function instance %s # of parms %d\n", SYMBOL_DEMANGLED_NAME (oload_syms[ix]), nparms);
- for (jj = 0; jj < nargs; jj++)
+ for (jj = 0; jj < nargs - static_offset; jj++)
fprintf_filtered (gdb_stderr,"...Badness @ %d : %d\n", jj, bv->rank[jj]);
fprintf_filtered (gdb_stderr,"Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
}
}
#endif
- /* Check how bad the best match is */
- for (ix = 1; ix <= nargs; ix++)
+ /* Check how bad the best match is. */
+ static_offset = 0;
+ if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, oload_champ))
+ static_offset = 1;
+ for (ix = 1; ix <= nargs - static_offset; ix++)
{
if (oload_champ_bv->rank[ix] >= 100)
oload_incompatible = 1; /* truly mismatched types */
if (method)
{
+ if (staticp && TYPE_FN_FIELD_STATIC_P (fns_ptr, oload_champ))
+ *staticp = 1;
+ else if (staticp)
+ *staticp = 0;
if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
*valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
else
}
*objp = temp;
}
+ if (cleanups != NULL)
+ do_cleanups (cleanups);
+
return oload_incompatible ? 100 : (oload_non_standard ? 10 : 0);
}
{
v = value_static_field (t, i);
if (v == NULL)
- error ("Internal error: could not find static variable %s",
+ error ("static field %s has been optimized out",
name);
return v;
}
int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+ check_stub_method_group (t, i);
+
if (intype == 0 && j > 1)
error ("non-unique member `%s' requires type instantiation", name);
if (intype)
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
-/* C++: return the value of the class instance variable, if one exists.
+/* Return the value of the local variable, if one exists.
Flag COMPLAIN signals an error if the request is made in an
inappropriate context. */
struct value *
-value_of_this (int complain)
+value_of_local (const char *name, int complain)
{
struct symbol *func, *sym;
struct block *b;
int i;
- static const char funny_this[] = "this";
- struct value *this;
+ struct value * ret;
- if (selected_frame == 0)
+ if (deprecated_selected_frame == 0)
{
if (complain)
error ("no frame selected");
return 0;
}
- func = get_frame_function (selected_frame);
+ func = get_frame_function (deprecated_selected_frame);
if (!func)
{
if (complain)
- error ("no `this' in nameless context");
+ error ("no `%s' in nameless context", name);
else
return 0;
}
if (i <= 0)
{
if (complain)
- error ("no args, no `this'");
+ error ("no args, no `%s'", name);
else
return 0;
}
/* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
symbol instead of the LOC_ARG one (if both exist). */
- sym = lookup_block_symbol (b, funny_this, VAR_NAMESPACE);
+ sym = lookup_block_symbol (b, name, NULL, VAR_NAMESPACE);
if (sym == NULL)
{
if (complain)
- error ("current stack frame not in method");
+ error ("current stack frame does not contain a variable named `%s'", name);
else
return NULL;
}
- this = read_var_value (sym, selected_frame);
- if (this == 0 && complain)
- error ("`this' argument at unknown address");
- return this;
+ ret = read_var_value (sym, deprecated_selected_frame);
+ if (ret == 0 && complain)
+ error ("`%s' argument unreadable", name);
+ return ret;
+}
+
+/* C++/Objective-C: return the value of the class instance variable,
+ if one exists. Flag COMPLAIN signals an error if the request is
+ made in an inappropriate context. */
+
+struct value *
+value_of_this (int complain)
+{
+ if (current_language->la_language == language_objc)
+ return value_of_local ("self", complain);
+ else
+ return value_of_local ("this", complain);
}
/* Create a slice (sub-string, sub-array) of ARRAY, that is LENGTH elements
value_slice (struct value *array, int lowbound, int length)
{
struct type *slice_range_type, *slice_type, *range_type;
- LONGEST lowerbound, upperbound, offset;
+ LONGEST lowerbound, upperbound;
struct value *slice;
struct type *array_type;
array_type = check_typedef (VALUE_TYPE (array));
if (get_discrete_bounds (range_type, &lowerbound, &upperbound) < 0)
error ("slice from bad array or bitstring");
if (lowbound < lowerbound || length < 0
- || lowbound + length - 1 > upperbound
- /* Chill allows zero-length strings but not arrays. */
- || (current_language->la_language == language_chill
- && length == 0 && TYPE_CODE (array_type) == TYPE_CODE_ARRAY))
+ || lowbound + length - 1 > upperbound)
error ("slice out of range");
/* FIXME-type-allocation: need a way to free this type when we are
done with it. */
else
{
struct type *element_type = TYPE_TARGET_TYPE (array_type);
- offset
+ LONGEST offset
= (lowbound - lowerbound) * TYPE_LENGTH (check_typedef (element_type));
slice_type = create_array_type ((struct type *) NULL, element_type,
slice_range_type);
return slice;
}
-/* Assuming chill_varying_type (VARRAY) is true, return an equivalent
- value as a fixed-length array. */
-
-struct value *
-varying_to_slice (struct value *varray)
-{
- struct type *vtype = check_typedef (VALUE_TYPE (varray));
- LONGEST length = unpack_long (TYPE_FIELD_TYPE (vtype, 0),
- VALUE_CONTENTS (varray)
- + TYPE_FIELD_BITPOS (vtype, 0) / 8);
- return value_slice (value_primitive_field (varray, 0, 1, vtype), 0, length);
-}
-
/* Create a value for a FORTRAN complex number. Currently most of
the time values are coerced to COMPLEX*16 (i.e. a complex number
composed of 2 doubles. This really should be a smarter routine
unwinds the stack and restore the context to what as it was before the call.\n\
The default is to stop in the frame where the signal was received.", &setlist),
&showlist);
+
+ add_show_from_set
+ (add_set_cmd ("coerce-float-to-double", class_obscure, var_boolean,
+ (char *) &coerce_float_to_double,
+ "Set coercion of floats to doubles when calling functions\n"
+ "Variables of type float should generally be converted to doubles before\n"
+ "calling an unprototyped function, and left alone when calling a prototyped\n"
+ "function. However, some older debug info formats do not provide enough\n"
+ "information to determine that a function is prototyped. If this flag is\n"
+ "set, GDB will perform the conversion for a function it considers\n"
+ "unprototyped.\n"
+ "The default is to perform the conversion.\n",
+ &setlist),
+ &showlist);
+ coerce_float_to_double = 1;
}