[RFA] Fix gdb/277 by separating types

Daniel Jacobowitz
2002-05-13T00:53:59Z

This patch requires my previous cleanup patch. It fixes a test in
gdb.c++/method.exp for GCC 3.x/stabs+, and closes gdb/277.

Basically, I divide the type structure into two elements. One marks our
position on the ring of related types - I removed the separate AS and CV
rings, which could never have worked quite right. With them, a '@code const
int' and a 'const @code int' would be different types. Everything left in
the new TYPE_CORE_TYPE should be shared among all qualified versions of this
type, and also can be safely copied a la replace_type. replace_type is
still gross, but no longer runs much risk of being unsafe.

As a consequence of doing this properly, the grossness in finish_cv_type is
no longer necessary, so I deleted all traces of it.

No regressions on i386-linux, fixes the testcase mentioned above. OK to
commit?

--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer

2002-05-12 Daniel Jacobowitz <drow@mvista.com>

Fix PR gdb/277.
* gdbtypes.h: Update accessor macros to use TYPE_CORE_TYPE.
(TYPE_CONST, TYPE_VOLATILE, TYPE_CODE_SPACE, TYPE_DATA_SPACE): Use
TYPE_INSTANCE_FLAGS.
(struct type_core): New.
(struct type): Move most members to struct type_core. Change
cv_type and as_type to new type_chain member. Add instance_flags.
(TYPE_CORE_TYPE, TYPE_CHAIN, TYPE_INSTANCE_FLAGS): New macros.
(TYPE_CV_TYPE, TYPE_AS_TYPE): Remove.
(finish_cv_type): Remove prototype.
* gdbtypes.c (alloc_type): Update comment. Allocate TYPE_CORE_TYPE.
Set TYPE_CHAIN.
(alloc_type_instance): New function.
(smash_type): New function.
(make_pointer_type, make_reference_type, make_function_type)
(smash_to_member_type, smash_to_method_type): Call smash_type.
(make_qualified_type): New function.
(make_type_with_address_space): Call make_qualified_type.
(make_cv_type): Likewise.
(finish_cv_type): Remove unnecessary function.
(replace_type): Update comment. Copy TYPE_CORE_TYPE.
(recursive_dump_type): Dump TYPE_CHAIN and TYPE_INSTANCE_FLAGS;
remove TYPE_CV_TYPE and TYPE_AS_TYPE.
* c-typeprint.c (c_type_print_modifier): Use TYPE_INSTANCE_FLAGS.
* dwarf2read.c (read_structure_scope): Don't call finish_cv_type.
* hpread.c (hpread_read_struct_type): Likewise.
* stabsread.c (read_struct_type): Likewise.

diff -x *.orig -pur gdb.inter/c-typeprint.c gdb.real/c-typeprint.c
--- gdb.inter/c-typeprint.c Sun May 12 20:34:14 2002
+++ gdb.real/c-typeprint.c Sun May 12 02:58:37 2002
@@ -316,7 +316,7 @@ c_type_print_modifier (struct type *type
did_print_modifier = 1;
}

- address_space_id = address_space_int_to_name (TYPE_FLAGS (type));
+ address_space_id = address_space_int_to_name (TYPE_INSTANCE_FLAGS (type));
if (address_space_id)
{
if (did_print_modifier || need_pre_space)
diff -x *.orig -pur gdb.inter/dwarf2read.c gdb.real/dwarf2read.c
--- gdb.inter/dwarf2read.c Sun May 12 20:25:57 2002
+++ gdb.real/dwarf2read.c Sun May 12 19:35:06 2002
@@ -2486,8 +2486,6 @@ read_structure_scope (struct die_info *d
/* No children, must be stub. */
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
}
-
- finish_cv_type (die->type);
}

/* Given a pointer to a die which begins an enumeration, process all
diff -x *.orig -pur gdb.inter/gdbtypes.c gdb.real/gdbtypes.c
--- gdb.inter/gdbtypes.c Sun May 12 20:34:14 2002
+++ gdb.real/gdbtypes.c Sun May 12 20:04:07 2002
@@ -135,7 +135,8 @@ static void virtual_base_list_aux (struc

/* Alloc a new type structure and fill it with some defaults. If
OBJFILE is non-NULL, then allocate the space for the type structure
- in that objfile's type_obstack. */
+ in that objfile's type_obstack. Otherwise allocate the new type structure
+ by xmalloc () (for permanent types). */

struct type *
alloc_type (struct objfile *objfile)
@@ -147,26 +148,74 @@ alloc_type (struct objfile *objfile)
if (objfile == NULL)
{
type = (struct type *) xmalloc (sizeof (struct type));
+ memset ((char *) (type), 0, sizeof (struct type));
+ TYPE_CORE_TYPE (type) = xmalloc (sizeof (struct type_core));
}
else
{
type = (struct type *) obstack_alloc (&objfile->type_obstack,
sizeof (struct type));
+ memset ((char *) (type), 0, sizeof (struct type));
+ TYPE_CORE_TYPE (type)
+ = (struct type_core *) obstack_alloc (&objfile->type_obstack,
+ sizeof (struct type_core));
OBJSTAT (objfile, n_types++);
}
- memset ((char *) type, 0, sizeof (struct type));
+ memset ((char *) TYPE_CORE_TYPE (type), 0, sizeof (struct type_core));

/* Initialize the fields that might not be zero. */

TYPE_CODE (type) = TYPE_CODE_UNDEF;
TYPE_OBJFILE (type) = objfile;
TYPE_VPTR_FIELDNO (type) = -1;
- TYPE_CV_TYPE (type) = type; /* chain back to itself */
- TYPE_AS_TYPE (type) = type; /* ditto */
+ TYPE_CHAIN (type) = type; /* Chain back to itself. */

return (type);
}

