I'm at 1ca642d785c49e9e0b28651b190720267703f023 (current master). $ cat test.cpp #include <memory> int main() { std::unique_ptr<int> p(new int); return 0; } $ /opt/gcc/git/bin/g++ test.cpp -g3 -O0 $ readelf --debug-dump a.out ... <3><968>: Abbrev Number: 79 (DW_TAG_member) <969> DW_AT_name : (indirect string, offset: 0xc214): _M_head_impl <96d> DW_AT_decl_file : 4 <96e> DW_AT_decl_line : 125 <96f> DW_AT_decl_column : 39 <970> DW_AT_type : <0x67e> <974> DW_AT_data_member_location: -1 ... The -1 DW_AT_data_member_location value looks wrong. Previous gcc versions would say 0, which makes more sense. It doesn't seem to change anything whether I use DWARF 4 or 5. Related GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28063
I bisected, it started with: libstdc++: Remove inheritance from elements in std::tuple 91e6226f880b048275a7ceedef716e159c7cefd9 So it's likely related to the use of [[no_unique_address]]. Relevant thread on dwarf-discuss: http://lists.dwarfstd.org/pipermail/dwarf-discuss-dwarfstd.org/2021-June/004825.html
It's indeed about [[no_unique_address]], and empty objects. Here's a smaller reproducer: $ cat test.cpp struct Empty {}; struct S { [[no_unique_address]] Empty empty; } s; $ g++ test.cpp -g -c -o test.o $ readelf --debug-dump test.o | grep "DW_AT_data_member_location:" <3d> DW_AT_data_member_location: -1 If you replace Empty with anything that isn't empty, you no longer get the -1. Notice this too: ~~~ $ cat test1.cpp #include <stdio.h> #include <stddef.h> struct Empty {}; struct S { [[no_unique_address]] Empty empty1; [[no_unique_address]] Empty empty2; [[no_unique_address]] Empty empty3; } s; int main () { printf ("&s.empty1 = %p\n", &s.empty1); printf ("&s.empty2 = %p\n", &s.empty2); printf ("&s.empty3 = %p\n", &s.empty3); printf ("s = %p\n", &s); printf ("offset empty1 = %ld\n", offsetof (struct S, empty1)); printf ("offset empty2 = %ld\n", offsetof (struct S, empty2)); printf ("offset empty3 = %ld\n", offsetof (struct S, empty3)); return 0; } ~~~ The debug info shows: <2><a3>: Abbrev Number: 10 (DW_TAG_member) <a4> DW_AT_name : (indirect string, offset: 0x186f): empty1 ... <af> DW_AT_data_member_location: -1 <2><b0>: Abbrev Number: 2 (DW_TAG_member) <b1> DW_AT_name : (indirect string, offset: 0x1876): empty2 ... <ba> DW_AT_data_member_location: 0 <2><bb>: Abbrev Number: 2 (DW_TAG_member) <bc> DW_AT_name : (indirect string, offset: 0x187d): empty3 ... <c5> DW_AT_data_member_location: 1 While at run time, we get: $ ./test1 &s.empty1 = 0x5627442ab011 &s.empty2 = 0x5627442ab012 &s.empty3 = 0x5627442ab013 s = 0x5627442ab011 offset empty1 = 0 offset empty2 = 1 offset empty3 = 2 So (0, 1, 2) at runtime, but (-1, 0, 1) in the DWARF. And then note this, with a non-empty field added before the empty ones: ~~~~ $ cat test2.cpp #include <stdio.h> #include <stddef.h> struct Empty {}; struct S { int i; [[no_unique_address]] Empty empty1; [[no_unique_address]] Empty empty2; } s; int main () { printf ("&s.i = %p\n", &s.i); printf ("&s.empty1 = %p\n", &s.empty1); printf ("&s.empty2 = %p\n", &s.empty2); printf ("s = %p\n", &s); printf ("offset i = %ld\n", offsetof (struct S, i)); printf ("offset empty1 = %ld\n", offsetof (struct S, empty1)); printf ("offset empty2 = %ld\n", offsetof (struct S, empty2)); return 0; } we see: <2><a3>: Abbrev Number: 9 (DW_TAG_member) <a4> DW_AT_name : i ... <ad> DW_AT_data_member_location: 0 <2><ae>: Abbrev Number: 10 (DW_TAG_member) <af> DW_AT_name : (indirect string, offset: 0x1872): empty1 ... <ba> DW_AT_data_member_location: -1 <2><bb>: Abbrev Number: 11 (DW_TAG_member) <bc> DW_AT_name : (indirect string, offset: 0x1879): empty2 ... <c7> DW_AT_data_member_location: 3 while at run time: $ ./test2 &s.i = 0x561fac538038 &s.empty1 = 0x561fac538038 &s.empty2 = 0x561fac53803c s = 0x561fac538038 offset i = 0 offset empty1 = 0 offset empty2 = 4 So it was (0, -1, 3) in the DWARF and (0, 0, 4) at run time. This all seems to suggest an off by one for the empty fields in the DWARF.
BTW, I found it curious that empty2 and empty3 get their own addresses, even at run time, when they could have all been squashed to the same address. I.e., e.g., this ends up with sizeof == 3, when it could have been 1, I believe: struct Empty {}; struct S { [[no_unique_address]] Empty empty1; [[no_unique_address]] Empty empty2; [[no_unique_address]] Empty empty3; }; Clang also gives empty2 and empty3 unique addresses and sizeof(S)==3. ABI compatibility could prevent changing this, of course. Clang also gets the DWARF right, BTW. For the example above: <2><48>: Abbrev Number: 4 (DW_TAG_member) <49> DW_AT_name : (indirect string, offset: 0x55): empty1 ... <53> DW_AT_data_member_location: 0 <2><54>: Abbrev Number: 4 (DW_TAG_member) <55> DW_AT_name : (indirect string, offset: 0x62): empty2 ... <5f> DW_AT_data_member_location: 1 <2><60>: Abbrev Number: 4 (DW_TAG_member) <61> DW_AT_name : (indirect string, offset: 0x69): empty3 ... <6b> DW_AT_data_member_location: 2
The C++ standard forbids two objects of the same type having the same address. That is true for the empty base-class optimization and it's true for [[no_unique_address]]. [intro.object] > Two objects with overlapping lifetimes that are not bit-fields may have the > same address if one is nested within the other, or if at least one is a > subobject of zero size and they are of different types; otherwise, they have > distinct addresses and occupy disjoint bytes of storage. There is a footnote that says: > Under the “as-if” rule an implementation is allowed to store two objects at > the same machine address or not store an object at all if the program cannot > observe the difference. But I don't think GCC does that, because if some property that is reflected in the debuginfo would allow you to observe the difference, then it's not allowed.
... and if the type is visible outside a single translation unit, then it needs to follow the layout mandated by the ABI anyway, or it would violate the One-Definition Rule.
Still the DWARF looks incorrect.
I must say I don't understand why we do that PCC_BITFIELD_TYPE_MATTERS stuff in dwarf2out.c (field_byte_offset) for non-bitfields, I don't understand why byte_position (decl) wouldn't work just fine. After all, stor-layout.c also doesn't do anything special for PCC_BITFIELD_TYPE_MATTERS unless DECL_BIT_FIELD or DECL_BIT_FIELD_TYPE. At least for C/C++, bitfields should have reasonable type sizes one can actually use (Ada has aggregate bitfields I think though), while non-bitfields can be e.g. the C++ classes that have TYPE_SIZE BITS_PER_UNIT, but DECL_SIZE of 0, which is why we are getting those negative offsets. 2021-11-09 Jakub Jelinek <jakub@redhat.com> PR debug/101378 * dwarf2out.c (field_byte_offset): Do the PCC_BITFIELD_TYPE_MATTERS handling only for DECL_BIT_FIELD decls. * g++.dg/debug/dwarf2/pr101378.C: New test. --- gcc/dwarf2out.c.jj 2021-11-05 10:19:46.339457342 +0100 +++ gcc/dwarf2out.c 2021-11-09 15:01:51.425437717 +0100 @@ -19646,6 +19646,7 @@ field_byte_offset (const_tree decl, stru properly dynamic byte offsets only when PCC bitfield type doesn't matter. */ if (PCC_BITFIELD_TYPE_MATTERS + && DECL_BIT_FIELD (decl) && TREE_CODE (DECL_FIELD_OFFSET (decl)) == INTEGER_CST) { offset_int object_offset_in_bits; --- gcc/testsuite/g++.dg/debug/dwarf2/pr101378.C.jj 2021-11-09 15:17:39.504975396 +0100 +++ gcc/testsuite/g++.dg/debug/dwarf2/pr101378.C 2021-11-09 15:17:28.067137556 +0100 @@ -0,0 +1,13 @@ +// PR debug/101378 +// { dg-do compile { target c++11 } } +// { dg-options "-gdwarf-5 -dA" } +// { dg-final { scan-assembler-times "0\[^0-9x\\r\\n\]* DW_AT_data_member_location" 1 } } +// { dg-final { scan-assembler-times "1\[^0-9x\\r\\n\]* DW_AT_data_member_location" 1 } } +// { dg-final { scan-assembler-times "2\[^0-9x\\r\\n\]* DW_AT_data_member_location" 1 } } +// { dg-final { scan-assembler-not "-1\[^0-9x\\r\\n\]* DW_AT_data_member_location" } } + +struct E {}; +struct S +{ + [[no_unique_address]] E e, f, g; +} s; fixes this for me.
Thank you, I missed the "same type" constraint. It's also mentioned at https://en.cppreference.com/w/cpp/language/attributes/no_unique_address . Indeed, if I use distinct empty types, GCC and Clang lay them at the same address: $ cat foo3.cc #include <stdio.h> #include <stddef.h> struct Empty1 {}; struct Empty2 {}; struct Empty3 {}; struct S { [[no_unique_address]] Empty1 empty1; [[no_unique_address]] Empty2 empty2; [[no_unique_address]] Empty3 empty3; } s; int main () { printf ("&s.empty1 = %p\n", &s.empty1); printf ("&s.empty2 = %p\n", &s.empty2); printf ("&s.empty3 = %p\n", &s.empty3); printf ("s = %p\n", &s); printf ("offset empty1 = %ld\n", offsetof (struct S, empty1)); printf ("offset empty2 = %ld\n", offsetof (struct S, empty2)); printf ("offset empty3 = %ld\n", offsetof (struct S, empty3)); return 0; } $ ./foo3 &s.empty1 = 0x55a5dc7aa031 &s.empty2 = 0x55a5dc7aa031 &s.empty3 = 0x55a5dc7aa031 s = 0x55a5dc7aa031 offset empty1 = 0 offset empty2 = 0 offset empty3 = 0 $ readelf -dw foo3| grep data_member_location <b6> DW_AT_data_member_location: -1 <c0> DW_AT_data_member_location: -1 <ca> DW_AT_data_member_location: -1 So (-1, -1, -1) in the DWARF and (0, 0, 0) at run time.
> 2021-11-09 Jakub Jelinek <jakub@redhat.com> > > PR debug/101378 > * dwarf2out.c (field_byte_offset): Do the PCC_BITFIELD_TYPE_MATTERS > handling only for DECL_BIT_FIELD decls. > > ... > > fixes this for me. I gave the patch a try, and all the testcases posted in this bugzilla now show correct DWARF AFAICT. Thank you!
I've now compared GDB testsuite runs with current GCC, unpatched vs patched, no regressions.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:10db7573014008ff867098206f51012d501ab57b commit r12-5148-g10db7573014008ff867098206f51012d501ab57b Author: Jakub Jelinek <jakub@redhat.com> Date: Thu Nov 11 10:14:04 2021 +0100 dwarf2out: Fix up field_byte_offset [PR101378] For PCC_BITFIELD_TYPE_MATTERS field_byte_offset has quite large code to deal with it since many years ago (see it e.g. in GCC 3.2, although it used to be on HOST_WIDE_INTs, then on double_ints, now on offset_ints). But that code apparently isn't able to cope with members with empty class types with [[no_unique_address]] attribute, because the empty classes have non-zero type size but zero decl size and so one can end up from the computation with negative offset or offset 1 byte smaller than it should be. For !PCC_BITFIELD_TYPE_MATTERS, we just use tree_result = byte_position (decl); which seems exactly right even for the empty classes or anything which is not a bitfield (and for which we don't add DW_AT_bit_offset attribute). So, instead of trying to handle those no_unique_address members in the current already very complicated code, this limits it to bitfields. stor-layout.c PCC_BITFIELD_TYPE_MATTERS handling also affects only bitfields, twice it checks DECL_BIT_FIELD and once DECL_BIT_FIELD_TYPE. As discussed, this patch uses DECL_BIT_FIELD_TYPE check, because DECL_BIT_FIELD might be cleared for some bitfields with bitsizes multiple of BITS_PER_UNIT and e.g. struct S { int e; int a : 1, b : 7, c : 8, d : 16; } s; struct T { int a : 1, b : 7; long long c : 8; int d : 16; } t; int main () { s.c = 0x55; s.d = 0xaaaa; t.c = 0x55; t.d = 0xaaaa; s.e++; } has different debug info with DECL_BIT_FIELD check. 2021-11-11 Jakub Jelinek <jakub@redhat.com> PR debug/101378 * dwarf2out.c (field_byte_offset): Do the PCC_BITFIELD_TYPE_MATTERS handling only for DECL_BIT_FIELD_TYPE decls. * g++.dg/debug/dwarf2/pr101378.C: New test.
The releases/gcc-11 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:c479d98137fb589718570258547c6bea4f27d1d5 commit r11-9330-gc479d98137fb589718570258547c6bea4f27d1d5 Author: Jakub Jelinek <jakub@redhat.com> Date: Thu Nov 11 10:14:04 2021 +0100 dwarf2out: Fix up field_byte_offset [PR101378] For PCC_BITFIELD_TYPE_MATTERS field_byte_offset has quite large code to deal with it since many years ago (see it e.g. in GCC 3.2, although it used to be on HOST_WIDE_INTs, then on double_ints, now on offset_ints). But that code apparently isn't able to cope with members with empty class types with [[no_unique_address]] attribute, because the empty classes have non-zero type size but zero decl size and so one can end up from the computation with negative offset or offset 1 byte smaller than it should be. For !PCC_BITFIELD_TYPE_MATTERS, we just use tree_result = byte_position (decl); which seems exactly right even for the empty classes or anything which is not a bitfield (and for which we don't add DW_AT_bit_offset attribute). So, instead of trying to handle those no_unique_address members in the current already very complicated code, this limits it to bitfields. stor-layout.c PCC_BITFIELD_TYPE_MATTERS handling also affects only bitfields, twice it checks DECL_BIT_FIELD and once DECL_BIT_FIELD_TYPE. As discussed, this patch uses DECL_BIT_FIELD_TYPE check, because DECL_BIT_FIELD might be cleared for some bitfields with bitsizes multiple of BITS_PER_UNIT and e.g. struct S { int e; int a : 1, b : 7, c : 8, d : 16; } s; struct T { int a : 1, b : 7; long long c : 8; int d : 16; } t; int main () { s.c = 0x55; s.d = 0xaaaa; t.c = 0x55; t.d = 0xaaaa; s.e++; } has different debug info with DECL_BIT_FIELD check. 2021-11-11 Jakub Jelinek <jakub@redhat.com> PR debug/101378 * dwarf2out.c (field_byte_offset): Do the PCC_BITFIELD_TYPE_MATTERS handling only for DECL_BIT_FIELD_TYPE decls. * g++.dg/debug/dwarf2/pr101378.C: New test. (cherry picked from commit 10db7573014008ff867098206f51012d501ab57b)
The releases/gcc-10 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:b7f30978be64fb7029698c8a3c4f4435d32f8097 commit r10-10652-gb7f30978be64fb7029698c8a3c4f4435d32f8097 Author: Jakub Jelinek <jakub@redhat.com> Date: Thu Nov 11 10:14:04 2021 +0100 dwarf2out: Fix up field_byte_offset [PR101378] For PCC_BITFIELD_TYPE_MATTERS field_byte_offset has quite large code to deal with it since many years ago (see it e.g. in GCC 3.2, although it used to be on HOST_WIDE_INTs, then on double_ints, now on offset_ints). But that code apparently isn't able to cope with members with empty class types with [[no_unique_address]] attribute, because the empty classes have non-zero type size but zero decl size and so one can end up from the computation with negative offset or offset 1 byte smaller than it should be. For !PCC_BITFIELD_TYPE_MATTERS, we just use tree_result = byte_position (decl); which seems exactly right even for the empty classes or anything which is not a bitfield (and for which we don't add DW_AT_bit_offset attribute). So, instead of trying to handle those no_unique_address members in the current already very complicated code, this limits it to bitfields. stor-layout.c PCC_BITFIELD_TYPE_MATTERS handling also affects only bitfields, twice it checks DECL_BIT_FIELD and once DECL_BIT_FIELD_TYPE. As discussed, this patch uses DECL_BIT_FIELD_TYPE check, because DECL_BIT_FIELD might be cleared for some bitfields with bitsizes multiple of BITS_PER_UNIT and e.g. struct S { int e; int a : 1, b : 7, c : 8, d : 16; } s; struct T { int a : 1, b : 7; long long c : 8; int d : 16; } t; int main () { s.c = 0x55; s.d = 0xaaaa; t.c = 0x55; t.d = 0xaaaa; s.e++; } has different debug info with DECL_BIT_FIELD check. 2021-11-11 Jakub Jelinek <jakub@redhat.com> PR debug/101378 * dwarf2out.c (field_byte_offset): Do the PCC_BITFIELD_TYPE_MATTERS handling only for DECL_BIT_FIELD_TYPE decls. * g++.dg/debug/dwarf2/pr101378.C: New test. (cherry picked from commit 10db7573014008ff867098206f51012d501ab57b)
The releases/gcc-9 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:4b14a4af62368e8b4892c195e4af80be8893bb0b commit r9-10108-g4b14a4af62368e8b4892c195e4af80be8893bb0b Author: Jakub Jelinek <jakub@redhat.com> Date: Thu Nov 11 10:14:04 2021 +0100 dwarf2out: Fix up field_byte_offset [PR101378] For PCC_BITFIELD_TYPE_MATTERS field_byte_offset has quite large code to deal with it since many years ago (see it e.g. in GCC 3.2, although it used to be on HOST_WIDE_INTs, then on double_ints, now on offset_ints). But that code apparently isn't able to cope with members with empty class types with [[no_unique_address]] attribute, because the empty classes have non-zero type size but zero decl size and so one can end up from the computation with negative offset or offset 1 byte smaller than it should be. For !PCC_BITFIELD_TYPE_MATTERS, we just use tree_result = byte_position (decl); which seems exactly right even for the empty classes or anything which is not a bitfield (and for which we don't add DW_AT_bit_offset attribute). So, instead of trying to handle those no_unique_address members in the current already very complicated code, this limits it to bitfields. stor-layout.c PCC_BITFIELD_TYPE_MATTERS handling also affects only bitfields, twice it checks DECL_BIT_FIELD and once DECL_BIT_FIELD_TYPE. As discussed, this patch uses DECL_BIT_FIELD_TYPE check, because DECL_BIT_FIELD might be cleared for some bitfields with bitsizes multiple of BITS_PER_UNIT and e.g. struct S { int e; int a : 1, b : 7, c : 8, d : 16; } s; struct T { int a : 1, b : 7; long long c : 8; int d : 16; } t; int main () { s.c = 0x55; s.d = 0xaaaa; t.c = 0x55; t.d = 0xaaaa; s.e++; } has different debug info with DECL_BIT_FIELD check. 2021-11-11 Jakub Jelinek <jakub@redhat.com> PR debug/101378 * dwarf2out.c (field_byte_offset): Do the PCC_BITFIELD_TYPE_MATTERS handling only for DECL_BIT_FIELD_TYPE decls. * g++.dg/debug/dwarf2/pr101378.C: New test. (cherry picked from commit 10db7573014008ff867098206f51012d501ab57b)
Fixed.