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))
{
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 */
}

View file

@ -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,

View file

@ -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;

View file

@ -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)

View file

@ -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;
@ -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
@ -3208,10 +3212,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype)
* 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,7 +3242,8 @@ 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 (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. */
@ -3299,14 +3301,11 @@ value_rtti_type (v, full, top, using_enc)
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 */
#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 */
@ -3321,7 +3320,106 @@ value_rtti_type (v, full, top, using_enc)
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
*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);
/* If we still can't find one, give up */
if (TYPE_VPTR_FIELDNO(known_type) < 0)
return NULL;
/* 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;
}

View file

@ -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;
@ -1124,13 +1125,26 @@ value_headof (in_arg, btype, dtype)
arg = in_arg;
if (btype != dtype)
arg = value_cast (lookup_pointer_type (btype), arg);
vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
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;
/* Check that VTBL looks like it points to a virtual function table. */
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
/* Turn vtable into typeinfo function */
VALUE_OFFSET(vtbl)+=4;
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))
|| (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.
@ -1141,53 +1155,13 @@ value_headof (in_arg, btype, dtype)
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;
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;