+/* Alloc a new type instance structure, fill it with some defaults,
+ and point it at OLDTYPE. Allocate the new type instance from the
+ same place as OLDTYPE. */
+
+static struct type *
+alloc_type_instance (struct type *oldtype)
+{
+ struct type *type;
+
+ /* Allocate the structure. */
+
+ if (TYPE_OBJFILE (oldtype) == NULL)
+ {
+ type = (struct type *) xmalloc (sizeof (struct type));
+ memset ((char *) (type), 0, sizeof (struct type));
+ }
+ else
+ {
+ type = (struct type *)
+ obstack_alloc (&TYPE_OBJFILE (oldtype)->type_obstack,
+ sizeof (struct type));
+ memset ((char *) (type), 0, sizeof (struct type));
+ }
+ TYPE_CORE_TYPE (type) = TYPE_CORE_TYPE (oldtype);
+
+ TYPE_CHAIN (type) = type; /* Chain back to itself for now. */
+
+ return (type);
+}
+
+/* Clear all remnants of the previous type at TYPE, in preparation for
+ replacing it with something else. */
+static void
+smash_type (struct type *type)
+{
+ memset ((char *) TYPE_CORE_TYPE (type), 0, sizeof (struct type_core));
+
+ /* For now, delete the rings. */
+ TYPE_CHAIN (type) = type;
+
+ /* For now, leave the pointer/reference types alone. */
+}
+
/* Lookup a pointer to a type TYPE. TYPEPTR, if nonzero, points
to a pointer to memory where the pointer type should be stored.
If *TYPEPTR is zero, update it to point to the pointer type we return.
@@ -202,7 +251,7 @@ make_pointer_type (struct type *type, st
{
ntype = *typeptr;
objfile = TYPE_OBJFILE (ntype);
- memset ((char *) ntype, 0, sizeof (struct type));
+ smash_type (ntype);
TYPE_OBJFILE (ntype) = objfile;
}

@@ -269,7 +318,7 @@ make_reference_type (struct type *type,
{
ntype = *typeptr;
objfile = TYPE_OBJFILE (ntype);
- memset ((char *) ntype, 0, sizeof (struct type));
+ smash_type (ntype);
TYPE_OBJFILE (ntype) = objfile;
}

@@ -318,7 +367,7 @@ make_function_type (struct type *type, s
{
ntype = *typeptr;
objfile = TYPE_OBJFILE (ntype);
- memset ((char *) ntype, 0, sizeof (struct type));
+ smash_type (ntype);
TYPE_OBJFILE (ntype) = objfile;
}

@@ -368,45 +417,63 @@ address_space_int_to_name (int space_fla
return NULL;
}

-/* Make an address-space-delimited variant of a type -- a type that
- is identical to the one supplied except that it has an address
- space attribute attached to it (such as "code" or "data").
-
- This is for Harvard architectures. */
+/* Create a new type with instance flags NEW_FLAGS, based on TYPE.
+ If STORAGE is non-NULL, create the new type instance there. */

struct type *
-make_type_with_address_space (struct type *type, int space_flag)
+make_qualified_type (struct type *type, int new_flags,
+ struct type *storage)
{
struct type *ntype;

ntype = type;
do {
- if ((ntype->flags & space_flag) != 0)
+ if (TYPE_INSTANCE_FLAGS (ntype) == new_flags)
return ntype;
- ntype = TYPE_AS_TYPE (ntype);
+ ntype = TYPE_CHAIN (ntype);
} while (ntype != type);

- /* Create a new, duplicate type. */
- ntype = alloc_type (TYPE_OBJFILE (type));
- /* Copy original type. */
- memcpy ((char *) ntype, (char *) type, sizeof (struct type));
+ /* Create a new type instance. */
+ if (storage == NULL)
+ ntype = alloc_type_instance (type);
+ else
+ {
+ ntype = storage;
+ TYPE_CORE_TYPE (ntype) = TYPE_CORE_TYPE (type);
+ TYPE_CHAIN (ntype) = ntype;
+ }

/* Pointers or references to the original type are not relevant to
- the new type; but if the original type is a pointer, the new type
- points to the same thing (so TYPE_TARGET_TYPE remains unchanged). */
+ the new type. */
TYPE_POINTER_TYPE (ntype) = (struct type *) 0;
TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0;
- TYPE_CV_TYPE (ntype) = ntype;

- /* Chain the new address-space-specific type to the old type. */
- ntype->as_type = type->as_type;
- type->as_type = ntype;
+ /* Chain the new qualified type to the old type. */
+ TYPE_CHAIN (ntype) = TYPE_CHAIN (type);
+ TYPE_CHAIN (type) = ntype;
+
+ /* Now set the instance flags and return the new type. */
+ TYPE_INSTANCE_FLAGS (ntype) = new_flags;

- /* Now set the address-space flag, and return the new type. */
- ntype->flags |= space_flag;
return ntype;
}

+/* Make an address-space-delimited variant of a type -- a type that
+ is identical to the one supplied except that it has an address
+ space attribute attached to it (such as "code" or "data").
+
+ This is for Harvard architectures. */
+
+struct type *
+make_type_with_address_space (struct type *type, int space_flag)
+{
+ struct type *ntype;
+ int new_flags = ((TYPE_INSTANCE_FLAGS (type)
+ & ~(TYPE_FLAG_CODE_SPACE | TYPE_FLAG_DATA_SPACE))
+ | space_flag);
+
+ return make_qualified_type (type, new_flags, NULL);
+}

/* Make a "c-v" variant of a type -- a type that is identical to the
one supplied except that it may have const or volatile attributes
@@ -425,142 +492,49 @@ make_cv_type (int cnst, int voltl, struc
register struct type *tmp_type = type; /* tmp type */
struct objfile *objfile;

