https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103086
Bug ID: 103086 Summary: [11/12 Regression] std::unique_ptr printer gets confused by [[no_unique_address]] in tuple Product: gcc Version: 11.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- When using GDB 11 or 12 and GCC 11 or 12 the pretty printer for std::unique_ptr shows the value of the deleter instead of the pointer: $1 = std::unique_ptr<datum> = {get() = {<No data fields>}} I filed this as https://sourceware.org/bugzilla/show_bug.cgi?id=28480 but with Bruno's help we realised it's actually a libstdc++ printer bug. The problem is that since std::tuple started using [[no_unique_address]] the tuple<T*, default_delete<T>> object has two _M_head_impl subobjects, in different base classes. That means this printer code is ambiguous: tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base head_field = tuple_head_type.fields()[0] if head_field.name == '_M_head_impl': self.pointer = tuple_member['_M_head_impl'] In older versions of GDB it happened to work by chance, because GDB returned the last _M_head_impl member and std::tuple's base classes are stored in reverse order, so the last one was the T* element of the tuple. Since GDB 11 it returns the first _M_head_impl, which is probably more sensible, but now the printer gets the default_delete<T> element. The fix is for the printer to stop using an ambiguous field name and cast the tuple to the right base class before accessing the _M_head_impl member: --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -258,7 +258,7 @@ class UniquePointerPrinter: tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base head_field = tuple_head_type.fields()[0] if head_field.name == '_M_head_impl': - self.pointer = tuple_member['_M_head_impl'] + self.pointer = tuple_member.cast(tuple_head_type)['_M_head_impl'] elif head_field.is_base_class: self.pointer = tuple_member.cast(head_field.type) else: