C++ changes for 5.0, finally committed.

This commit is contained in:
Daniel Berlin
2000-04-04 04:53:50 +00:00
parent eb90a51f9d
commit 070ad9f02e
6 changed files with 341 additions and 209 deletions

View File

@@ -481,6 +481,17 @@ c_value_print (val, stream, format, pretty)
} }
else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS)) 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 */ /* Pointer to class, check real type of object */
fprintf_filtered (stream, "("); fprintf_filtered (stream, "(");
real_type = value_rtti_target_type (val, &full, &top, &using_enc); 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 */ /* create a reference type referencing the real type */
type = lookup_reference_type (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 /* Note: When we look up RTTI entries, we don't get any
information on const or volatile attributes */ information on const or volatile attributes */
} }

View File

@@ -37,6 +37,9 @@ extern int hp_som_som_object_present;
/* This is defined in valops.c */ /* This is defined in valops.c */
extern int overload_resolution; 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. */ /* Prototypes for local functions. */
@@ -428,32 +431,16 @@ evaluate_subexp_standard (expect_type, exp, pos, noside)
(*pos) += 3; (*pos) += 3;
if (noside == EVAL_SKIP) if (noside == EVAL_SKIP)
goto nosideret; goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct symbol *sym = exp->elts[pc + 2].symbol;
enum lval_type lv;
switch (SYMBOL_CLASS (sym)) /* JYG: We used to just return value_zero of the symbol type
{ if we're asked to avoid side effects. Otherwise we return
case LOC_CONST: value_of_variable (...). However I'm not sure if
case LOC_LABEL: value_of_variable () has any side effect.
case LOC_CONST_BYTES: We need a full value object returned here for whatis_exp ()
lv = not_lval; to call evaluate_type () and then pass the full value to
break; 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, return value_of_variable (exp->elts[pc + 2].symbol,
exp->elts[pc + 1].block); 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); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP) if (noside == EVAL_SKIP)
goto nosideret; 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) if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1), return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
&exp->elts[pc + 2].string, &exp->elts[pc + 2].string,

View File

@@ -1484,11 +1484,11 @@ check_stub_method (type, method_id, signature_id)
argtypetext = p; argtypetext = p;
while (*p) while (*p)
{ {
if (*p == '(') if (*p == '(' || *p == '<')
{ {
depth += 1; depth += 1;
} }
else if (*p == ')') else if (*p == ')' || *p == '>')
{ {
depth -= 1; depth -= 1;
} }
@@ -1527,11 +1527,11 @@ check_stub_method (type, method_id, signature_id)
argtypetext = p + 1; argtypetext = p + 1;
} }
if (*p == '(') if (*p == '(' || *p == '<')
{ {
depth += 1; depth += 1;
} }
else if (*p == ')') else if (*p == ')' || *p == '>')
{ {
depth -= 1; depth -= 1;
} }
@@ -2199,6 +2199,16 @@ rank_one_type (parm, arg)
if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF) if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
arg = check_typedef (arg); 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 */ /* Check if identical after resolving typedefs */
if (parm == arg) if (parm == arg)
return 0; return 0;

View File