- ntype = TYPE_CV_TYPE (type);
-
- while (ntype != type)
- {
- if ((TYPE_CONST (ntype) == cnst) &&
- (TYPE_VOLATILE (ntype) == voltl))
- {
- if (typeptr == 0)
- return ntype;
- else if (*typeptr == 0)
- {
- *typeptr = ntype; /* Tracking alloc, and we have new type. */
- return ntype;
- }
- }
- tmp_type = ntype;
- ntype = TYPE_CV_TYPE (ntype);
- }
-
- if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
- {
- ntype = alloc_type (TYPE_OBJFILE (type));
- if (typeptr)
- *typeptr = ntype;
- }
- else
- /* We have storage, but need to reset it. */
- {
- ntype = *typeptr;
- objfile = TYPE_OBJFILE (ntype);
- /* memset ((char *) ntype, 0, sizeof (struct type)); */
- TYPE_OBJFILE (ntype) = objfile;
- }
+ int new_flags = (TYPE_INSTANCE_FLAGS (type)
+ & ~(TYPE_FLAG_CONST | TYPE_FLAG_VOLATILE));

- /* Copy original type */
- memcpy ((char *) ntype, (char *) type, sizeof (struct type));
- /* But zero out fields that shouldn't be copied */
- TYPE_POINTER_TYPE (ntype) = (struct type *) 0; /* Need new pointer kind */
- TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0; /* Need new referene kind */
- TYPE_AS_TYPE (ntype) = ntype; /* Need new address-space kind. */
- /* Note: TYPE_TARGET_TYPE can be left as is */
-
- /* Set flags appropriately */
if (cnst)
- TYPE_FLAGS (ntype) |= TYPE_FLAG_CONST;
- else
- TYPE_FLAGS (ntype) &= ~TYPE_FLAG_CONST;
+ new_flags |= TYPE_FLAG_CONST;

if (voltl)
- TYPE_FLAGS (ntype) |= TYPE_FLAG_VOLATILE;
- else
- TYPE_FLAGS (ntype) &= ~TYPE_FLAG_VOLATILE;
-
- /* Fix the chain of cv variants */
- TYPE_CV_TYPE (ntype) = type;
- TYPE_CV_TYPE (tmp_type) = ntype;
-
- return ntype;
-}
-
-/* When reading in a class type, we may have created references to
- cv-qualified versions of the type (in method arguments, for
- instance). Update everything on the cv ring from the primary
- type TYPE.
-
- The only reason we do not need to do the same thing for address
- spaces is that type readers do not create address space qualified
- types. */
-void
-finish_cv_type (struct type *type)
-{
- struct type *ntype, *cv_type, *ptr_type, *ref_type;
- int cv_flags;
-
- gdb_assert (!TYPE_CONST (type) && !TYPE_VOLATILE (type));
+ new_flags |= TYPE_FLAG_VOLATILE;

- ntype = type;
- while ((ntype = TYPE_CV_TYPE (ntype)) != type)
+ if (typeptr && *typeptr != NULL)
{
- /* Save cv_flags. */
- cv_flags = TYPE_FLAGS (ntype) & (TYPE_FLAG_VOLATILE | TYPE_FLAG_CONST);
-
- /* If any reference or pointer types were created, save them too. */
- ptr_type = TYPE_POINTER_TYPE (ntype);
- ref_type = TYPE_REFERENCE_TYPE (ntype);
-
- /* Don't disturb the CV chain. */
- cv_type = TYPE_CV_TYPE (ntype);
-
- /* Verify that we haven't added any address-space qualified types,
- for the future. */
- gdb_assert (ntype == TYPE_AS_TYPE (ntype));
-
- /* Copy original type */
- memcpy ((char *) ntype, (char *) type, sizeof (struct type));
+ /* Objfile is per-core-type. This const-qualified type had best
+ belong to the same objfile as the type it is qualifying... */
+ gdb_assert (TYPE_OBJFILE (*typeptr) == TYPE_OBJFILE (type));
+ }
+
+ ntype = make_qualified_type (type, new_flags, typeptr ? *typeptr : NULL);

- /* Restore everything. */
- TYPE_POINTER_TYPE (ntype) = ptr_type;
- TYPE_REFERENCE_TYPE (ntype) = ref_type;
- TYPE_CV_TYPE (ntype) = cv_type;
- TYPE_FLAGS (ntype) = TYPE_FLAGS (ntype) | cv_flags;
+ if (typeptr != NULL)
+ *typeptr = ntype;

- TYPE_AS_TYPE (ntype) = ntype;
- }
+ return ntype;
}

-/* Replace the contents of ntype with the type *type.
+/* Replace the contents of ntype with the type *type. This changes the
+ contents, rather than the pointer for TYPE_CORE_TYPE (ntype); thus
+ the changes are propogated to all types in the TYPE_CHAIN.

In order to build recursive types, it's inevitable that we'll need
to update types in place --- but this sort of indiscriminate
smashing is ugly, and needs to be replaced with something more
- controlled. For example, Daniel Jacobowitz has suggested moving
- the fields common to a set of c/v variants into their own object,
- which the variants would share.
-
- This function does not handle the replacement type being
- cv-qualified; it could be easily fixed to, but it would be better
- to just change the whole approach. */
+ controlled. TYPE_CORE_TYPE is a step in this direction; it's not
+ clear if more steps are needed. */
void
replace_type (struct type *ntype, struct type *type)
{
struct type *cv_chain, *as_chain, *ptr, *ref;

- cv_chain = TYPE_CV_TYPE (ntype);
- as_chain = TYPE_AS_TYPE (ntype);
- ptr = TYPE_POINTER_TYPE (ntype);
- ref = TYPE_REFERENCE_TYPE (ntype);
-
- *ntype = *type;
-
- TYPE_POINTER_TYPE (ntype) = ptr;
- TYPE_REFERENCE_TYPE (ntype) = ref;
- TYPE_CV_TYPE (ntype) = cv_chain;
- TYPE_AS_TYPE (ntype) = as_chain;
+ *TYPE_CORE_TYPE (ntype) = *TYPE_CORE_TYPE (type);

- finish_cv_type (ntype);
+ /* Assert that the two types have equivalent instance qualifiers.
+ This should be true for at least all of our debug readers. */
+ gdb_assert (TYPE_INSTANCE_FLAGS (ntype) == TYPE_INSTANCE_FLAGS (type));
}

