This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
RFC: DWARF2 vs. qualified array types
- To: gcc at gcc dot gnu dot org
- Subject: RFC: DWARF2 vs. qualified array types
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 11 Apr 2001 12:57:26 -0700
- Cc: Jim Wilson <wilson at cygnus dot com>, Jason Merrill <jason at cygnus dot com>
- Organization: CodeSourcery, LLC
PR1657 is one of those bugs that shouldn't exist: turning on -ggdb
causes the C++ front-end to emit an error message where it doesn't
otherwise.
In detail:
- modified_type_die contains this code:
type = build_type_variant (type, is_const_type, is_volatile_type);
- If type is an ARRAY_TYPE, this is incorrect for C++. (As in C,
the meaning of `const int[4]' is that you hvae an array of
`const ints', not that you have a `const' version of `int [4]'.)
There is no such thing as a qualified array type in C++.
- The C++ front-end doesn't check for these bogus types and
ignore them because they shouldn't exist. So, later, when we
need an `int[4]' we decide that the weird const-qualified version
is what we want. But then we notice later that it's not.
There are several problems here:
- Ideally, dwarf2out wouldn't be creating trees. The
front-end should create trees, not the debugging generation code.
- If it *does* create trees, it shouldn't chain them into otherwise
accessible trees. Calling build_type_variant creates a type that
is chained, via TYPE_MAIN_VARIANT, to other types, and so it
is visible to the rest of the compiler later.
- More subtly, we have a global function (build_type_variant)
that doesn't do the right thing for all languages, but not
everyone can be reasonably expected to know this. This is again
where we desparately need object-orientation, modules, or some
other kind of interface hiding. It would be ideal if each
front-end could replace build_type_variant with an appropriate
function, and then code like this would probably just work,
despite the caveats above.
Anyhow, here's my attempt at a patch, which does indeed fix the
test-case in question.
However, I can't quite convince myself that we'll still get the right
DWARF2 output. I'd appreciate it if Jason or Jim (or someone else
expert in the area) could look at the patch. I intend to check it in
(even without such an opinion) in an hour or two -- it is certainly
better to generate slightly incorrect debug information than to refuse
to compile legal code -- but I would like to avoid both eventualities.
Thanks,
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.242.2.5
diff -c -p -r1.242.2.5 dwarf2out.c
*** dwarf2out.c 2001/04/03 01:46:20 1.242.2.5
--- dwarf2out.c 2001/04/11 19:46:05
*************** modified_type_die (type, is_const_type,
*** 7522,7543 ****
if (code != ERROR_MARK)
{
! type = build_type_variant (type, is_const_type, is_volatile_type);
! mod_type_die = lookup_type_die (type);
! if (mod_type_die)
! return mod_type_die;
/* Handle C typedef types. */
! if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
! && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
{
! tree dtype = TREE_TYPE (TYPE_NAME (type));
! if (type == dtype)
{
/* For a named type, use the typedef. */
! gen_type_die (type, context_die);
! mod_type_die = lookup_type_die (type);
}
else if (is_const_type < TYPE_READONLY (dtype)
--- 7522,7556 ----
if (code != ERROR_MARK)
{
! tree qualified_type;
! /* See if we already have the appropriately qualified variant of
! this type. */
! qualified_type
! = get_qualified_type (type,
! ((is_const_type ? TYPE_QUAL_CONST : 0)
! | (is_volatile_type
! ? TYPE_QUAL_VOLATILE : 0)));
! /* If we do, then we can just use its DIE, if it exists. */
! if (qualified_type)
! {
! mod_type_die = lookup_type_die (qualified_type);
! if (mod_type_die)
! return mod_type_die;
! }
/* Handle C typedef types. */
! if (qualified_type && TYPE_NAME (qualified_type)
! && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
! && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
{
! tree type_name = TYPE_NAME (qualified_type);
! tree dtype = TREE_TYPE (type_name);
! if (qualified_type == dtype)
{
/* For a named type, use the typedef. */
! gen_type_die (qualified_type, context_die);
! mod_type_die = lookup_type_die (qualified_type);
}
else if (is_const_type < TYPE_READONLY (dtype)
*************** modified_type_die (type, is_const_type,
*** 7545,7551 ****
/* cv-unqualified version of named type. Just use the unnamed
type to which it refers. */
mod_type_die
! = modified_type_die (DECL_ORIGINAL_TYPE (TYPE_NAME (type)),
is_const_type, is_volatile_type,
context_die);
/* Else cv-qualified version of named type; fall through. */
--- 7558,7564 ----
/* cv-unqualified version of named type. Just use the unnamed
type to which it refers. */
mod_type_die
! = modified_type_die (DECL_ORIGINAL_TYPE (type_name),
is_const_type, is_volatile_type,
context_die);
/* Else cv-qualified version of named type; fall through. */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.185.2.4
diff -c -p -r1.185.2.4 tree.c
*** tree.c 2001/03/20 22:03:34 1.185.2.4
--- tree.c 2001/04/11 19:46:06
*************** set_type_quals (type, type_quals)
*** 2993,3023 ****
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
}
! /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
! the same kind of data as TYPE describes. Variants point to the
! "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
! and it points to a chain of other variants so that duplicate
! variants are never made. Only main variants should ever appear as
! types of expressions. */
tree
! build_qualified_type (type, type_quals)
tree type;
int type_quals;
{
! register tree t;
/* Search the chain of variants to see if there is already one there just
like the one we need to have. If so, use that existing one. We must
preserve the TYPE_NAME, since there is code that depends on this. */
-
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
return t;
- /* We need a new one. */
- t = build_type_copy (type);
- set_type_quals (t, type_quals);
return t;
}
--- 2993,3039 ----
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
}
! /* Return a version of the TYPE, qualified as indicated by the
! TYPE_QUALS, if one exists. If no qualified version exists yet,
! return NULL_TREE. */
tree
! get_qualified_type (type, type_quals)
tree type;
int type_quals;
{
! tree t;
/* Search the chain of variants to see if there is already one there just
like the one we need to have. If so, use that existing one. We must
preserve the TYPE_NAME, since there is code that depends on this. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
return t;
+
+ return NULL_TREE;
+ }
+
+ /* Like get_qualified_type, but creates the type if it does not
+ exist. This function never returns NULL_TREE. */
+
+ tree
+ build_qualified_type (type, type_quals)
+ tree type;
+ int type_quals;
+ {
+ tree t;
+
+ /* See if we already have the appropriate qualified variant. */
+ t = get_qualified_type (type, type_quals);
+
+ /* If not, build it. */
+ if (!t)
+ {
+ t = build_type_copy (type);
+ set_type_quals (t, type_quals);
+ }
return t;
}
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.223.2.7
diff -c -p -r1.223.2.7 tree.h
*** tree.h 2001/03/27 04:41:16 1.223.2.7
--- tree.h 2001/04/11 19:46:07
*************** extern tree lookup_attribute PARAMS ((c
*** 2071,2082 ****
extern tree merge_attributes PARAMS ((tree, tree));
! /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
! the same kind of data as TYPE describes. Variants point to the
! "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
! and it points to a chain of other variants so that duplicate
! variants are never made. Only main variants should ever appear as
! types of expressions. */
extern tree build_qualified_type PARAMS ((tree, int));
--- 2071,2084 ----
extern tree merge_attributes PARAMS ((tree, tree));
! /* Return a version of the TYPE, qualified as indicated by the
! TYPE_QUALS, if one exists. If no qualified version exists yet,
! return NULL_TREE. */
!
! extern tree get_qualified_type PARAMS ((tree, int));
!
! /* Like get_qualified_type, but creates the type if it does not
! exist. This function never returns NULL_TREE. */
extern tree build_qualified_type PARAMS ((tree, int));