@@ -82,6 +82,7 @@ whatis_exp (exp, show)
register value_ptr val; register value_ptr val;
register struct cleanup *old_chain = NULL; register struct cleanup *old_chain = NULL;
struct type *real_type = NULL; struct type *real_type = NULL;
struct type *type;
int full = 0; int full = 0;
int top = -1; int top = -1;
int using_enc = 0; int using_enc = 0;
@@ -96,17 +97,40 @@ whatis_exp (exp, show)
else else
val = access_value_history (0); 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); real_type = value_rtti_type (val, &full, &top, &using_enc);
}
printf_filtered ("type = "); printf_filtered ("type = ");
if (real_type && objectprint) if (real_type)
printf_filtered ("/* real type = %s%s */\n", {
TYPE_NAME (real_type), printf_filtered ("/* real type = ");
full ? "" : " (incomplete object)"); type_print (real_type, "", gdb_stdout, -1);
/* FIXME: maybe better to use 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"); printf_filtered ("\n");
if (exp) if (exp)

View File

@@ -38,7 +38,7 @@
value operations with HP aCC code/runtime. */ value operations with HP aCC code/runtime. */
extern int hp_som_som_object_present; extern int hp_som_som_object_present;
extern int overload_debug;
/* Local functions. */ /* Local functions. */
static int typecmp PARAMS ((int staticp, struct type * t1[], value_ptr t2[])); 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_ptr v2 = value_ind (arg2);
VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v) VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v)
+ VALUE_OFFSET (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); v2 = value_addr (v2);
VALUE_TYPE (v2) = type; VALUE_TYPE (v2) = type;
return v2; return v2;
@@ -411,14 +417,14 @@ value_zero (type, lv)
return val; 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; Call value_at only if the data needs to be fetched immediately;
if we can be 'lazy' and defer the fetch, perhaps indefinately, call if we can be 'lazy' and defer the fetch, perhaps indefinately, call
value_at_lazy instead. value_at_lazy simply records the address of value_at_lazy instead. value_at_lazy simply records the address of
the data and sets the lazy-evaluation-required flag. The lazy flag 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 is tested in the VALUE_CONTENTS macro, which is used if and when
the contents are actually required. the contents are actually required.
Note: value_at does *NOT* handle embedded offsets; perform such Note: value_at does *NOT* handle embedded offsets; perform such
adjustments before or after calling it. */ adjustments before or after calling it. */
@@ -491,9 +497,9 @@ value_at_lazy (type, addr, sect)
return val; return val;
} }
/* Called only from the VALUE_CONTENTS and VALUE_CONTENTS_ALL macros, /* Called only from the VALUE_CONTENTS and VALUE_CONTENTS_ALL macros,
if the current data for a variable needs to be loaded into if the current data for a variable needs to be loaded into
VALUE_CONTENTS(VAL). Fetches the data from the user's process, and 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. 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 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 #ifndef COERCE_FLOAT_TO_DOUBLE
#define COERCE_FLOAT_TO_DOUBLE(formal, actual) \ #define COERCE_FLOAT_TO_DOUBLE(formal, actual) \
(default_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 /* 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); 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. */ Calls error() if the function is not valid for calling. */
static CORE_ADDR 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 /* 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 is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
and remove any extra bytes which might exist because ULONGEST is 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 NOTE: This is pretty wierd, as the call dummy is actually a
sequence of instructions. But CISC machines will have 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); 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 /*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 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. 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 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 of the function called by hand) are made via $$dyncall_external which
requires some registers setting, this is taken care of if we call requires some registers setting, this is taken care of if we call
via a function pointer variable, but not via a function address. via a function pointer variable, but not via a function address.
In cc this is not a problem. */ In cc this is not a problem. */
if (using_gcc == 0) if (using_gcc == 0)
@@ -1498,10 +1504,10 @@ hand_function_call (function, nargs, args)
/* if this parameter is a pointer to function */ /* if this parameter is a pointer to function */
if (TYPE_CODE (param_type) == TYPE_CODE_PTR) if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
if (TYPE_CODE (param_type->target_type) == TYPE_CODE_FUNC) 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 to compile the target. We want to issue the error
message only if the compiler used was HP's aCC. message only if the compiler used was HP's aCC.
If we used HP's cc, then there is no problem and no need If we used HP's cc, then there is no problem and no need
to return at this point */ to return at this point */
if (using_gcc == 0) /* && compiler == aCC */ if (using_gcc == 0) /* && compiler == aCC */
/* go see if the actual parameter is a variable of type /* 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 /* 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 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 */ hppa_push_arguments */
#ifndef NO_EXTRA_ALIGNMENT_NEEDED #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 function. Since this doesn't actually involve executing a JSR/BSR
instruction, the return address must be set up by hand, either by instruction, the return address must be set up by hand, either by
pushing onto the stack or copying into a return-address register 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 but that's overloading its functionality a bit, so I'm making it
explicit to do it here. */ explicit to do it here. */
sp = PUSH_RETURN_ADDRESS (real_pc, sp); 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 doesn't cost us anything but space and if the function is pcc
it will ignore this value, we will make that assumption. 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. */ convention like gcc's. */
if (struct_return) 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 * virtual base entries. Offset is negative -- virtual base entries
* appear _before_ the address point of the virtual table. */ * 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 */ & use long type */
/* epstein : FIXME -- added param for overlay section. May not be correct */ /* 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++) 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); check_stub_method (domain, i, j);
} }
} }
@@ -2863,19 +2869,17 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
break; break;
} }
free (parm_types); free (parm_types);
#ifdef DEBUG_OLOAD if (overload_debug)
/* FIXME: cagney/2000-03-12: Send the output to gdb_stderr. See {
comments above about adding a ``set debug'' command. */
if (method) 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 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++) for (jj = 0; jj < nargs; jj++)
printf ("...Badness @ %d : %d\n", jj, bv->rank[jj]); fprintf_filtered (gdb_stderr,"...Badness @ %d : %d\n", jj, bv->rank[jj]);
printf ("Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous); fprintf_filtered (gdb_stderr,"Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
#endif }
} /* end loop over all candidates */ } /* end loop over all candidates */
/* NOTE: dan/2000-03-10: Seems to be a better idea to just pick one /* 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 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 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. * USING_ENC is the flag that distinguishes the two cases.
* If it is 1, then the offset is for the enclosing object, * If it is 1, then the offset is for the enclosing object,
* otherwise for the embedded 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 * struct type *
value_rtti_type (v, full, top, using_enc) 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 */ /* RTTI works only or class objects */
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS) if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
return NULL; return NULL;
if (TYPE_HAS_VTABLE(known_type))
/* 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); /* If neither the declared type nor the enclosing type of the
CHECK_TYPEDEF (known_type); * value structure has a HP ANSI C++ style virtual table,
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) || * we can't do anything. */
!TYPE_HAS_VTABLE (known_type)) if (!TYPE_HAS_VTABLE (known_type))
return NULL; /* No RTTI, or not HP-compiled types */ {
CHECK_TYPEDEF (known_type); known_type = VALUE_ENCLOSING_TYPE (v);
using_enclosing = 1; 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) if (using_enclosing && using_enc)
*using_enc = 1; *using_enc = 1;
/* First get the virtual table address */ /* First get the virtual table address */
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v)) coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
+ VALUE_OFFSET (v) + VALUE_OFFSET (v)
+ (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v))); + (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
if (coreptr == 0) if (coreptr == 0)
return NULL; /* return silently -- maybe called on gdb-generated value */ return NULL; /* return silently -- maybe called on gdb-generated value */
/* Fetch the top offset of the object */ /* Fetch the top offset of the object */
/* FIXME possible 32x64 problem with pointer size & arithmetic */ /* FIXME possible 32x64 problem with pointer size & arithmetic */
vp = value_at (builtin_type_int, vp = value_at (builtin_type_int,
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET, coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
VALUE_BFD_SECTION (v)); VALUE_BFD_SECTION (v));
top_offset = value_as_long (vp); top_offset = value_as_long (vp);
if (top) if (top)
*top = top_offset; *top = top_offset;
/* Fetch the typeinfo pointer */ /* Fetch the typeinfo pointer */
/* FIXME possible 32x64 problem with pointer size & arithmetic */ /* FIXME possible 32x64 problem with pointer size & arithmetic */
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v)); 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 /* Indirect through the typeinfo pointer and retrieve the pointer
* to the string name */ * to the string name */
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp)); coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
if (!coreptr) if (!coreptr)
error ("Retrieved null typeinfo pointer in trying to determine run-time type"); 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 */ vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
/* FIXME possible 32x64 problem */ /* 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) if (strlen (rtti_type_name) == 0)
error ("Retrieved null type name from typeinfo"); error ("Retrieved null type name from typeinfo");
/* search for type */ /* search for type */
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1); rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
if (!rtti_type) if (!rtti_type)
error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name); error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
CHECK_TYPEDEF (rtti_type); CHECK_TYPEDEF (rtti_type);
#if 0
#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);
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
#endif #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 */ *full = 1;
if (full /* Non-null pointer passed */ }
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);
&& /* If we still can't find one, give up */
/* Either we checked on the whole object in hand and found the if (TYPE_VPTR_FIELDNO(known_type) < 0)
top offset to be zero */ return NULL;
(((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))))
*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; return rtti_type;
} }
@@ -3568,10 +3666,10 @@ varying_to_slice (varray)
return value_slice (value_primitive_field (varray, 0, 1, vtype), 0, length); return value_slice (value_primitive_field (varray, 0, 1, vtype), 0, length);
} }
/* Create a value for a FORTRAN complex number. Currently most of /* Create a value for a FORTRAN complex number. Currently most of
the time values are coerced to COMPLEX*16 (i.e. a complex number the time values are coerced to COMPLEX*16 (i.e. a complex number
composed of 2 doubles. This really should be a smarter routine composed of 2 doubles. This really should be a smarter routine
that figures out precision inteligently as opposed to assuming that figures out precision inteligently as opposed to assuming
doubles. FIXME: fmb */ doubles. FIXME: fmb */
value_ptr value_ptr