/* Implement direct support for MEMBER_TYPE in GNU C++.
@@ -879,7 +853,7 @@ smash_to_member_type (struct type *type,

objfile = TYPE_OBJFILE (type);

- memset ((char *) type, 0, sizeof (struct type));
+ smash_type (type);
TYPE_OBJFILE (type) = objfile;
TYPE_TARGET_TYPE (type) = to_type;
TYPE_DOMAIN_TYPE (type) = domain;
@@ -902,7 +876,7 @@ smash_to_method_type (struct type *type,

objfile = TYPE_OBJFILE (type);

- memset ((char *) type, 0, sizeof (struct type));
+ smash_type (type);
TYPE_OBJFILE (type) = objfile;
TYPE_TARGET_TYPE (type) = to_type;
TYPE_DOMAIN_TYPE (type) = domain;
@@ -3011,13 +2985,11 @@ recursive_dump_type (struct type *type,
printfi_filtered (spaces, "reference_type ");
gdb_print_host_address (TYPE_REFERENCE_TYPE (type), gdb_stdout);
printf_filtered ("\n");
- printfi_filtered (spaces, "cv_type ");
- gdb_print_host_address (TYPE_CV_TYPE (type), gdb_stdout);
- printf_filtered ("\n");
- printfi_filtered (spaces, "as_type ");
- gdb_print_host_address (TYPE_AS_TYPE (type), gdb_stdout);
+ printfi_filtered (spaces, "type_chain ");
+ gdb_print_host_address (TYPE_CHAIN (type), gdb_stdout);
printf_filtered ("\n");
printfi_filtered (spaces, "flags 0x%x", TYPE_FLAGS (type));
+ printfi_filtered (spaces, "instance_flags 0x%x", TYPE_INSTANCE_FLAGS (type));
if (TYPE_UNSIGNED (type))
{
puts_filtered (" TYPE_FLAG_UNSIGNED");
diff -x *.orig -pur gdb.inter/gdbtypes.h gdb.real/gdbtypes.h
--- gdb.inter/gdbtypes.h Sun May 12 20:34:14 2002
+++ gdb.real/gdbtypes.h Sun May 12 19:34:42 2002
@@ -187,14 +187,14 @@ enum type_code
*/

#define TYPE_FLAG_CONST (1 << 5)
-#define TYPE_CONST(t) (TYPE_FLAGS (t) & TYPE_FLAG_CONST)
+#define TYPE_CONST(t) (TYPE_INSTANCE_FLAGS (t) & TYPE_FLAG_CONST)

/* Volatile type. If this is set, the corresponding type has a
* volatile modifier.
*/

#define TYPE_FLAG_VOLATILE (1 << 6)
-#define TYPE_VOLATILE(t) (TYPE_FLAGS (t) & TYPE_FLAG_VOLATILE)
+#define TYPE_VOLATILE(t) (TYPE_INSTANCE_FLAGS (t) & TYPE_FLAG_VOLATILE)

/* This is a function type which appears to have a prototype. We need this
@@ -235,10 +235,10 @@ enum type_code
is instruction space, and for data objects is data memory. */

#define TYPE_FLAG_CODE_SPACE (1 << 9)
-#define TYPE_CODE_SPACE(t) (TYPE_FLAGS (t) & TYPE_FLAG_CODE_SPACE)
+#define TYPE_CODE_SPACE(t) (TYPE_INSTANCE_FLAGS (t) & TYPE_FLAG_CODE_SPACE)

#define TYPE_FLAG_DATA_SPACE (1 << 10)
-#define TYPE_DATA_SPACE(t) (TYPE_FLAGS (t) & TYPE_FLAG_DATA_SPACE)
+#define TYPE_DATA_SPACE(t) (TYPE_INSTANCE_FLAGS (t) & TYPE_FLAG_DATA_SPACE)

/* FIXME: Kludge to mark a varargs function type for C++ member
function argument processing. Currently only used in dwarf2read.c,
@@ -254,238 +254,240 @@ enum type_code
#define TYPE_FLAG_VECTOR (1 << 12)
#define TYPE_VECTOR(t) (TYPE_FLAGS (t) & TYPE_FLAG_VECTOR)

+struct type_core
+{
+ /* Code for kind of type */
+
+ enum type_code code;
+
+ /* Name of this type, or NULL if none.
+
+ This is used for printing only, except by poorly designed C++ code.
+ For looking up a name, look for a symbol in the VAR_NAMESPACE. */
+
+ char *name;
+
+ /* Tag name for this type, or NULL if none. This means that the
+ name of the type consists of a keyword followed by the tag name.
+ Which keyword is determined by the type code ("struct" for
+ TYPE_CODE_STRUCT, etc.). As far as I know C/C++ are the only languages
+ with this feature.
+
+ This is used for printing only, except by poorly designed C++ code.
+ For looking up a name, look for a symbol in the STRUCT_NAMESPACE.
+ One more legitimate use is that if TYPE_FLAG_STUB is set, this is
+ the name to use to look for definitions in other files. */
+
+ char *tag_name;
+
+ /* Length of storage for a value of this type. This is what
+ sizeof(type) would return; use it for address arithmetic,
+ memory reads and writes, etc. This size includes padding. For
+ example, an i386 extended-precision floating point value really
+ only occupies ten bytes, but most ABI's declare its size to be
+ 12 bytes, to preserve alignment. A `struct type' representing
+ such a floating-point type would have a `length' value of 12,
+ even though the last two bytes are unused.
+
+ There's a bit of a host/target mess here, if you're concerned
+ about machines whose bytes aren't eight bits long, or who don't
+ have byte-addressed memory. Various places pass this to memcpy
+ and such, meaning it must be in units of host bytes. Various
+ other places expect they can calculate addresses by adding it
+ and such, meaning it must be in units of target bytes. For
+ some DSP targets, in which HOST_CHAR_BIT will (presumably) be 8
+ and TARGET_CHAR_BIT will be (say) 32, this is a problem.
+
+ One fix would be to make this field in bits (requiring that it
+ always be a multiple of HOST_CHAR_BIT and TARGET_CHAR_BIT) ---
+ the other choice would be to make it consistently in units of
+ HOST_CHAR_BIT. However, this would still fail to address
+ machines based on a ternary or decimal representation. */
+
+ unsigned length;

