DWARF array bounds missing from C++ array definitions

A variable redeclaration or definition that provides additional type
information for it, e.g. outermost array bounds, is not reflected in
the debug information for the variable.  With this patch, the debug
info of the variable specialization gets a type attribute with the
adjusted type.

This patch affects mostly only array bounds.  However, when the
symbolic type used in a declaration and in a definition are different,
although they refer to the same type, debug information will end up
(correctly?) naming different symbolic types in the specification and
the definition.  Also, when a readonly declaration of an array loses
the readonly flag at the definition because of the initializer, the
definition may end up referencing a type while the specification
refers to a const-qualified version of that type.  If the type of the
variable is already const-qualified, e.g. an array of a const type,
the difference is meaningless.


for  gcc/ChangeLog

	PR debug/91507
	* dwarf2out.c (override_type_for_decl_p): New.
	(gen_variable_die): Use it.

for  gcc/testsuite/ChangeLog

	PR debug/91507
	* gcc.dg/debug/dwarf2/array-0.c: New.
	* gcc.dg/debug/dwarf2/array-1.c: New.
	* gcc.dg/debug/dwarf2/array-2.c: New.
	* gcc.dg/debug/dwarf2/array-3.c: New.
	* g++.dg/debug/dwarf2/array-0.C: New.
	* g++.dg/debug/dwarf2/array-1.C: New.
	* g++.dg/debug/dwarf2/array-2.C: New.  Based on libstdc++-v3's
	src/c++98/pool_allocator.cc:__pool_alloc_base::_S_heap_size.
	* g++.dg/debug/dwarf2/array-3.C: New.  Based on
	gcc's config/i386/i386-features.c:xlogue_layout::s_instances.
	* g++.dg/debug/dwarf2/array-4.C: New.

From-SVN: r276403
This commit is contained in:
Alexandre Oliva 2019-10-01 11:36:31 +00:00 committed by Alexandre Oliva
parent c7ea76ea56
commit 31632e2c43
12 changed files with 165 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2019-10-01 Alexandre Oliva <oliva@adacore.com>
PR debug/91507
* dwarf2out.c (override_type_for_decl_p): New.
(gen_variable_die): Use it.
2019-10-01 Richard Biener <rguenther@suse.de>
* tree-vect-loop.c (vectorizable_reduction): Move variables

View File

@ -23705,6 +23705,34 @@ local_function_static (tree decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL;
}
/* Return true iff DECL overrides (presumably completes) the type of
OLD_DIE within CONTEXT_DIE. */
static bool
override_type_for_decl_p (tree decl, dw_die_ref old_die,
dw_die_ref context_die)
{
tree type = TREE_TYPE (decl);
int cv_quals;
if (decl_by_reference_p (decl))
{
type = TREE_TYPE (type);
cv_quals = TYPE_UNQUALIFIED;
}
else
cv_quals = decl_quals (decl);
dw_die_ref type_die = modified_type_die (type,
cv_quals | TYPE_QUALS (type),
false,
context_die);
dw_die_ref old_type_die = get_AT_ref (old_die, DW_AT_type);
return type_die != old_type_die;
}
/* Generate a DIE to represent a declared data object.
Either DECL or ORIGIN must be non-null. */
@ -23957,7 +23985,9 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
&& !DECL_ABSTRACT_P (decl_or_origin)
&& variably_modified_type_p (TREE_TYPE (decl_or_origin),
decl_function_context
(decl_or_origin))))
(decl_or_origin)))
|| (old_die && specialization_p
&& override_type_for_decl_p (decl_or_origin, old_die, context_die)))
{
tree type = TREE_TYPE (decl_or_origin);

View File

@ -1,3 +1,18 @@
2019-10-01 Alexandre Oliva <oliva@adacore.com>
PR debug/91507
* gcc.dg/debug/dwarf2/array-0.c: New.
* gcc.dg/debug/dwarf2/array-1.c: New.
* gcc.dg/debug/dwarf2/array-2.c: New.
* gcc.dg/debug/dwarf2/array-3.c: New.
* g++.dg/debug/dwarf2/array-0.C: New.
* g++.dg/debug/dwarf2/array-1.C: New.
* g++.dg/debug/dwarf2/array-2.C: New. Based on libstdc++-v3's
src/c++98/pool_allocator.cc:__pool_alloc_base::_S_heap_size.
* g++.dg/debug/dwarf2/array-3.C: New. Based on
gcc's config/i386/i386-features.c:xlogue_layout::s_instances.
* g++.dg/debug/dwarf2/array-4.C: New.
2019-10-01 Richard Sandiford <richard.sandiford@arm.com>
* gcc.dg/diag-aka-1.c (T): Turn into a pointer typedef.

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
struct S
{
static int array[42];
};
int S::array[42];
/* Verify that we get only one DW_TAG_subrange_type with a
DW_AT_upper_bound. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
struct S
{
static int array[];
};
int S::array[42];
/* Verify that we get two DW_TAG_subrange_type, only one of which with
a DW_AT_upper_bound. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 4 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
struct S
{
typedef int i_t;
static i_t array[42];
};
int S::array[42];
/* Verify that we get two DW_TAG_subrange_type (plus abbrev), and two
DW_AT_upper_bound, because a different symbolic name is used for
the array element type. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 3 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 2 } } */

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
struct S
{
S() {}
~S() {}
static const S array[2];
};
const S S::array[2] = { S(), S() };
/* Verify that we get only one DW_TAG_subrange_type (plus the abbrev),
and one DW_AT_upper_bound (non-abbrev), because the array
definition loses the readonly wrapper for the array type because of
the dynamic initializers. The const types are 4: S, S*, int, and
S[4], plus the abbrev. A const version of S[4] doesn't make sense,
but we output it. */
/* { dg-final { scan-assembler-times " DW_TAG_const_type" 5 } } */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,16 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
struct S
{
S() {}
~S() {}
};
const S array[2] = { S(), S() };
/* Like array-3, but with a non-member array without a separate
declaration, to check that we don't issue the nonsensical
DW_TAG_const_type used by the member array declaration there. */
/* { dg-final { scan-assembler-times " DW_TAG_const_type" 4 } } */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
extern int array[42];
int array[42];
/* Verify that we get only one DW_TAG_subtrange_type (plus abbrev),
with a DW_AT_upper_bound. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
extern int array[];
int array[42];
/* Verify that we get two DW_TAG_subtrange_type (each with an abbrev),
but only one DW_AT_upper_bound. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 4 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
int array[42];
/* Verify that we get only one DW_TAG_subtrange_type (plus abbrev)
with DW_AT_upper_bound. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */

View File

@ -0,0 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-gdwarf-2 -dA" } */
int array[] = { 0, 1, 2 };
/* Verify that we get only one DW_TAG_subtrange_type (plus abbrev)
with DW_AT_upper_bound. */
/* { dg-final { scan-assembler-times " DW_TAG_subrange_type" 2 } } */
/* { dg-final { scan-assembler-times " DW_AT_upper_bound" 1 } } */