[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:
parent
d90c0a5980
commit
abdc17f814
@ -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)
|
||||
{
|
||||
|
@ -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 } } */
|
@ -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 } } */
|
12
gcc/testsuite/gcc.dg/guality/pr63300-const-volatile.c
Normal file
12
gcc/testsuite/gcc.dg/guality/pr63300-const-volatile.c
Normal 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" } } */
|
16
gcc/tree.c
16
gcc/tree.c
@ -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
|
||||
|
@ -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). */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user