-struct type
- {
-
- /* Code for kind of type */
-
- enum type_code code;
-
- /* Name of this type, or NULL if none.
-
- This is used for printing only, except by poorly designed C++ code.
- For looking up a name, look for a symbol in the VAR_NAMESPACE. */
-
- char *name;
-
- /* Tag name for this type, or NULL if none. This means that the
- name of the type consists of a keyword followed by the tag name.
- Which keyword is determined by the type code ("struct" for
- TYPE_CODE_STRUCT, etc.). As far as I know C/C++ are the only languages
- with this feature.
-
- This is used for printing only, except by poorly designed C++ code.
- For looking up a name, look for a symbol in the STRUCT_NAMESPACE.
- One more legitimate use is that if TYPE_FLAG_STUB is set, this is
- the name to use to look for definitions in other files. */
-
- char *tag_name;
-
- /* Length of storage for a value of this type. This is what
- sizeof(type) would return; use it for address arithmetic,
- memory reads and writes, etc. This size includes padding. For
- example, an i386 extended-precision floating point value really
- only occupies ten bytes, but most ABI's declare its size to be
- 12 bytes, to preserve alignment. A `struct type' representing
- such a floating-point type would have a `length' value of 12,
- even though the last two bytes are unused.
-
- There's a bit of a host/target mess here, if you're concerned
- about machines whose bytes aren't eight bits long, or who don't
- have byte-addressed memory. Various places pass this to memcpy
- and such, meaning it must be in units of host bytes. Various
- other places expect they can calculate addresses by adding it
- and such, meaning it must be in units of target bytes. For
- some DSP targets, in which HOST_CHAR_BIT will (presumably) be 8
- and TARGET_CHAR_BIT will be (say) 32, this is a problem.
-
- One fix would be to make this field in bits (requiring that it
- always be a multiple of HOST_CHAR_BIT and TARGET_CHAR_BIT) ---
- the other choice would be to make it consistently in units of
- HOST_CHAR_BIT. However, this would still fail to address
- machines based on a ternary or decimal representation. */
- unsigned length;
-
- /* FIXME, these should probably be restricted to a Fortran-specific
- field in some fashion. */
+ /* FIXME, these should probably be restricted to a Fortran-specific
+ field in some fashion. */
#define BOUND_CANNOT_BE_DETERMINED 5
#define BOUND_BY_REF_ON_STACK 4
#define BOUND_BY_VALUE_ON_STACK 3
#define BOUND_BY_REF_IN_REG 2
#define BOUND_BY_VALUE_IN_REG 1
#define BOUND_SIMPLE 0
- int upper_bound_type;
- int lower_bound_type;
-
- /* Every type is now associated with a particular objfile, and the
- type is allocated on the type_obstack for that objfile. One problem
- however, is that there are times when gdb allocates new types while
- it is not in the process of reading symbols from a particular objfile.
- Fortunately, these happen when the type being created is a derived
- type of an existing type, such as in lookup_pointer_type(). So
- we can just allocate the new type using the same objfile as the
- existing type, but to do this we need a backpointer to the objfile
- from the existing type. Yes this is somewhat ugly, but without
- major overhaul of the internal type system, it can't be avoided
- for now. */
-
- struct objfile *objfile;
-
- /* For a pointer type, describes the type of object pointed to.
- For an array type, describes the type of the elements.
- For a function or method type, describes the type of the return value.
- For a range type, describes the type of the full range.
- For a complex type, describes the type of each coordinate.
- Unused otherwise. */
-
- struct type *target_type;
-
- /* Type that is a pointer to this type.
- NULL if no such pointer-to type is known yet.
- The debugger may add the address of such a type
- if it has to construct one later. */
-
- struct type *pointer_type;
-
- /* C++: also need a reference type. */
-
- struct type *reference_type;
-
- /* C-v variant chain. This points to a type that
- differs from this one only in a const or volatile
- attribute (or both). The various c-v variants
- are chained together in a ring. */
- struct type *cv_type;
-
- /* Address-space delimited variant chain. This points to a type
- that differs from this one only in an address-space qualifier
- attribute. The otherwise-identical address-space delimited
- types are chained together in a ring. */
- struct type *as_type;
-
- /* Flags about this type. */
-
- int flags;
-
- /* Number of fields described for this type */
-
- short nfields;
-
- /* For structure and union types, a description of each field.
- For set and pascal array types, there is one "field",
- whose type is the domain type of the set or array.
- For range types, there are two "fields",
- the minimum and maximum values (both inclusive).
- For enum types, each possible value is described by one "field".
- For a function type, a "field" for each parameter type.
- For C++ classes, there is one field for each base class (if it is
- a derived class) plus one field for each class data member. Member
- functions are recorded elsewhere.
-
- Using a pointer to a separate array of fields
- allows all types to have the same size, which is useful
- because we can allocate the space for a type before
- we know what to put in it. */
-
- struct field
- {
- union field_location
- {
- /* Position of this field, counting in bits from start of
- containing structure.
- For BITS_BIG_ENDIAN=1 targets, it is the bit offset to the MSB.
- For BITS_BIG_ENDIAN=0 targets, it is the bit offset to the LSB.
- For a range bound or enum value, this is the value itself. */
-
- int bitpos;
-
- /* For a static field, if TYPE_FIELD_STATIC_HAS_ADDR then physaddr
- is the location (in the target) of the static field.
- Otherwise, physname is the mangled label of the static field. */
-
- CORE_ADDR physaddr;
- char *physname;
+ int upper_bound_type;
+ int lower_bound_type;

- /* For a function type, this is 1 if the argument is marked
- artificial. Artificial arguments should not be shown to the
- user. */
- int artificial;
- }
- loc;
+ /* Every type is now associated with a particular objfile, and the
+ type is allocated on the type_obstack for that objfile. One problem
+ however, is that there are times when gdb allocates new types while
+ it is not in the process of reading symbols from a particular objfile.
+ Fortunately, these happen when the type being created is a derived
+ type of an existing type, such as in lookup_pointer_type(). So
+ we can just allocate the new type using the same objfile as the
+ existing type, but to do this we need a backpointer to the objfile
+ from the existing type. Yes this is somewhat ugly, but without
+ major overhaul of the internal type system, it can't be avoided
+ for now. */
+
+ struct objfile *objfile;
+
+ /* For a pointer type, describes the type of object pointed to.
+ For an array type, describes the type of the elements.
+ For a function or method type, describes the type of the return value.
+ For a range type, describes the type of the full range.
+ For a complex type, describes the type of each coordinate.
+ Unused otherwise. */
+
+ struct type *target_type;
+
+ /* Flags about this type. */
+
+ int flags;
+
+ /* Number of fields described for this type */
+
+ short nfields;
+
+ /* For structure and union types, a description of each field.
+ For set and pascal array types, there is one "field",
+ whose type is the domain type of the set or array.
+ For range types, there are two "fields",
+ the minimum and maximum values (both inclusive).
+ For enum types, each possible value is described by one "field".
+ For a function type, a "field" for each parameter type.
+ For C++ classes, there is one field for each base class (if it is
+ a derived class) plus one field for each class data member. Member
+ functions are recorded elsewhere.
+
+ Using a pointer to a separate array of fields
+ allows all types to have the same size, which is useful
+ because we can allocate the space for a type before
+ we know what to put in it. */

- /* Size of this field, in bits, or zero if not packed.
- For an unpacked field, the field's type's length
- says how many bytes the field occupies.
- A value of -1 or -2 indicates a static field; -1 means the location
- is specified by the label loc.physname; -2 means that loc.physaddr
- specifies the actual address. */
-
- int bitsize;
-
- /* In a struct or union type, type of this field.
- In a function type, type of this argument.
- In an array type, the domain-type of the array. */
-
- struct type *type;
-
- /* Name of field, value or argument.
- NULL for range bounds and array domains. */
-
- char *name;
-
- }
- *fields;
-
- /* For types with virtual functions (TYPE_CODE_STRUCT), VPTR_BASETYPE
- is the base class which defined the virtual function table pointer.
+ struct field
+ {
+ union field_location
+ {
+ /* Position of this field, counting in bits from start of
+ containing structure.
+ For BITS_BIG_ENDIAN=1 targets, it is the bit offset to the MSB.
+ For BITS_BIG_ENDIAN=0 targets, it is the bit offset to the LSB.
+ For a range bound or enum value, this is the value itself. */
+
+ int bitpos;
+
+ /* For a static field, if TYPE_FIELD_STATIC_HAS_ADDR then physaddr
+ is the location (in the target) of the static field.
+ Otherwise, physname is the mangled label of the static field. */
+
+ CORE_ADDR physaddr;
+ char *physname;
+
+ /* For a function type, this is 1 if the argument is marked
+ artificial. Artificial arguments should not be shown to the
+ user. */
+ int artificial;
+ }
+ loc;
+
+ /* Size of this field, in bits, or zero if not packed.
+ For an unpacked field, the field's type's length
+ says how many bytes the field occupies.
+ A value of -1 or -2 indicates a static field; -1 means the location
+ is specified by the label loc.physname; -2 means that loc.physaddr
+ specifies the actual address. */
+
+ int bitsize;
+
+ /* In a struct or union type, type of this field.
+ In a function type, type of this argument.
+ In an array type, the domain-type of the array. */

- For types that are pointer to member types (TYPE_CODE_MEMBER),
- VPTR_BASETYPE is the type that this pointer is a member of.
+ struct type *type;

- For method types (TYPE_CODE_METHOD), VPTR_BASETYPE is the aggregate
- type that contains the method.
+ /* Name of field, value or argument.
+ NULL for range bounds and array domains. */

- Unused otherwise. */
+ char *name;

- struct type *vptr_basetype;
+ } *fields;

- /* Field number of the virtual function table pointer in
- VPTR_BASETYPE. If -1, we were unable to find the virtual
- function table pointer in initial symbol reading, and
- fill_in_vptr_fieldno should be called to find it if possible.
+ /* For types with virtual functions (TYPE_CODE_STRUCT), VPTR_BASETYPE
+ is the base class which defined the virtual function table pointer.

- Unused if this type does not have virtual functions. */
+ For types that are pointer to member types (TYPE_CODE_MEMBER),
+ VPTR_BASETYPE is the type that this pointer is a member of.

- int vptr_fieldno;
+ For method types (TYPE_CODE_METHOD), VPTR_BASETYPE is the aggregate
+ type that contains the method.

- /* Slot to point to additional language-specific fields of this type. */
+ Unused otherwise. */

- union type_specific
- {
+ struct type *vptr_basetype;

- /* ARG_TYPES is for TYPE_CODE_METHOD.
- Contains the type of each argument, ending with a void type
- after the last argument for normal member functions or a NULL
- pointer after the last argument for functions with variable
- arguments. */
+ /* Field number of the virtual function table pointer in
+ VPTR_BASETYPE. If -1, we were unable to find the virtual
+ function table pointer in initial symbol reading, and
+ fill_in_vptr_fieldno should be called to find it if possible.

- struct type **arg_types;
+ Unused if this type does not have virtual functions. */

- /* CPLUS_STUFF is for TYPE_CODE_STRUCT. It is initialized to point to
- cplus_struct_default, a default static instance of a struct
- cplus_struct_type. */
+ int vptr_fieldno;

- struct cplus_struct_type *cplus_stuff;
+ /* Slot to point to additional language-specific fields of this type. */

- /* FLOATFORMAT is for TYPE_CODE_FLT. It is a pointer to the
- floatformat object that describes the floating-point value
- that resides within the type. */
+ union type_specific
+ {
+ /* ARG_TYPES is for TYPE_CODE_METHOD.
+ Contains the type of each argument, ending with a void type
+ after the last argument for normal member functions or a NULL
+ pointer after the last argument for functions with variable
+ arguments. */
+
+ struct type **arg_types;
+
+ /* CPLUS_STUFF is for TYPE_CODE_STRUCT. It is initialized to point to
+ cplus_struct_default, a default static instance of a struct
+ cplus_struct_type. */
+
+ struct cplus_struct_type *cplus_stuff;
+
+ /* FLOATFORMAT is for TYPE_CODE_FLT. It is a pointer to the
+ floatformat object that describes the floating-point value
+ that resides within the type. */
+
+ const struct floatformat *floatformat;
+ } type_specific;
+};

