diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7c3eb339628..13f2355aac5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-10-01 Alexandre Oliva + + PR debug/91507 + * dwarf2out.c (override_type_for_decl_p): New. + (gen_variable_die): Use it. + 2019-10-01 Richard Biener * tree-vect-loop.c (vectorizable_reduction): Move variables diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index d33f19b818d..bf69ce497f2 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 891b2bf5e4b..99230295d7c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2019-10-01 Alexandre Oliva + + 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 * gcc.dg/diag-aka-1.c (T): Turn into a pointer typedef. diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-0.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-0.C new file mode 100644 index 00000000000..a3458bd0d32 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-0.C @@ -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 } } */ diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-1.C new file mode 100644 index 00000000000..e8fd6f8ffea --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-1.C @@ -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 } } */ diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-2.C new file mode 100644 index 00000000000..dd178120438 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-2.C @@ -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 } } */ diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-3.C new file mode 100644 index 00000000000..8db6133b765 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-3.C @@ -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 } } */ diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/array-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/array-4.C new file mode 100644 index 00000000000..6b3f546c1b5 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/array-4.C @@ -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 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-0.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-0.c new file mode 100644 index 00000000000..b06392e04a2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-0.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-1.c new file mode 100644 index 00000000000..ad8f466ef08 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-1.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-2.c new file mode 100644 index 00000000000..5d1606f0889 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-2.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/array-3.c b/gcc/testsuite/gcc.dg/debug/dwarf2/array-3.c new file mode 100644 index 00000000000..077a62ef9a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/array-3.c @@ -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 } } */