From 0b980cd812b8a34ff80fc0047fa6dd78dca0cb8e Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 17 Jun 2025 13:05:54 +0100 Subject: [PATCH 1/3] [lldb][Formatter] Get element type for unordered_maps from __hash_table::value_type https://github.com/llvm/llvm-project/pull/143501 changes usage of `__hash_value_type` in libcxx to an empty tag type. This type will no longer have a definition in DWARF. Currently the LLDB unordered_map formatter deduces the map's `element_type` by looking at the `__cc_` member of `__hash_value_type`. But that will no longer work because we only have its forward declaration. Since what we're really after is the type that `__hash_value_type` is wrapping, we can just look at the `__hash_table::value_type` typedef. With https://github.com/llvm/llvm-project/pull/143501 that will now point to the `std::pair` element type (which used to be what we got from `__cc_`). TBD: need to double-check this works for older layouts. Quick glance at the code makes me suspicious of cases like `unordered_map, int>` --- lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 642723dd91132..761247d1f7a35 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -99,10 +99,10 @@ static bool isUnorderedMap(ConstString type_name) { CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: GetElementType(CompilerType table_type) { - auto element_type = table_type.GetTypedefedType().GetTypeTemplateArgument(0); + auto element_type = table_type.GetDirectNestedTypeWithName("value_type").GetTypedefedType(); // This synthetic provider is used for both unordered_(multi)map and - // unordered_(multi)set. For unordered_map, the element type has an + // unordered_(multi)set. For older unordered_map layouts, the element type has an // additional type layer, an internal struct (`__hash_value_type`) // that wraps a std::pair. Peel away the internal wrapper type - whose // structure is of no value to users, to expose the std::pair. This From 92a4a14a40f1bca20bab5e15679f07bbfdbf4f2a Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 17 Jun 2025 14:47:55 +0100 Subject: [PATCH 2/3] fixup! clang-format --- .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 761247d1f7a35..f70061f9a929a 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -99,14 +99,15 @@ static bool isUnorderedMap(ConstString type_name) { CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: GetElementType(CompilerType table_type) { - auto element_type = table_type.GetDirectNestedTypeWithName("value_type").GetTypedefedType(); + auto element_type = + table_type.GetDirectNestedTypeWithName("value_type").GetTypedefedType(); // This synthetic provider is used for both unordered_(multi)map and - // unordered_(multi)set. For older unordered_map layouts, the element type has an - // additional type layer, an internal struct (`__hash_value_type`) - // that wraps a std::pair. Peel away the internal wrapper type - whose - // structure is of no value to users, to expose the std::pair. This - // matches the structure returned by the std::map synthetic provider. + // unordered_(multi)set. For older unordered_map layouts, the element type has + // an additional type layer, an internal struct (`__hash_value_type`) that + // wraps a std::pair. Peel away the internal wrapper type - whose structure is + // of no value to users, to expose the std::pair. This matches the structure + // returned by the std::map synthetic provider. if (isUnorderedMap( m_backend.GetCompilerType().GetCanonicalType().GetTypeName())) { std::string name; From 82abcb43aece0b7b5a17eeefd2bbfeff8ed6c506 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 17 Jun 2025 15:16:17 +0100 Subject: [PATCH 3/3] fixup! early return if we found the std::pair element type --- .../source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index f70061f9a929a..ffc33395830bb 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -102,6 +102,11 @@ CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: auto element_type = table_type.GetDirectNestedTypeWithName("value_type").GetTypedefedType(); + // In newer unordered_map layouts, the std::pair element type isn't wrapped + // in any helper types. So return it directly. + if (isStdTemplate(element_type.GetTypeName(), "pair")) + return element_type; + // This synthetic provider is used for both unordered_(multi)map and // unordered_(multi)set. For older unordered_map layouts, the element type has // an additional type layer, an internal struct (`__hash_value_type`) that