- const struct floatformat *floatformat;
- }
- type_specific;
- };
+/* A ``struct type'' describes a particular instance of a type, with
+ some particular qualification. */
+struct type
+{
+ /* Type that is a pointer to this type.
+ NULL if no such pointer-to type is known yet.
+ The debugger may add the address of such a type
+ if it has to construct one later. */
+
+ struct type *pointer_type;
+
+ /* C++: also need a reference type. */
+
+ struct type *reference_type;
+
+ /* Variant chain. This points to a type that differs from this one only
+ in qualifiers. Currently, the possible qualifiers are const, volatile,
+ code-space, and data-space. The variants are linked in a circular
+ ring and share CORE_TYPE. */
+ struct type *chain;
+
+ /* Flags specific to this instance of the type, indicating where
+ on the ring we are. */
+ int instance_flags;
+
+ /* Core type, shared by a group of qualified types. */
+ struct type_core *core_type;
+};

#define NULL_TYPE ((struct type *) 0)

@@ -738,25 +740,26 @@ extern void allocate_cplus_struct_type (
#define HAVE_CPLUS_STRUCT(type) \
(TYPE_CPLUS_SPECIFIC(type) != &cplus_struct_default)

-#define TYPE_NAME(thistype) (thistype)->name
-#define TYPE_TAG_NAME(type) ((type)->tag_name)
-#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
+#define TYPE_INSTANCE_FLAGS(thistype) (thistype)->instance_flags
+#define TYPE_CORE_TYPE(thistype) (thistype)->core_type
+#define TYPE_NAME(thistype) TYPE_CORE_TYPE(thistype)->name
+#define TYPE_TAG_NAME(type) TYPE_CORE_TYPE(type)->tag_name
+#define TYPE_TARGET_TYPE(thistype) TYPE_CORE_TYPE(thistype)->target_type
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
-#define TYPE_CV_TYPE(thistype) (thistype)->cv_type
-#define TYPE_AS_TYPE(thistype) (thistype)->as_type
+#define TYPE_CHAIN(thistype) (thistype)->chain
/* Note that if thistype is a TYPEDEF type, you have to call check_typedef.
But check_typedef does set the TYPE_LENGTH of the TYPEDEF type,
so you only have to call check_typedef once. Since allocate_value
calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */
-#define TYPE_LENGTH(thistype) (thistype)->length
-#define TYPE_OBJFILE(thistype) (thistype)->objfile
-#define TYPE_FLAGS(thistype) (thistype)->flags
+#define TYPE_LENGTH(thistype) TYPE_CORE_TYPE(thistype)->length
+#define TYPE_OBJFILE(thistype) TYPE_CORE_TYPE(thistype)->objfile
+#define TYPE_FLAGS(thistype) TYPE_CORE_TYPE(thistype)->flags
/* Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you want the real
type, you need to do TYPE_CODE (check_type (this_type)). */
-#define TYPE_CODE(thistype) (thistype)->code
-#define TYPE_NFIELDS(thistype) (thistype)->nfields
-#define TYPE_FIELDS(thistype) (thistype)->fields
+#define TYPE_CODE(thistype) TYPE_CORE_TYPE(thistype)->code
+#define TYPE_NFIELDS(thistype) TYPE_CORE_TYPE(thistype)->nfields
+#define TYPE_FIELDS(thistype) TYPE_CORE_TYPE(thistype)->fields
#define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args
#define TYPE_INSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->instantiations

@@ -766,8 +769,10 @@ extern void allocate_cplus_struct_type (

/* Moto-specific stuff for FORTRAN arrays */

-#define TYPE_ARRAY_UPPER_BOUND_TYPE(thistype) (thistype)->upper_bound_type
-#define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) (thistype)->lower_bound_type
+#define TYPE_ARRAY_UPPER_BOUND_TYPE(thistype) \
+ TYPE_CORE_TYPE(thistype)->upper_bound_type
+#define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) \
+ TYPE_CORE_TYPE(thistype)->lower_bound_type

#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
(TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),1))
@@ -777,22 +782,22 @@ extern void allocate_cplus_struct_type (

/* C++ */

-#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
-#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
-#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
+#define TYPE_VPTR_BASETYPE(thistype) TYPE_CORE_TYPE(thistype)->vptr_basetype
+#define TYPE_DOMAIN_TYPE(thistype) TYPE_CORE_TYPE(thistype)->vptr_basetype
+#define TYPE_VPTR_FIELDNO(thistype) TYPE_CORE_TYPE(thistype)->vptr_fieldno
#define TYPE_FN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->fn_fields
#define TYPE_NFN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields
#define TYPE_NFN_FIELDS_TOTAL(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields_total
#define TYPE_NTEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ntemplate_args
#define TYPE_NINSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ninstantiations
#define TYPE_DECLARED_TYPE(thistype) TYPE_CPLUS_SPECIFIC(thistype)->declared_type
-#define TYPE_TYPE_SPECIFIC(thistype) (thistype)->type_specific
-#define TYPE_ARG_TYPES(thistype) (thistype)->type_specific.arg_types
-#define TYPE_CPLUS_SPECIFIC(thistype) (thistype)->type_specific.cplus_stuff
-#define TYPE_FLOATFORMAT(thistype) (thistype)->type_specific.floatformat
-#define TYPE_BASECLASS(thistype,index) (thistype)->fields[index].type
+#define TYPE_TYPE_SPECIFIC(thistype) TYPE_CORE_TYPE(thistype)->type_specific
+#define TYPE_ARG_TYPES(thistype) TYPE_CORE_TYPE(thistype)->type_specific.arg_types
+#define TYPE_CPLUS_SPECIFIC(thistype) TYPE_CORE_TYPE(thistype)->type_specific.cplus_stuff
+#define TYPE_FLOATFORMAT(thistype) TYPE_CORE_TYPE(thistype)->type_specific.floatformat
+#define TYPE_BASECLASS(thistype,index) TYPE_CORE_TYPE(thistype)->fields[index].type
#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
-#define TYPE_BASECLASS_NAME(thistype,index) (thistype)->fields[index].name
+#define TYPE_BASECLASS_NAME(thistype,index) TYPE_CORE_TYPE(thistype)->fields[index].name
#define TYPE_BASECLASS_BITPOS(thistype,index) TYPE_FIELD_BITPOS(thistype,index)
#define BASETYPE_VIA_PUBLIC(thistype, index) \
((!TYPE_FIELD_PRIVATE(thistype, index)) && (!TYPE_FIELD_PROTECTED(thistype, index)))
@@ -812,7 +817,7 @@ extern void allocate_cplus_struct_type (
((thisfld).bitsize = -1, FIELD_PHYSNAME(thisfld) = (name))
#define SET_FIELD_PHYSADDR(thisfld, name) \
((thisfld).bitsize = -2, FIELD_PHYSADDR(thisfld) = (name))
-#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
+#define TYPE_FIELD(thistype, n) TYPE_CORE_TYPE(thistype)->fields[n]
#define TYPE_FIELD_TYPE(thistype, n) FIELD_TYPE(TYPE_FIELD(thistype, n))
#define TYPE_FIELD_NAME(thistype, n) FIELD_NAME(TYPE_FIELD(thistype, n))
#define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS(TYPE_FIELD(thistype,n))
@@ -851,8 +856,8 @@ extern void allocate_cplus_struct_type (
(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits == NULL ? 0 \
: B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n)))

-#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitsize < 0)
-#define TYPE_FIELD_STATIC_HAS_ADDR(thistype, n) ((thistype)->fields[n].bitsize == -2)
+#define TYPE_FIELD_STATIC(thistype, n) (TYPE_CORE_TYPE (thistype)->fields[n].bitsize < 0)
+#define TYPE_FIELD_STATIC_HAS_ADDR(thistype, n) (TYPE_CORE_TYPE (thistype)->fields[n].bitsize == -2)
#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) FIELD_PHYSNAME(TYPE_FIELD(thistype, n))
#define TYPE_FIELD_STATIC_PHYSADDR(thistype, n) FIELD_PHYSADDR(TYPE_FIELD(thistype, n))

@@ -1076,8 +1081,6 @@ extern struct type *lookup_reference_typ
extern struct type *make_reference_type (struct type *, struct type **);

extern struct type *make_cv_type (int, int, struct type *, struct type **);
-
-extern void finish_cv_type (struct type *);

extern void replace_type (struct type *, struct type *);

diff -x *.orig -pur gdb.inter/hpread.c gdb.real/hpread.c
--- gdb.inter/hpread.c Sun May 12 20:34:14 2002
+++ gdb.real/hpread.c Sun May 12 20:01:55 2002
@@ -4403,9 +4403,6 @@ hpread_read_struct_type (dnttpointer hp_
/* Clear the global saying what template we are in the middle of processing */
current_template = NULL;

- /* Fix up any cv-qualified versions of this type. */
- finish_cv_type (type);
-
return type;
}

diff -x *.orig -pur gdb.inter/stabsread.c gdb.real/stabsread.c
--- gdb.inter/stabsread.c Sun May 12 20:25:57 2002
+++ gdb.real/stabsread.c Sun May 12 19:34:50 2002
@@ -4302,8 +4302,6 @@ read_struct_type (char **pp, struct type
type = error_type (pp, objfile);
}

- /* Fix up any cv-qualified versions of this type. */
- finish_cv_type (type);
do_cleanups (back_to);
return (type);
}