Skip to content

[LLDB] Simplify libstdc++ string summaries #146562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

Nerixyz
Copy link
Contributor

@Nerixyz Nerixyz commented Jul 1, 2025

From #143177. This combines the summaries for the pre- and post C++ 11 std::string as well as std::wstring. In all cases, the data pointer is reachable through _M_dataplus._M_p. It has the correct type (i.e. char*/wchar_t*) and it's null terminated, so LLDB knows how to format it as expected when using GetSummaryAsCString.

@Nerixyz Nerixyz requested a review from JDevlieghere as a code owner July 1, 2025 16:06
@llvmbot llvmbot added the lldb label Jul 1, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2025

@llvm/pr-subscribers-lldb

Author: nerix (Nerixyz)

Changes

From #143177. This combines the summaries for the pre- and post C++ 11 std::string as well as std::wstring. In all cases, the data pointer is reachable through _M_dataplus._M_p. It has the correct type (i.e. char*/wchar_t*) and it's null terminated, so LLDB knows how to format it as expected when using GetSummaryAsCString.


Full diff: https://github.com/llvm/llvm-project/pull/146562.diff

3 Files Affected:

  • (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+11-18)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp (+5-115)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h (+1-5)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 7ae2e141a63e0..f96fd0f0bcd30 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1344,38 +1344,31 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       .SetShowMembersOneLiner(false)
       .SetHideItemNames(false);
 
-  lldb::TypeSummaryImplSP std_string_summary_sp(
-      new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
-
-  lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
+  lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(
       stl_summary_flags, LibStdcppStringSummaryProvider,
-      "libstdc++ c++11 std::string summary provider"));
-  lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
-      stl_summary_flags, LibStdcppWStringSummaryProvider,
-      "libstdc++ c++11 std::wstring summary provider"));
+      "libstdc++ std::(w)string summary provider"));
 
   cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact,
-                                  std_string_summary_sp);
+                                  string_summary_sp);
   cpp_category_sp->AddTypeSummary("std::basic_string<char>",
-                                  eFormatterMatchExact, std_string_summary_sp);
+                                  eFormatterMatchExact, string_summary_sp);
   cpp_category_sp->AddTypeSummary(
       "std::basic_string<char,std::char_traits<char>,std::allocator<char> >",
-      eFormatterMatchExact, std_string_summary_sp);
+      eFormatterMatchExact, string_summary_sp);
   cpp_category_sp->AddTypeSummary(
       "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
-      eFormatterMatchExact, std_string_summary_sp);
+      eFormatterMatchExact, string_summary_sp);
 
   cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact,
-                                  cxx11_string_summary_sp);
+                                  string_summary_sp);
   cpp_category_sp->AddTypeSummary(
       "std::__cxx11::basic_string<char, std::char_traits<char>, "
       "std::allocator<char> >",
-      eFormatterMatchExact, cxx11_string_summary_sp);
+      eFormatterMatchExact, string_summary_sp);
   cpp_category_sp->AddTypeSummary("std::__cxx11::basic_string<unsigned char, "
                                   "std::char_traits<unsigned char>, "
                                   "std::allocator<unsigned char> >",
-                                  eFormatterMatchExact,
-                                  cxx11_string_summary_sp);
+                                  eFormatterMatchExact, string_summary_sp);
 
   // making sure we force-pick the summary for printing wstring (_M_p is a
   // wchar_t*)
@@ -1395,11 +1388,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       eFormatterMatchExact, std_wstring_summary_sp);
 
   cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact,
-                                  cxx11_wstring_summary_sp);
+                                  string_summary_sp);
   cpp_category_sp->AddTypeSummary(
       "std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, "
       "std::allocator<wchar_t> >",
-      eFormatterMatchExact, cxx11_wstring_summary_sp);
+      eFormatterMatchExact, string_summary_sp);
 
   SyntheticChildren::Flags stl_synth_flags;
   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 77e0755607a06..28b7c01ab1b5b 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -239,122 +239,12 @@ VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
 
 bool lldb_private::formatters::LibStdcppStringSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
-  const bool scalar_is_load_addr = true;
-  auto [addr_of_string, addr_type] =
-      valobj.IsPointerOrReferenceType()
-          ? valobj.GetPointerValue()
-          : valobj.GetAddressOf(scalar_is_load_addr);
-  if (addr_of_string != LLDB_INVALID_ADDRESS) {
-    switch (addr_type) {
-    case eAddressTypeLoad: {
-      ProcessSP process_sp(valobj.GetProcessSP());
-      if (!process_sp)
-        return false;
-
-      StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
-      Status error;
-      lldb::addr_t addr_of_data =
-          process_sp->ReadPointerFromMemory(addr_of_string, error);
-      if (error.Fail() || addr_of_data == 0 ||
-          addr_of_data == LLDB_INVALID_ADDRESS)
-        return false;
-      options.SetLocation(addr_of_data);
-      options.SetTargetSP(valobj.GetTargetSP());
-      options.SetStream(&stream);
-      options.SetNeedsZeroTermination(false);
-      options.SetBinaryZeroIsTerminator(true);
-      lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
-          addr_of_string + process_sp->GetAddressByteSize(), error);
-      if (error.Fail())
-        return false;
-      options.SetSourceSize(size_of_data);
-      options.SetHasSourceSize(true);
-
-      if (!StringPrinter::ReadStringAndDumpToStream<
-              StringPrinter::StringElementType::UTF8>(options)) {
-        stream.Printf("Summary Unavailable");
-        return true;
-      } else
-        return true;
-    } break;
-    case eAddressTypeHost:
-      break;
-    case eAddressTypeInvalid:
-    case eAddressTypeFile:
-      break;
-    }
-  }
-  return false;
-}
+  ValueObjectSP ptr = valobj.GetChildAtNamePath({"_M_dataplus", "_M_p"});
+  if (!ptr)
+    return false;
 
-bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
-    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
-  const bool scalar_is_load_addr = true;
-  auto [addr_of_string, addr_type] = valobj.GetAddressOf(scalar_is_load_addr);
-  if (addr_of_string != LLDB_INVALID_ADDRESS) {
-    switch (addr_type) {
-    case eAddressTypeLoad: {
-      ProcessSP process_sp(valobj.GetProcessSP());
-      if (!process_sp)
-        return false;
-
-      CompilerType wchar_compiler_type =
-          valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
-
-      if (!wchar_compiler_type)
-        return false;
-
-      // Safe to pass nullptr for exe_scope here.
-      std::optional<uint64_t> size =
-          llvm::expectedToOptional(wchar_compiler_type.GetBitSize(nullptr));
-      if (!size)
-        return false;
-      const uint32_t wchar_size = *size;
-
-      StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
-      Status error;
-      lldb::addr_t addr_of_data =
-          process_sp->ReadPointerFromMemory(addr_of_string, error);
-      if (error.Fail() || addr_of_data == 0 ||
-          addr_of_data == LLDB_INVALID_ADDRESS)
-        return false;
-      options.SetLocation(addr_of_data);
-      options.SetTargetSP(valobj.GetTargetSP());
-      options.SetStream(&stream);
-      options.SetNeedsZeroTermination(false);
-      options.SetBinaryZeroIsTerminator(false);
-      lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
-          addr_of_string + process_sp->GetAddressByteSize(), error);
-      if (error.Fail())
-        return false;
-      options.SetSourceSize(size_of_data);
-      options.SetHasSourceSize(true);
-      options.SetPrefixToken("L");
-
-      switch (wchar_size) {
-      case 8:
-        return StringPrinter::ReadStringAndDumpToStream<
-            StringPrinter::StringElementType::UTF8>(options);
-      case 16:
-        return StringPrinter::ReadStringAndDumpToStream<
-            StringPrinter::StringElementType::UTF16>(options);
-      case 32:
-        return StringPrinter::ReadStringAndDumpToStream<
-            StringPrinter::StringElementType::UTF32>(options);
-      default:
-        stream.Printf("size for wchar_t is not valid");
-        return true;
-      }
-      return true;
-    } break;
-    case eAddressTypeHost:
-      break;
-    case eAddressTypeInvalid:
-    case eAddressTypeFile:
-      break;
-    }
-  }
-  return false;
+  stream << ptr->GetSummaryAsCString();
+  return true;
 }
 
 LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
index c7b2130275ad8..8d4d777edee88 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -18,11 +18,7 @@ namespace lldb_private {
 namespace formatters {
 bool LibStdcppStringSummaryProvider(
     ValueObject &valobj, Stream &stream,
-    const TypeSummaryOptions &options); // libcstdc++ c++11 std::string
-
-bool LibStdcppWStringSummaryProvider(
-    ValueObject &valobj, Stream &stream,
-    const TypeSummaryOptions &options); // libcstdc++ c++11 std::wstring
+    const TypeSummaryOptions &options); // libstdc++ std::string
 
 bool LibStdcppSmartPointerSummaryProvider(
     ValueObject &valobj, Stream &stream,

Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@Michael137 Michael137 merged commit 4c7a706 into llvm:main Jul 2, 2025
9 checks passed
@Nerixyz Nerixyz deleted the refactor/lldb-simplify-libstdcxx-string branch July 2, 2025 10:52
@slydiman
Copy link
Contributor

slydiman commented Jul 3, 2025

Please look at https://lab.llvm.org/buildbot/#/builders/211/builds/181
This buildbot was red last 2 days. But probably this patch fixed XPASS: lldb-api::TestCallStdStringFunction.py and @expectedFailureAll can be removed.

DavidSpickett pushed a commit that referenced this pull request Jul 3, 2025
#146562 made
[TestCallStdStringFunction](https://github.com/llvm/llvm-project/blob/bd6cd92984e7a30cb91e4f069a0bacc5c582a234/lldb/test/API/commands/expression/call-function/TestCallStdStringFunction.py)
unexpectedly pass on Windows.

The test now passes, because `expression str` now prints the "raw"
string object, which happens to include the string "Hello world".
Previously, this resulted in an error:

```
(lldb) expression str
(std::string) $0 = {
  _Mypair = {
    _Myval2 = {
      _Bx = (_Buf = "Hello world", _Ptr = "", _Alias = "Hello world")
      _Mysize = 11
      _Myres = 15
    }
  }
}
(lldb) type summary add std::string --summary-string "${var._M_dataplus._M_p}"
^^^ previous summary ^^^
(lldb) expression str
(std::string) $1 = error: summary string parsing error
```

#143177 will eventually add the correct summary for MSVC STL strings.

Relates to #22139
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants