PR exp/12117
	* gdbtypes.c (check_typedef): Clean up function comment.
	Keep track of instance flags as we strip typedefs and create a new
	type to preserve them if necessary.
	* gdbtypes.h (type) <instance_flags>: Extend the comment.

gdb/testsuite/
	PR exp/12117
	* gdb.cp/ptype-cv-cp.cc: New file.
	* gdb.cp/ptype-cv-cp.exp: New file.
This commit is contained in:
Jan Kratochvil
2010-10-15 17:48:48 +00:00
parent 3917d5d5ca
commit 92163a10dc
6 changed files with 159 additions and 28 deletions

View File

@@ -1347,7 +1347,21 @@ stub_noname_complaint (void)
complaint (&symfile_complaints, _("stub type has NULL name"));
}
/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
/* Find the real type of TYPE. This function returns the real type,
after removing all layers of typedefs, and completing opaque or stub
types. Completion changes the TYPE argument, but stripping of
typedefs does not.
Instance flags (e.g. const/volatile) are preserved as typedefs are
stripped. If necessary a new qualified form of the underlying type
is created.
NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
not been computed and we're either in the middle of reading symbols, or
there was no name for the typedef in the debug info.
If TYPE is a TYPE_CODE_TYPEDEF, its length is updated to the length of
the target type.
If this is a stubbed struct (i.e. declared as struct foo *), see if
we can find a full definition in some other file. If so, copy this
@@ -1355,26 +1369,15 @@ stub_noname_complaint (void)
(but not any code) that if we don't find a full definition, we'd
set a flag so we don't spend time in the future checking the same
type. That would be a mistake, though--we might load in more
symbols which contain a full definition for the type.
This used to be coded as a macro, but I don't think it is called
often enough to merit such treatment.
Find the real type of TYPE. This function returns the real type,
after removing all layers of typedefs and completing opaque or stub
types. Completion changes the TYPE argument, but stripping of
typedefs does not.
If TYPE is a TYPE_CODE_TYPEDEF, its length is (also) set to the length of
the target type instead of zero. However, in the case of TYPE_CODE_TYPEDEF
check_typedef can still return different type than the original TYPE
pointer. */
symbols which contain a full definition for the type. */
struct type *
check_typedef (struct type *type)
{
struct type *orig_type = type;
int is_const, is_volatile;
/* While we're removing typedefs, we don't want to lose qualifiers.
E.g., const/volatile. */
int instance_flags = TYPE_INSTANCE_FLAGS (type);
gdb_assert (type);
@@ -1388,7 +1391,7 @@ check_typedef (struct type *type)
/* It is dangerous to call lookup_symbol if we are currently
reading a symtab. Infinite recursion is one danger. */
if (currently_reading_symtab)
return type;
return make_qualified_type (type, instance_flags, NULL);
name = type_name_no_tag (type);
/* FIXME: shouldn't we separately check the TYPE_NAME and
@@ -1398,7 +1401,7 @@ check_typedef (struct type *type)
if (name == NULL)
{
stub_noname_complaint ();
return type;
return make_qualified_type (type, instance_flags, NULL);
}
sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
if (sym)
@@ -1407,10 +1410,33 @@ check_typedef (struct type *type)
TYPE_TARGET_TYPE (type) = alloc_type_arch (get_type_arch (type));
}
type = TYPE_TARGET_TYPE (type);
}
is_const = TYPE_CONST (type);
is_volatile = TYPE_VOLATILE (type);
/* Preserve the instance flags as we traverse down the typedef chain.
Handling address spaces/classes is nasty, what do we do if there's a
conflict?
E.g., what if an outer typedef marks the type as class_1 and an inner
typedef marks the type as class_2?
This is the wrong place to do such error checking. We leave it to
the code that created the typedef in the first place to flag the
error. We just pick the outer address space (akin to letting the
outer cast in a chain of casting win), instead of assuming
"it can't happen". */
{
const int ALL_SPACES = (TYPE_INSTANCE_FLAG_CODE_SPACE
| TYPE_INSTANCE_FLAG_DATA_SPACE);
const int ALL_CLASSES = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL;
int new_instance_flags = TYPE_INSTANCE_FLAGS (type);
/* Treat code vs data spaces and address classes separately. */
if ((instance_flags & ALL_SPACES) != 0)
new_instance_flags &= ~ALL_SPACES;
if ((instance_flags & ALL_CLASSES) != 0)
new_instance_flags &= ~ALL_CLASSES;
instance_flags |= new_instance_flags;
}
}
/* If this is a struct/class/union with no fields, then check
whether a full definition exists somewhere else. This is for
@@ -1428,7 +1454,7 @@ check_typedef (struct type *type)
if (name == NULL)
{
stub_noname_complaint ();
return type;
return make_qualified_type (type, instance_flags, NULL);
}
newtype = lookup_transparent_type (name);
@@ -1445,7 +1471,9 @@ check_typedef (struct type *type)
move over any other types NEWTYPE refers to, which could
be an unbounded amount of stuff. */
if (TYPE_OBJFILE (newtype) == TYPE_OBJFILE (type))
make_cv_type (is_const, is_volatile, newtype, &type);
type = make_qualified_type (newtype,
TYPE_INSTANCE_FLAGS (type),
type);
else
type = newtype;
}
@@ -1464,17 +1492,18 @@ check_typedef (struct type *type)
if (name == NULL)
{
stub_noname_complaint ();
return type;
return make_qualified_type (type, instance_flags, NULL);
}
sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
if (sym)
{
/* Same as above for opaque types, we can replace the stub
with the complete type only if they are int the same
with the complete type only if they are in the same
objfile. */
if (TYPE_OBJFILE (SYMBOL_TYPE(sym)) == TYPE_OBJFILE (type))
make_cv_type (is_const, is_volatile,
SYMBOL_TYPE (sym), &type);
type = make_qualified_type (SYMBOL_TYPE (sym),
TYPE_INSTANCE_FLAGS (type),
type);
else
type = SYMBOL_TYPE (sym);
}
@@ -1534,8 +1563,12 @@ check_typedef (struct type *type)
TYPE_TARGET_STUB (type) = 0;
}
}
type = make_qualified_type (type, instance_flags, NULL);
/* Cache TYPE_LENGTH for future use. */
TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
return type;
}