C++ changes for 5.0, finally committed.
This commit is contained in:
parent
eb90a51f9d
commit
070ad9f02e
6 changed files with 341 additions and 209 deletions
|
@ -481,6 +481,17 @@ c_value_print (val, stream, format, pretty)
|
|||
}
|
||||
else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
|
||||
{
|
||||
|
||||
if (TYPE_CODE(type) == TYPE_CODE_REF)
|
||||
{
|
||||
/* Copy value, change to pointer, so we don't get an
|
||||
* error about a non-pointer type in value_rtti_target_type
|
||||
*/
|
||||
value_ptr temparg;
|
||||
temparg=value_copy(val);
|
||||
VALUE_TYPE (temparg) = lookup_pointer_type(TYPE_TARGET_TYPE(type));
|
||||
val=temparg;
|
||||
}
|
||||
/* Pointer to class, check real type of object */
|
||||
fprintf_filtered (stream, "(");
|
||||
real_type = value_rtti_target_type (val, &full, &top, &using_enc);
|
||||
|
@ -497,6 +508,9 @@ c_value_print (val, stream, format, pretty)
|
|||
/* create a reference type referencing the real type */
|
||||
type = lookup_reference_type (real_type);
|
||||
}
|
||||
/* JYG: Need to adjust pointer value. */
|
||||
val->aligner.contents[0] -= top;
|
||||
|
||||
/* Note: When we look up RTTI entries, we don't get any
|
||||
information on const or volatile attributes */
|
||||
}
|
||||
|
|
60
gdb/eval.c
60
gdb/eval.c
|
@ -37,6 +37,9 @@ extern int hp_som_som_object_present;
|
|||
/* This is defined in valops.c */
|
||||
extern int overload_resolution;
|
||||
|
||||
/* JYG: lookup rtti type of STRUCTOP_PTR when this is set to continue
|
||||
on with successful lookup for member/method of the rtti type. */
|
||||
extern int objectprint;
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
|
||||
|
@ -428,32 +431,16 @@ evaluate_subexp_standard (expect_type, exp, pos, noside)
|
|||
(*pos) += 3;
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
{
|
||||
struct symbol *sym = exp->elts[pc + 2].symbol;
|
||||
enum lval_type lv;
|
||||
|
||||
switch (SYMBOL_CLASS (sym))
|
||||
{
|
||||
case LOC_CONST:
|
||||
case LOC_LABEL:
|
||||
case LOC_CONST_BYTES:
|
||||
lv = not_lval;
|
||||
break;
|
||||
/* JYG: We used to just return value_zero of the symbol type
|
||||
if we're asked to avoid side effects. Otherwise we return
|
||||
value_of_variable (...). However I'm not sure if
|
||||
value_of_variable () has any side effect.
|
||||
We need a full value object returned here for whatis_exp ()
|
||||
to call evaluate_type () and then pass the full value to
|
||||
value_rtti_target_type () if we are dealing with a pointer
|
||||
or reference to a base class and print object is on. */
|
||||
|
||||
case LOC_REGISTER:
|
||||
case LOC_REGPARM:
|
||||
lv = lval_register;
|
||||
break;
|
||||
|
||||
default:
|
||||
lv = lval_memory;
|
||||
break;
|
||||
}
|
||||
|
||||
return value_zero (SYMBOL_TYPE (sym), lv);
|
||||
}
|
||||
else
|
||||
return value_of_variable (exp->elts[pc + 2].symbol,
|
||||
exp->elts[pc + 1].block);
|
||||
|
||||
|
@ -1051,6 +1038,31 @@ evaluate_subexp_standard (expect_type, exp, pos, noside)
|
|||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
|
||||
/* JYG: if print object is on we need to replace the base type
|
||||
with rtti type in order to continue on with successful
|
||||
lookup of member / method only available in the rtti type. */
|
||||
{
|
||||
struct type *type = VALUE_TYPE (arg1);
|
||||
struct type *real_type;
|
||||
int full, top, using_enc;
|
||||
|
||||
if (objectprint && TYPE_TARGET_TYPE(type) &&
|
||||
(TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
|
||||
{
|
||||
real_type = value_rtti_target_type (arg1, &full, &top, &using_enc);
|
||||
if (real_type)
|
||||
{
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||||
real_type = lookup_pointer_type (real_type);
|
||||
else
|
||||
real_type = lookup_reference_type (real_type);
|
||||
|
||||
arg1 = value_cast (real_type, arg1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
|
||||
&exp->elts[pc + 2].string,
|
||||
|
|
|
@ -1484,11 +1484,11 @@ check_stub_method (type, method_id, signature_id)
|
|||
argtypetext = p;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '(')
|
||||
if (*p == '(' || *p == '<')
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
else if (*p == ')')
|
||||
else if (*p == ')' || *p == '>')
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
|
@ -1527,11 +1527,11 @@ check_stub_method (type, method_id, signature_id)
|
|||
argtypetext = p + 1;
|
||||
}
|
||||
|
||||
if (*p == '(')
|
||||
if (*p == '(' || *p == '<')
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
else if (*p == ')')
|
||||
else if (*p == ')' || *p == '>')
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
|
@ -2199,6 +2199,16 @@ rank_one_type (parm, arg)
|
|||
if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
|
||||
arg = check_typedef (arg);
|
||||
|
||||
/*
|
||||
Well, damnit, if the names are exactly the same,
|
||||
i'll say they are exactly the same. This happens when we generate
|
||||
method stubs. The types won't point to the same address, but they
|
||||
really are the same.
|
||||
*/
|
||||
|
||||
if (TYPE_NAME (parm) == TYPE_NAME (arg))
|
||||
return 0;
|
||||
|
||||
/* Check if identical after resolving typedefs */
|
||||
if (parm == arg)
|
||||
return 0;
|
||||
|
|
|
@ -82,6 +82,7 @@ whatis_exp (exp, show)
|
|||
register value_ptr val;
|
||||
register struct cleanup *old_chain = NULL;
|
||||
struct type *real_type = NULL;
|
||||
struct type *type;
|
||||
int full = 0;
|
||||
int top = -1;
|
||||
int using_enc = 0;
|
||||
|
@ -96,17 +97,40 @@ whatis_exp (exp, show)
|
|||
else
|
||||
val = access_value_history (0);
|
||||
|
||||
type = VALUE_TYPE (val);
|
||||
|
||||
if (objectprint)
|
||||
{
|
||||
if (((TYPE_CODE (type) == TYPE_CODE_PTR) ||
|
||||
(TYPE_CODE (type) == TYPE_CODE_REF))
|
||||
&&
|
||||
(TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
|
||||
{
|
||||
real_type = value_rtti_target_type (val, &full, &top, &using_enc);
|
||||
if (real_type)
|
||||
{
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||||
real_type = lookup_pointer_type (real_type);
|
||||
else
|
||||
real_type = lookup_reference_type (real_type);
|
||||
}
|
||||
}
|
||||
else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
|
||||
real_type = value_rtti_type (val, &full, &top, &using_enc);
|
||||
}
|
||||
|
||||
printf_filtered ("type = ");
|
||||
|
||||
if (real_type && objectprint)
|
||||
printf_filtered ("/* real type = %s%s */\n",
|
||||
TYPE_NAME (real_type),
|
||||
full ? "" : " (incomplete object)");
|
||||
/* FIXME: maybe better to use type_print (real_type, "", gdb_stdout, -1); */
|
||||
if (real_type)
|
||||
{
|
||||
printf_filtered ("/* real type = ");
|
||||
type_print (real_type, "", gdb_stdout, -1);
|
||||
if (! full)
|
||||
printf_filtered (" (incomplete object)");
|
||||
printf_filtered (" */\n");
|
||||
}
|
||||
|
||||
type_print (VALUE_TYPE (val), "", gdb_stdout, show);
|
||||
type_print (type, "", gdb_stdout, show);
|
||||
printf_filtered ("\n");
|
||||
|
||||
if (exp)
|
||||
|
|
312
gdb/valops.c
312
gdb/valops.c
|
@ -38,7 +38,7 @@
|
|||
value operations with HP aCC code/runtime. */
|
||||
extern int hp_som_som_object_present;
|
||||
|
||||
|
||||
extern int overload_debug;
|
||||
/* Local functions. */
|
||||
|
||||
static int typecmp PARAMS ((int staticp, struct type * t1[], value_ptr t2[]));
|
||||
|
@ -324,6 +324,12 @@ value_cast (type, arg2)
|
|||
value_ptr 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;
|
||||
|
@ -411,14 +417,14 @@ value_zero (type, lv)
|
|||
return val;
|
||||
}
|
||||
|
||||
/* Return a value with type TYPE located at ADDR.
|
||||
/* Return a value with type TYPE located at ADDR.
|
||||
|
||||
Call value_at only if the data needs to be fetched immediately;
|
||||
if we can be 'lazy' and defer the fetch, perhaps indefinately, call
|
||||
value_at_lazy instead. value_at_lazy simply records the address of
|
||||
the data and sets the lazy-evaluation-required flag. The lazy flag
|
||||
is tested in the VALUE_CONTENTS macro, which is used if and when
|
||||
the contents are actually required.
|
||||
the data and sets the lazy-evaluation-required flag. The lazy flag
|
||||
is tested in the VALUE_CONTENTS macro, which is used if and when
|
||||
the contents are actually required.
|
||||
|
||||
Note: value_at does *NOT* handle embedded offsets; perform such
|
||||
adjustments before or after calling it. */
|
||||
|
@ -491,9 +497,9 @@ value_at_lazy (type, addr, sect)
|
|||
return val;
|
||||
}
|
||||
|
||||
/* Called only from the VALUE_CONTENTS and VALUE_CONTENTS_ALL macros,
|
||||
if the current data for a variable needs to be loaded into
|
||||
VALUE_CONTENTS(VAL). Fetches the data from the user's process, and
|
||||
/* Called only from the VALUE_CONTENTS and VALUE_CONTENTS_ALL macros,
|
||||
if the current data for a variable needs to be loaded into
|
||||
VALUE_CONTENTS(VAL). Fetches the data from the user's process, and
|
||||
clears the lazy flag to indicate that the data in the buffer is valid.
|
||||
|
||||
If the value is zero-length, we avoid calling read_memory, which would
|
||||
|
@ -1131,7 +1137,7 @@ default_push_arguments (nargs, args, sp, struct_return, struct_addr)
|
|||
#ifndef COERCE_FLOAT_TO_DOUBLE
|
||||
#define COERCE_FLOAT_TO_DOUBLE(formal, actual) \
|
||||
(default_coerce_float_to_double ((formal), (actual)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* A default function for COERCE_FLOAT_TO_DOUBLE: do the coercion only
|
||||
|
@ -1244,7 +1250,7 @@ value_arg_coerce (arg, param_type, is_prototyped)
|
|||
return value_cast (type, 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. */
|
||||
|
||||
static CORE_ADDR
|
||||
|
@ -1335,7 +1341,7 @@ hand_function_call (function, nargs, args)
|
|||
/* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
|
||||
is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
|
||||
and remove any extra bytes which might exist because ULONGEST is
|
||||
bigger than REGISTER_SIZE.
|
||||
bigger than REGISTER_SIZE.
|
||||
|
||||
NOTE: This is pretty wierd, as the call dummy is actually a
|
||||
sequence of instructions. But CISC machines will have
|
||||
|
@ -1484,13 +1490,13 @@ hand_function_call (function, nargs, args)
|
|||
args[i] = value_arg_coerce (args[i], param_type, is_prototyped);
|
||||
}
|
||||
|
||||
/*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
|
||||
/*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
|
||||
is the address of a function and not a pointer to function variable.
|
||||
In aCC compiled code, the calls through pointers to functions (in the body
|
||||
of the function called by hand) are made via $$dyncall_external which
|
||||
requires some registers setting, this is taken care of if we call
|
||||
via a function pointer variable, but not via a function address.
|
||||
requires some registers setting, this is taken care of if we call
|
||||
via a function pointer variable, but not via a function address.
|
||||
In cc this is not a problem. */
|
||||
|
||||
if (using_gcc == 0)
|
||||
|
@ -1498,10 +1504,10 @@ hand_function_call (function, nargs, args)
|
|||
/* 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)
|
||||
/* elz: FIXME here should go the test about the compiler used
|
||||
/* 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.
|
||||
If we used HP's cc, then there is no problem and no need
|
||||
message only if the compiler used was HP's aCC.
|
||||
If we used HP's cc, then there is no problem and no need
|
||||
to return at this point */
|
||||
if (using_gcc == 0) /* && compiler == aCC */
|
||||
/* go see if the actual parameter is a variable of type
|
||||
|
@ -1611,7 +1617,7 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
|
|||
|
||||
/* elz: on HPPA no need for this extra alignment, maybe it is needed
|
||||
on other architectures. This is because all the alignment is taken care
|
||||
of in the above code (ifdef REG_STRUCT_HAS_ADDR) and in
|
||||
of in the above code (ifdef REG_STRUCT_HAS_ADDR) and in
|
||||
hppa_push_arguments */
|
||||
#ifndef NO_EXTRA_ALIGNMENT_NEEDED
|
||||
|
||||
|
@ -1642,7 +1648,7 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
|
|||
function. Since this doesn't actually involve executing a JSR/BSR
|
||||
instruction, the return address must be set up by hand, either by
|
||||
pushing onto the stack or copying into a return-address register
|
||||
as appropriate. Formerly this has been done in PUSH_ARGUMENTS,
|
||||
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);
|
||||
|
@ -1677,7 +1683,7 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
|
|||
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
|
||||
Also note that on some machines (like the sparc) pcc uses a
|
||||
convention like gcc's. */
|
||||
|
||||
if (struct_return)
|
||||
|
@ -2270,7 +2276,7 @@ find_rt_vbase_offset (type, basetype, valaddr, offset, boffset_p, skip_p)
|
|||
* virtual base entries. Offset is negative -- virtual base entries
|
||||
* appear _before_ the address point of the virtual table. */
|
||||
|
||||
/* pai: FIXME -- 32x64 problem, if word = 8 bytes, change multiplier
|
||||
/* pai: FIXME -- 32x64 problem, if word = 8 bytes, change multiplier
|
||||
& use long type */
|
||||
|
||||
/* epstein : FIXME -- added param for overlay section. May not be correct */
|
||||
|
@ -2775,7 +2781,7 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
|
|||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
if (TYPE_FN_FIELD_STUB (f, j))
|
||||
if (TYPE_FN_FIELD_STUB (f, j) && (!strcmp_iw (TYPE_FN_FIELDLIST_NAME (domain,i),name)))
|
||||
check_stub_method (domain, i, j);
|
||||
}
|
||||
}
|
||||
|
@ -2863,19 +2869,17 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
|
|||
break;
|
||||
}
|
||||
free (parm_types);
|
||||
#ifdef DEBUG_OLOAD
|
||||
/* FIXME: cagney/2000-03-12: Send the output to gdb_stderr. See
|
||||
comments above about adding a ``set debug'' command. */
|
||||
if (overload_debug)
|
||||
{
|
||||
if (method)
|
||||
printf ("Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
|
||||
fprintf_filtered (gdb_stderr,"Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
|
||||
else
|
||||
printf ("Overloaded function instance %s # of parms %d\n", SYMBOL_DEMANGLED_NAME (oload_syms[ix]), nparms);
|
||||
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++)
|
||||
printf ("...Badness @ %d : %d\n", jj, bv->rank[jj]);
|
||||
printf ("Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
} /* end loop over all candidates */
|
||||
|
||||
/* NOTE: dan/2000-03-10: Seems to be a better idea to just pick one
|
||||
if they have the exact same goodness. This is because there is no
|
||||
way to differentiate based on return type, which we need to in
|
||||
|
@ -3207,11 +3211,8 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype)
|
|||
* USING_ENC is the flag that distinguishes the two cases.
|
||||
* If it is 1, then the offset is for the enclosing object,
|
||||
* otherwise for the embedded object.
|
||||
*
|
||||
* This currently works only for RTTI information generated
|
||||
* by the HP ANSI C++ compiler (aCC). g++ today (1997-06-10)
|
||||
* does not appear to support RTTI. This function returns a
|
||||
* NULL value for objects in the g++ runtime model. */
|
||||
*
|
||||
*/
|
||||
|
||||
struct type *
|
||||
value_rtti_type (v, full, top, using_enc)
|
||||
|
@ -3241,87 +3242,184 @@ value_rtti_type (v, full, top, using_enc)
|
|||
/* RTTI works only or class objects */
|
||||
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
|
||||
return NULL;
|
||||
|
||||
/* If neither the declared type nor the enclosing type of the
|
||||
* value structure has a HP ANSI C++ style virtual table,
|
||||
* we can't do anything. */
|
||||
if (!TYPE_HAS_VTABLE (known_type))
|
||||
if (TYPE_HAS_VTABLE(known_type))
|
||||
{
|
||||
known_type = VALUE_ENCLOSING_TYPE (v);
|
||||
CHECK_TYPEDEF (known_type);
|
||||
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
|
||||
!TYPE_HAS_VTABLE (known_type))
|
||||
return NULL; /* No RTTI, or not HP-compiled types */
|
||||
CHECK_TYPEDEF (known_type);
|
||||
using_enclosing = 1;
|
||||
}
|
||||
/* If neither the declared type nor the enclosing type of the
|
||||
* value structure has a HP ANSI C++ style virtual table,
|
||||
* we can't do anything. */
|
||||
if (!TYPE_HAS_VTABLE (known_type))
|
||||
{
|
||||
known_type = VALUE_ENCLOSING_TYPE (v);
|
||||
CHECK_TYPEDEF (known_type);
|
||||
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
|
||||
!TYPE_HAS_VTABLE (known_type))
|
||||
return NULL; /* No RTTI, or not HP-compiled types */
|
||||
CHECK_TYPEDEF (known_type);
|
||||
using_enclosing = 1;
|
||||
}
|
||||
|
||||
if (using_enclosing && using_enc)
|
||||
*using_enc = 1;
|
||||
if (using_enclosing && using_enc)
|
||||
*using_enc = 1;
|
||||
|
||||
/* First get the virtual table address */
|
||||
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
|
||||
+ VALUE_OFFSET (v)
|
||||
+ (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
|
||||
if (coreptr == 0)
|
||||
return NULL; /* return silently -- maybe called on gdb-generated value */
|
||||
/* First get the virtual table address */
|
||||
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
|
||||
+ VALUE_OFFSET (v)
|
||||
+ (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
|
||||
if (coreptr == 0)
|
||||
return NULL; /* return silently -- maybe called on gdb-generated value */
|
||||
|
||||
/* Fetch the top offset of the object */
|
||||
/* FIXME possible 32x64 problem with pointer size & arithmetic */
|
||||
vp = value_at (builtin_type_int,
|
||||
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
|
||||
VALUE_BFD_SECTION (v));
|
||||
top_offset = value_as_long (vp);
|
||||
if (top)
|
||||
*top = top_offset;
|
||||
/* Fetch the top offset of the object */
|
||||
/* FIXME possible 32x64 problem with pointer size & arithmetic */
|
||||
vp = value_at (builtin_type_int,
|
||||
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
|
||||
VALUE_BFD_SECTION (v));
|
||||
top_offset = value_as_long (vp);
|
||||
if (top)
|
||||
*top = top_offset;
|
||||
|
||||
/* Fetch the typeinfo pointer */
|
||||
/* FIXME possible 32x64 problem with pointer size & arithmetic */
|
||||
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
|
||||
/* Indirect through the typeinfo pointer and retrieve the pointer
|
||||
* to the string name */
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
if (!coreptr)
|
||||
error ("Retrieved null typeinfo pointer in trying to determine run-time type");
|
||||
vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
|
||||
/* FIXME possible 32x64 problem */
|
||||
/* Fetch the typeinfo pointer */
|
||||
/* FIXME possible 32x64 problem with pointer size & arithmetic */
|
||||
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
|
||||
/* Indirect through the typeinfo pointer and retrieve the pointer
|
||||
* to the string name */
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
if (!coreptr)
|
||||
error ("Retrieved null typeinfo pointer in trying to determine run-time type");
|
||||
vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
|
||||
/* FIXME possible 32x64 problem */
|
||||
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
|
||||
read_memory_string (coreptr, rtti_type_name, 256);
|
||||
read_memory_string (coreptr, rtti_type_name, 256);
|
||||
|
||||
if (strlen (rtti_type_name) == 0)
|
||||
error ("Retrieved null type name from typeinfo");
|
||||
if (strlen (rtti_type_name) == 0)
|
||||
error ("Retrieved null type name from typeinfo");
|
||||
|
||||
/* search for type */
|
||||
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
|
||||
/* search for type */
|
||||
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
|
||||
|
||||
if (!rtti_type)
|
||||
error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
|
||||
CHECK_TYPEDEF (rtti_type);
|
||||
|
||||
#if 0 /* debugging */
|
||||
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
|
||||
if (!rtti_type)
|
||||
error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
|
||||
CHECK_TYPEDEF (rtti_type);
|
||||
#if 0
|
||||
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
|
||||
#endif
|
||||
/* Check whether we have the entire object */
|
||||
if (full /* Non-null pointer passed */
|
||||
&&
|
||||
/* Either we checked on the whole object in hand and found the
|
||||
top offset to be zero */
|
||||
(((top_offset == 0) &&
|
||||
using_enclosing &&
|
||||
TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
|
||||
||
|
||||
/* Or we checked on the embedded object and top offset was the
|
||||
same as the embedded offset */
|
||||
((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
|
||||
!using_enclosing &&
|
||||
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
|
||||
|
||||
/* Check whether we have the entire object */
|
||||
if (full /* Non-null pointer passed */
|
||||
*full = 1;
|
||||
}
|
||||
else
|
||||
/*
|
||||
Right now this is G++ RTTI. Plan on this changing in the
|
||||
future as i get around to setting the vtables properly for G++
|
||||
compiled stuff. Also, i'll be using the type info functions,
|
||||
which are always right. Deal with it until then.
|
||||
*/
|
||||
{
|
||||
CORE_ADDR vtbl;
|
||||
struct minimal_symbol *minsym;
|
||||
struct symbol *sym;
|
||||
char *demangled_name;
|
||||
struct type *btype;
|
||||
/* If the type has no vptr fieldno, try to get it filled in */
|
||||
if (TYPE_VPTR_FIELDNO(known_type) < 0)
|
||||
fill_in_vptr_fieldno(known_type);
|
||||
|
||||
&&
|
||||
/* Either we checked on the whole object in hand and found the
|
||||
top offset to be zero */
|
||||
(((top_offset == 0) &&
|
||||
using_enclosing &&
|
||||
TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
|
||||
||
|
||||
/* Or we checked on the embedded object and top offset was the
|
||||
same as the embedded offset */
|
||||
((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
|
||||
!using_enclosing &&
|
||||
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
|
||||
/* If we still can't find one, give up */
|
||||
if (TYPE_VPTR_FIELDNO(known_type) < 0)
|
||||
return NULL;
|
||||
|
||||
*full = 1;
|
||||
/* Make sure our basetype and known type match, otherwise, cast
|
||||
so we can get at the vtable properly.
|
||||
*/
|
||||
btype = TYPE_VPTR_BASETYPE (known_type);
|
||||
CHECK_TYPEDEF (btype);
|
||||
if (btype != known_type )
|
||||
{
|
||||
v = value_cast (btype, v);
|
||||
if (using_enc)
|
||||
*using_enc=1;
|
||||
}
|
||||
/*
|
||||
We can't use value_ind here, because it would want to use RTTI, and
|
||||
we'd waste a bunch of time figuring out we already know the type.
|
||||
Besides, we don't care about the type, just the actual pointer
|
||||
*/
|
||||
if (VALUE_ADDRESS(value_field(v,TYPE_VPTR_FIELDNO(known_type))) == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
If we are enclosed by something that isn't us, adjust the
|
||||
address properly and set using_enclosing.
|
||||
*/
|
||||
if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
|
||||
{
|
||||
value_ptr tempval;
|
||||
tempval=value_field(v,TYPE_VPTR_FIELDNO(known_type));
|
||||
VALUE_ADDRESS(tempval)+=(TYPE_BASECLASS_BITPOS(known_type,TYPE_VPTR_FIELDNO(known_type))/8);
|
||||
vtbl=value_as_pointer(tempval);
|
||||
using_enclosing=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
|
||||
using_enclosing=0;
|
||||
}
|
||||
|
||||
/* Try to find a symbol that is the vtable */
|
||||
minsym=lookup_minimal_symbol_by_pc(vtbl);
|
||||
if (minsym==NULL || (demangled_name=SYMBOL_NAME(minsym))==NULL || !VTBL_PREFIX_P(demangled_name))
|
||||
return NULL;
|
||||
|
||||
/* If we just skip the prefix, we get screwed by namespaces */
|
||||
demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
|
||||
*(strchr(demangled_name,' '))=0;
|
||||
|
||||
/* Lookup the type for the name */
|
||||
rtti_type=lookup_typename(demangled_name, (struct block *)0,1);
|
||||
|
||||
if (rtti_type==NULL)
|
||||
return NULL;
|
||||
|
||||
if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
|
||||
{
|
||||
if (top)
|
||||
*top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
|
||||
if (top && ((*top) >0))
|
||||
{
|
||||
if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
|
||||
{
|
||||
if (full)
|
||||
*full=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (full)
|
||||
*full=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (full)
|
||||
*full=1;
|
||||
}
|
||||
if (using_enc)
|
||||
*using_enc=using_enclosing;
|
||||
}
|
||||
return rtti_type;
|
||||
}
|
||||
|
||||
|
@ -3568,10 +3666,10 @@ varying_to_slice (varray)
|
|||
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
|
||||
that figures out precision inteligently as opposed to assuming
|
||||
/* 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
|
||||
that figures out precision inteligently as opposed to assuming
|
||||
doubles. FIXME: fmb */
|
||||
|
||||
value_ptr
|
||||
|
|
110
gdb/values.c
110
gdb/values.c
|
@ -892,7 +892,7 @@ value_fn_field (arg1p, f, j, type, offset)
|
|||
*arg1p = value_ind (value_cast (lookup_pointer_type (type),
|
||||
value_addr (*arg1p)));
|
||||
|
||||
/* Move the `this' pointer according to the offset.
|
||||
/* Move the `this' pointer according to the offset.
|
||||
VALUE_OFFSET (*arg1p) += offset;
|
||||
*/
|
||||
}
|
||||
|
@ -1102,7 +1102,12 @@ value_virtual_fn_field (arg1p, f, j, type, offset)
|
|||
return the most derived type we find. The caller must
|
||||
be satisfied when the return value == DTYPE.
|
||||
|
||||
FIXME-tiemann: should work with dossier entries as well. */
|
||||
FIXME-tiemann: should work with dossier entries as well.
|
||||
NOTICE - djb: I see no good reason at all to keep this function now that
|
||||
we have RTTI support. It's used in literally one place, and it's
|
||||
hard to keep this function up to date when it's purpose is served
|
||||
by value_rtti_type efficiently.
|
||||
Consider it gone for 5.1. */
|
||||
|
||||
static value_ptr
|
||||
value_headof (in_arg, btype, dtype)
|
||||
|
@ -1110,12 +1115,8 @@ value_headof (in_arg, btype, dtype)
|
|||
struct type *btype, *dtype;
|
||||
{
|
||||
/* First collect the vtables we must look at for this object. */
|
||||
/* FIXME-tiemann: right now, just look at top-most vtable. */
|
||||
value_ptr arg, vtbl, entry, best_entry = 0;
|
||||
int i, nelems;
|
||||
int offset, best_offset = 0;
|
||||
value_ptr arg, vtbl;
|
||||
struct symbol *sym;
|
||||
CORE_ADDR pc_for_sym;
|
||||
char *demangled_name;
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
|
@ -1123,72 +1124,45 @@ value_headof (in_arg, btype, dtype)
|
|||
CHECK_TYPEDEF (btype);
|
||||
arg = in_arg;
|
||||
if (btype != dtype)
|
||||
arg = value_cast (lookup_pointer_type (btype), arg);
|
||||
arg = value_cast (lookup_pointer_type (btype), arg);
|
||||
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF)
|
||||
{
|
||||
/*
|
||||
* Copy the value, but change the type from (T&) to (T*).
|
||||
* We keep the same location information, which is efficient,
|
||||
* and allows &(&X) to get the location containing the reference.
|
||||
*/
|
||||
arg = value_copy (arg);
|
||||
VALUE_TYPE (arg) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg)));
|
||||
}
|
||||
if (VALUE_ADDRESS(value_field (value_ind(arg), TYPE_VPTR_FIELDNO (btype)))==0)
|
||||
return arg;
|
||||
|
||||
vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
|
||||
/* Turn vtable into typeinfo function */
|
||||
VALUE_OFFSET(vtbl)+=4;
|
||||
|
||||
/* Check that VTBL looks like it points to a virtual function table. */
|
||||
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
|
||||
msymbol = lookup_minimal_symbol_by_pc ( value_as_pointer(value_ind(vtbl)) );
|
||||
if (msymbol == NULL
|
||||
|| (demangled_name = SYMBOL_NAME (msymbol)) == NULL
|
||||
|| !VTBL_PREFIX_P (demangled_name))
|
||||
{
|
||||
/* If we expected to find a vtable, but did not, let the user
|
||||
know that we aren't happy, but don't throw an error.
|
||||
FIXME: there has to be a better way to do this. */
|
||||
struct type *error_type = (struct type *) xmalloc (sizeof (struct type));
|
||||
memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
|
||||
TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
|
||||
VALUE_TYPE (in_arg) = error_type;
|
||||
return in_arg;
|
||||
}
|
||||
|| (demangled_name = SYMBOL_NAME (msymbol)) == NULL)
|
||||
{
|
||||
/* If we expected to find a vtable, but did not, let the user
|
||||
know that we aren't happy, but don't throw an error.
|
||||
FIXME: there has to be a better way to do this. */
|
||||
struct type *error_type = (struct type *) xmalloc (sizeof (struct type));
|
||||
memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
|
||||
TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
|
||||
VALUE_TYPE (in_arg) = error_type;
|
||||
return in_arg;
|
||||
}
|
||||
demangled_name = cplus_demangle(demangled_name,DMGL_ANSI);
|
||||
*(strchr (demangled_name, ' ')) = '\0';
|
||||
|
||||
/* Now search through the virtual function table. */
|
||||
entry = value_ind (vtbl);
|
||||
nelems = longest_to_int (value_as_long (value_field (entry, 2)));
|
||||
for (i = 1; i <= nelems; i++)
|
||||
{
|
||||
entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
|
||||
(LONGEST) i));
|
||||
/* This won't work if we're using thunks. */
|
||||
if (TYPE_CODE (check_typedef (VALUE_TYPE (entry))) != TYPE_CODE_STRUCT)
|
||||
break;
|
||||
offset = longest_to_int (value_as_long (value_field (entry, 0)));
|
||||
/* If we use '<=' we can handle single inheritance
|
||||
* where all offsets are zero - just use the first entry found. */
|
||||
if (offset <= best_offset)
|
||||
{
|
||||
best_offset = offset;
|
||||
best_entry = entry;
|
||||
}
|
||||
}
|
||||
/* Move the pointer according to BEST_ENTRY's offset, and figure
|
||||
out what type we should return as the new pointer. */
|
||||
if (best_entry == 0)
|
||||
{
|
||||
/* An alternative method (which should no longer be necessary).
|
||||
* But we leave it in for future use, when we will hopefully
|
||||
* have optimizes the vtable to use thunks instead of offsets. */
|
||||
/* Use the name of vtable itself to extract a base type. */
|
||||
demangled_name += 4; /* Skip _vt$ prefix. */
|
||||
}
|
||||
else
|
||||
{
|
||||
pc_for_sym = value_as_pointer (value_field (best_entry, 2));
|
||||
sym = find_pc_function (pc_for_sym);
|
||||
demangled_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ANSI);
|
||||
*(strchr (demangled_name, ':')) = '\0';
|
||||
}
|
||||
sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
|
||||
if (sym == NULL)
|
||||
error ("could not find type declaration for `%s'", demangled_name);
|
||||
if (best_entry)
|
||||
{
|
||||
free (demangled_name);
|
||||
arg = value_add (value_cast (builtin_type_int, arg),
|
||||
value_field (best_entry, 0));
|
||||
}
|
||||
else
|
||||
arg = in_arg;
|
||||
error ("could not find type declaration for `%s'", demangled_name);
|
||||
|
||||
arg = in_arg;
|
||||
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
|
||||
return arg;
|
||||
}
|
||||
|
@ -1458,7 +1432,7 @@ retry:
|
|||
}
|
||||
|
||||
/* Create a value for a string constant to be stored locally
|
||||
(not in the inferior's memory space, but in GDB memory).
|
||||
(not in the inferior's memory space, but in GDB memory).
|
||||
This is analogous to value_from_longest, which also does not
|
||||
use inferior memory. String shall NOT contain embedded nulls. */
|
||||
|
||||
|
|
Loading…
Reference in a new issue