View File

@@ -892,7 +892,7 @@ value_fn_field (arg1p, f, j, type, offset)
*arg1p = value_ind (value_cast (lookup_pointer_type (type), *arg1p = value_ind (value_cast (lookup_pointer_type (type),
value_addr (*arg1p))); value_addr (*arg1p)));
/* Move the `this' pointer according to the offset. /* Move the `this' pointer according to the offset.
VALUE_OFFSET (*arg1p) += 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 return the most derived type we find. The caller must
be satisfied when the return value == DTYPE. 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 static value_ptr
value_headof (in_arg, btype, dtype) value_headof (in_arg, btype, dtype)
@@ -1110,12 +1115,8 @@ value_headof (in_arg, btype, dtype)
struct type *btype, *dtype; struct type *btype, *dtype;
{ {
/* First collect the vtables we must look at for this object. */ /* 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;
value_ptr arg, vtbl, entry, best_entry = 0;
int i, nelems;
int offset, best_offset = 0;
struct symbol *sym; struct symbol *sym;
CORE_ADDR pc_for_sym;
char *demangled_name; char *demangled_name;
struct minimal_symbol *msymbol; struct minimal_symbol *msymbol;
@@ -1123,72 +1124,45 @@ value_headof (in_arg, btype, dtype)
CHECK_TYPEDEF (btype); CHECK_TYPEDEF (btype);
arg = in_arg; arg = in_arg;
if (btype != dtype) 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))); 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_as_pointer(value_ind(vtbl)) );
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
if (msymbol == NULL if (msymbol == NULL
|| (demangled_name = SYMBOL_NAME (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
/* 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.
know that we aren't happy, but don't throw an error. FIXME: there has to be a better way to do this. */
FIXME: there has to be a better way to do this. */ struct type *error_type = (struct type *) xmalloc (sizeof (struct type));
struct type *error_type = (struct type *) xmalloc (sizeof (struct type)); memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type)); TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *")); VALUE_TYPE (in_arg) = error_type;
VALUE_TYPE (in_arg) = error_type; return in_arg;
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); sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
if (sym == NULL) if (sym == NULL)
error ("could not find type declaration for `%s'", demangled_name); error ("could not find type declaration for `%s'", demangled_name);
if (best_entry)
{ arg = in_arg;
free (demangled_name);
arg = value_add (value_cast (builtin_type_int, arg),
value_field (best_entry, 0));
}
else
arg = in_arg;
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym)); VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg; return arg;
} }
@@ -1458,7 +1432,7 @@ retry:
} }
/* Create a value for a string constant to be stored locally /* 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 This is analogous to value_from_longest, which also does not
use inferior memory. String shall NOT contain embedded nulls. */ use inferior memory. String shall NOT contain embedded nulls. */