[multiple changes]

2014-09-25  Andreas Arnez  <arnez@linux.vnet.ibm.com>

	PR 63300/debug
	* tree.c (check_base_type): New.
	(check_qualified_type): Exploit new helper function above.
	* tree.h (check_base_type): New prototype.
	* dwarf2out.c (get_nearest_type_subqualifiers): New.
	(modified_type_die): Fix handling for qualifiers.  Qualifiers to
	"peel off" are now determined using get_nearest_type_subqualifiers.

2014-09-25  Mark Wielaard  <mjw@redhat.com>

	PR 63300/debug
	* gcc.dg/debug/dwarf2/stacked-qualified-types-1.c: New testcase.
	* gcc.dg/debug/dwarf2/stacked-qualified-types-2.c: Likewise.
	* gcc.dg/guality/pr63300-const-volatile.c: New testcase.

From-SVN: r215582
This commit is contained in:
Andreas Krebbel 2014-09-25 07:37:36 +00:00
parent d90c0a5980
commit abdc17f814
6 changed files with 130 additions and 33 deletions

View File

@ -10461,6 +10461,40 @@ decl_quals (const_tree decl)
? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED));
}
/* Determine the TYPE whose qualifiers match the largest strict subset
of the given TYPE_QUALS, and return its qualifiers. Ignore all
qualifiers outside QUAL_MASK. */
static int
get_nearest_type_subqualifiers (tree type, int type_quals, int qual_mask)
{
tree t;
int best_rank = 0, best_qual = 0, max_rank;
type_quals &= qual_mask;
max_rank = popcount_hwi (type_quals) - 1;
for (t = TYPE_MAIN_VARIANT (type); t && best_rank < max_rank;
t = TYPE_NEXT_VARIANT (t))
{
int q = TYPE_QUALS (t) & qual_mask;
if ((q & type_quals) == q && q != type_quals
&& check_base_type (t, type))
{
int rank = popcount_hwi (q);
if (rank > best_rank)
{
best_rank = rank;
best_qual = q;
}
}
}
return best_qual;
}
/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
entry that chains various modifiers in front of the given type. */
@ -10474,12 +10508,14 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
tree qualified_type;
tree name, low, high;
dw_die_ref mod_scope;
/* Only these cv-qualifiers are currently handled. */
const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT);
if (code == ERROR_MARK)
return NULL;
/* Only these cv-qualifiers are currently handled. */
cv_quals &= (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT);
cv_quals &= cv_qual_mask;
/* Don't emit DW_TAG_restrict_type for DWARFv2, since it is a type
tag modifier (and not an attribute) old consumers won't be able
@ -10530,7 +10566,7 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
else
{
int dquals = TYPE_QUALS_NO_ADDR_SPACE (dtype);
dquals &= (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT);
dquals &= cv_qual_mask;
if ((dquals & ~cv_quals) != TYPE_UNQUALIFIED
|| (cv_quals == dquals && DECL_ORIGINAL_TYPE (name) != type))
/* cv-unqualified version of named type. Just use
@ -10543,33 +10579,33 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
mod_scope = scope_die_for (type, context_die);
if ((cv_quals & TYPE_QUAL_CONST)
/* If there are multiple type modifiers, prefer a path which
leads to a qualified type. */
&& (((cv_quals & ~TYPE_QUAL_CONST) == TYPE_UNQUALIFIED)
|| get_qualified_type (type, cv_quals) == NULL_TREE
|| (get_qualified_type (type, cv_quals & ~TYPE_QUAL_CONST)
!= NULL_TREE)))
if (cv_quals)
{
mod_type_die = new_die (DW_TAG_const_type, mod_scope, type);
sub_die = modified_type_die (type, cv_quals & ~TYPE_QUAL_CONST,
context_die);
}
else if ((cv_quals & TYPE_QUAL_VOLATILE)
&& (((cv_quals & ~TYPE_QUAL_VOLATILE) == TYPE_UNQUALIFIED)
|| get_qualified_type (type, cv_quals) == NULL_TREE
|| (get_qualified_type (type, cv_quals & ~TYPE_QUAL_VOLATILE)
!= NULL_TREE)))
{
mod_type_die = new_die (DW_TAG_volatile_type, mod_scope, type);
sub_die = modified_type_die (type, cv_quals & ~TYPE_QUAL_VOLATILE,
context_die);
}
else if (cv_quals & TYPE_QUAL_RESTRICT)
{
mod_type_die = new_die (DW_TAG_restrict_type, mod_scope, type);
sub_die = modified_type_die (type, cv_quals & ~TYPE_QUAL_RESTRICT,
context_die);
struct qual_info { int q; enum dwarf_tag t; };
static const struct qual_info qual_info[] =
{
{ TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
{ TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
{ TYPE_QUAL_CONST, DW_TAG_const_type },
};
int sub_quals;
unsigned i;
/* Determine a lesser qualified type that most closely matches
this one. Then generate DW_TAG_* entries for the remaining
qualifiers. */
sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
cv_qual_mask);
mod_type_die = modified_type_die (type, sub_quals, context_die);
for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
if (qual_info[i].q & cv_quals & ~sub_quals)
{
dw_die_ref d = new_die (qual_info[i].t, mod_scope, type);
if (mod_type_die)
add_AT_die_ref (d, DW_AT_type, mod_type_die);
mod_type_die = d;
}
}
else if (code == POINTER_TYPE)
{

View File

@ -0,0 +1,18 @@
/* PR63300 make sure we don't duplicate type qualifiers unneeded. */
/* { dg-do compile } */
/* { dg-options "-gdwarf -dA" } */
/* This should give us:
- One const type pointing to a char
- One volatile type pointing to a char
- Either one const type pointing to the volatile type pointing to a char
or one volatile type pointing to the const type pointing to a char.
But not both. */
char a;
const char b;
volatile const char c;
volatile char d;
const volatile char e;
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_(?:const|volatile)_type" 3 } } */

View File

@ -0,0 +1,19 @@
/* PR63300 make sure we don't duplicate type qualifiers unneeded. */
/* { dg-do compile } */
/* { dg-options "-std=c99 -gdwarf-4 -dA" } */
/* This should give us:
- One restrict type pointing to a char pointer.
- One volatile type pointing to the restrict type.
- One const type pointing to the restrict type.
- Either one const type pointing to the volatile type pointing to
the restrict type or one volatile type pointing to the const type
pointing to the restrict type. But not both. */
char * restrict a;
char * const restrict b;
char * const volatile restrict c;
char * volatile restrict d;
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_restrict_type" 1 } } */
/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_(?:const|volatile)_type" 3 } } */

View File

@ -0,0 +1,12 @@
/* PR63300 'const volatile' sometimes stripped in debug info */
/* { dg-do run } */
/* { dg-options "-g" } */
int
main (int argc, char **argv)
{
const volatile int v = argc;
return v - argc;
}
/* { dg-final { gdb-test 9 "type:v" "const volatile int" } } */

View File

@ -6185,13 +6185,12 @@ set_type_quals (tree type, int type_quals)
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */
/* Returns true iff unqualified CAND and BASE are equivalent. */
bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
check_base_type (const_tree cand, const_tree base)
{
return (TYPE_QUALS (cand) == type_quals
&& TYPE_NAME (cand) == TYPE_NAME (base)
return (TYPE_NAME (cand) == TYPE_NAME (base)
/* Apparently this is needed for Objective-C. */
&& TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
/* Check alignment. */
@ -6200,6 +6199,15 @@ check_qualified_type (const_tree cand, const_tree base, int type_quals)
TYPE_ATTRIBUTES (base)));
}
/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */
bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
{
return (TYPE_QUALS (cand) == type_quals
&& check_base_type (cand, base));
}
/* Returns true iff CAND is equivalent to BASE with ALIGN. */
static bool

View File

@ -3829,6 +3829,10 @@ extern tree merge_dllimport_decl_attributes (tree, tree);
extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
#endif
/* Returns true iff unqualified CAND and BASE are equivalent. */
extern bool check_base_type (const_tree cand, const_tree base);
/* Check whether CAND is suitable to be returned from get_qualified_type
(BASE, TYPE_QUALS). */