Skip to content

[lldb][test] Merge MSVC STL std::(u8)string tests into generic directory #147525

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
merged 4 commits into from
Jul 9, 2025

Conversation

Michael137
Copy link
Member

Now that most STL formatter tests have been moved to generic. Do the same for the MSVC tests (which are currently just for std::string). The std::string test was mostly the same (MSVC just had 1 additional check, which I moved over).

We also only tested u8string with MSVC. So i moved those into generic as-is. I kept it separate from the existing std::string tests since it requires c++20.

The tests are currently failing for libc++ and libstdc++ because MSVC had a test case which checked that:

  std::string overwritten_zero("abc");
  const_cast<char *>(overwritten_zero.data())[3] = 'd';

prints as "abc". But libc++ and libstdc++ print it as "abcd" (which seems like the more correct thing to do?)

@Michael137 Michael137 requested a review from labath July 8, 2025 13:48
@Michael137 Michael137 requested a review from JDevlieghere as a code owner July 8, 2025 13:48
@llvmbot llvmbot added the lldb label Jul 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 8, 2025

@llvm/pr-subscribers-lldb

Author: Michael Buch (Michael137)

Changes

Now that most STL formatter tests have been moved to generic. Do the same for the MSVC tests (which are currently just for std::string). The std::string test was mostly the same (MSVC just had 1 additional check, which I moved over).

We also only tested u8string with MSVC. So i moved those into generic as-is. I kept it separate from the existing std::string tests since it requires c++20.

The tests are currently failing for libc++ and libstdc++ because MSVC had a test case which checked that:

  std::string overwritten_zero("abc");
  const_cast&lt;char *&gt;(overwritten_zero.data())[3] = 'd';

prints as "abc". But libc++ and libstdc++ print it as "abcd" (which seems like the more correct thing to do?)


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

8 Files Affected:

  • (modified) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py (+21)
  • (modified) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp (+2)
  • (renamed) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/Makefile (+1)
  • (renamed) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py (+20-9)
  • (renamed) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/main.cpp (+4-6)
  • (removed) lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/TestDataFormatterMsvcStlString.py (-120)
  • (removed) lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/main.cpp (-40)
  • (removed) lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/Makefile (-4)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
index 7ae5687af2cf4..ba8a8b32afeb7 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
@@ -80,6 +80,7 @@ def cleanup():
                 '(%s::string) Q = "quite a long std::strin with lots of info inside it"'
                 % ns,
                 "(%s::string *) null_str = nullptr" % ns,
+                '(std::string) overwritten_zero = "abc"',
             ],
         )
 
@@ -124,6 +125,11 @@ def test_libstdcxx(self):
         self.build(dictionary={"USE_LIBSTDCPP": 1})
         self.do_test()
 
+    @add_test_categories(["msvcstl"])
+    def test_msvc(self):
+        self.build()
+        self.do_test()
+
     def do_test_multibyte(self):
         lldbutil.run_to_source_breakpoint(
             self, "Set break point at this line.", self.main_spec
@@ -157,6 +163,11 @@ def test_multibyte_libstdcxx(self):
         self.build(dictionary={"USE_LIBSTDCPP": 1})
         self.do_test_multibyte()
 
+    @add_test_categories(["msvcstl"])
+    def test_multibyte_msvc(self):
+        self.build()
+        self.do_test_multibyte()
+
     def do_test_uncapped_summary(self):
         (_, _, thread, _) = lldbutil.run_to_source_breakpoint(
             self, "Set break point at this line.", self.main_spec
@@ -187,6 +198,11 @@ def test_uncapped_libstdcxx(self):
         self.build(dictionary={"USE_LIBSTDCPP": 1})
         self.do_test_uncapped_summary()
 
+    @add_test_categories(["msvcstl"])
+    def test_uncapped_msvc(self):
+        self.build()
+        self.do_test_uncapped_summary()
+
     def do_test_summary_unavailable(self):
         """
         Make sure that if the string is not readable, we give an error.
@@ -212,3 +228,8 @@ def test_unavailable_summary_libcxx(self):
     def test_unavailable_summary_libstdcxx(self):
         self.build(dictionary={"USE_LIBSTDCPP": 1})
         self.do_test_summary_unavailable()
+
+    @add_test_categories(["msvcstl"])
+    def test_unavailable_summary_msvc(self):
+        self.build()
+        self.do_test_summary_unavailable()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
index db695ed06f015..f22c890861d01 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
@@ -13,6 +13,8 @@ int main() {
   std::string empty("");
   std::string q("hello world");
   std::string Q("quite a long std::strin with lots of info inside it");
+  std::string overwritten_zero("abc");
+  const_cast<char *>(overwritten_zero.data())[3] = 'd';
   std::string TheVeryLongOne(
       "123456789012345678901234567890123456789012345678901234567890123456789012"
       "345678901234567890123456789012345678901234567890123456789012345678901234"
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/Makefile
similarity index 61%
rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/Makefile
rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/Makefile
index 99998b20bcb05..4f79c0a900c3a 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/Makefile
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/Makefile
@@ -1,3 +1,4 @@
 CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -std=c++20
 
 include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/TestDataFormatterMsvcStlU8String.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py
similarity index 53%
rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/TestDataFormatterMsvcStlU8String.py
rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py
index f181f520f5d85..f5d7dc5c3b79b 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/TestDataFormatterMsvcStlU8String.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py
@@ -1,6 +1,6 @@
 # coding=utf8
 """
-Test std::u8string summary with MSVC's STL.
+Test std::u8string summary.
 """
 
 
@@ -10,14 +10,8 @@
 from lldbsuite.test import lldbutil
 
 
-class MsvcStlU8StringDataFormatterTestCase(TestBase):
-    NO_DEBUG_INFO_TESTCASE = True
-
-    @add_test_categories(["msvcstl"])
-    def test_with_run_command(self):
-        """Test that that file and class static variables display correctly."""
-        self.build()
-
+class StdU8StringDataFormatterTestCase(TestBase):
+    def do_test(self):
         lldbutil.run_to_source_breakpoint(
             self, "Set break point at this line.", lldb.SBFileSpec("main.cpp")
         )
@@ -31,3 +25,20 @@ def test_with_run_command(self):
                 '(std::u8string) u8_text = u8"ABC"',
             ],
         )
+
+    @expectedFailureAll(bugnumber="No libc++ formatters for std::u8string yet.")
+    @add_test_categories(["libc++"])
+    def test_libcxx(self):
+        self.build(dictionary={"USE_LIBCPP": 1})
+        self.do_test()
+
+    @expectedFailureAll(bugnumber="No libstdc++ formatters for std::u8string yet.")
+    @add_test_categories(["libstdcxx"])
+    def test_libstdcxx(self):
+        self.build(dictionary={"USE_LIBSTDCPP": 1})
+        self.do_test()
+
+    @add_test_categories(["msvcstl"])
+    def test_msvc(self):
+        self.build()
+        self.do_test()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/main.cpp
similarity index 52%
rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/main.cpp
rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/main.cpp
index e01af9fa08e7e..3db9d6380f61e 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/main.cpp
@@ -1,14 +1,12 @@
+#include <cstdio>
 #include <string>
 
-#ifndef _MSVC_STL_VERSION
-// this is more of a sanity check that the categories work as expected
-#error Not using MSVC STL
-#endif
-
 int main() {
   std::u8string u8_string_small(u8"🍄");
   std::u8string u8_string(u8"❤️👍📄📁😃🧑‍🌾");
   std::u8string u8_empty(u8"");
   std::u8string u8_text(u8"ABC");
-  u8_text.assign(u8"ABCd"); // Set break point at this line.
+  u8_text.assign(u8"ABCd");
+
+  std::puts("// Set break point at this line.");
 }
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/TestDataFormatterMsvcStlString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/TestDataFormatterMsvcStlString.py
deleted file mode 100644
index e49ea84dbdf47..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/TestDataFormatterMsvcStlString.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# coding=utf8
-"""
-Test std::*string summaries with MSVC's STL.
-"""
-
-
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class MsvcStlStringDataFormatterTestCase(TestBase):
-    NO_DEBUG_INFO_TESTCASE = True
-
-    @add_test_categories(["msvcstl"])
-    def test_with_run_command(self):
-        """Test that that file and class static variables display correctly."""
-        self.build()
-
-        main_spec = lldb.SBFileSpec("main.cpp")
-        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
-            self, "Set break point at this line.", main_spec
-        )
-        frame = thread.frames[0]
-
-        # This is the function to remove the custom formats in order to have a
-        # clean slate for the next test case.
-        def cleanup():
-            self.runCmd("type format clear", check=False)
-            self.runCmd("type summary clear", check=False)
-            self.runCmd("type filter clear", check=False)
-            self.runCmd("type synth clear", check=False)
-
-        # Execute the cleanup function during test case tear down.
-        self.addTearDownHook(cleanup)
-
-        self.expect(
-            "frame variable",
-            substrs=[
-                '(std::wstring) wempty = L""',
-                '(std::wstring) s = L"hello world! מזל טוב!"',
-                '(std::wstring) S = L"!!!!"',
-                "(const wchar_t *) mazeltov = 0x",
-                'L"מזל טוב"',
-                '(std::string) empty = ""',
-                '(std::string) q = "hello world"',
-                '(std::string) Q = "quite a long std::strin with lots of info inside it"',
-                '(std::string) overwritten_zero = "abc"',
-                '(std::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"',
-                '(std::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
-                '(std::u16string) u16_string = u"ß水氶"',
-                '(std::u16string) u16_empty = u""',
-                '(std::u32string) u32_string = U"🍄🍅🍆🍌"',
-                '(std::u32string) u32_empty = U""',
-                "(std::string *) null_str = nullptr",
-            ],
-        )
-
-        thread.StepOver()
-
-        TheVeryLongOne = frame.FindVariable("TheVeryLongOne")
-        summaryOptions = lldb.SBTypeSummaryOptions()
-        summaryOptions.SetCapping(lldb.eTypeSummaryUncapped)
-        uncappedSummaryStream = lldb.SBStream()
-        TheVeryLongOne.GetSummary(uncappedSummaryStream, summaryOptions)
-        uncappedSummary = uncappedSummaryStream.GetData()
-        self.assertGreater(
-            uncappedSummary.find("someText"),
-            0,
-            "uncappedSummary does not include the full string",
-        )
-        summaryOptions.SetCapping(lldb.eTypeSummaryCapped)
-        cappedSummaryStream = lldb.SBStream()
-        TheVeryLongOne.GetSummary(cappedSummaryStream, summaryOptions)
-        cappedSummary = cappedSummaryStream.GetData()
-        self.assertLessEqual(
-            cappedSummary.find("someText"), 0, "cappedSummary includes the full string"
-        )
-
-        self.expect_expr(
-            "s", result_type="std::wstring", result_summary='L"hello world! מזל טוב!"'
-        )
-
-        self.expect_expr("q", result_type="std::string", result_summary='"hello world"')
-
-        self.expect_expr(
-            "Q",
-            result_type="std::string",
-            result_summary='"quite a long std::strin with lots of info inside it"',
-        )
-
-        self.expect(
-            "frame variable",
-            substrs=[
-                '(std::wstring) S = L"!!!!!"',
-                "(const wchar_t *) mazeltov = 0x",
-                'L"מזל טוב"',
-                '(std::string) q = "hello world"',
-                '(std::string) Q = "quite a long std::strin with lots of info inside it"',
-                '(std::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"',
-                '(std::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
-                '(std::u16string) u16_string = u"ß水氶"',
-                '(std::u32string) u32_string = U"🍄🍅🍆🍌"',
-                '(std::u32string) u32_empty = U""',
-                "(std::string *) null_str = nullptr",
-            ],
-        )
-
-        # Finally, make sure that if the string is not readable, we give an error:
-        bkpt_2 = target.BreakpointCreateBySourceRegex(
-            "Break here to look at bad string", main_spec
-        )
-        self.assertEqual(bkpt_2.GetNumLocations(), 1, "Got one location")
-        threads = lldbutil.continue_to_breakpoint(process, bkpt_2)
-        self.assertEqual(len(threads), 1, "Stopped at second breakpoint")
-        frame = threads[0].frames[0]
-        var = frame.FindVariable("in_str")
-        self.assertTrue(var.GetError().Success(), "Made variable")
-        self.assertIsNone(var.GetSummary())
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/main.cpp
deleted file mode 100644
index fcfb5d48e9bb1..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/string/main.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <stdint.h>
-
-#include <string>
-
-#ifndef _MSVC_STL_VERSION
-// this is more of a sanity check that the categories work as expected
-#error Not using MSVC STL
-#endif
-
-static size_t touch_string(std::string &in_str) {
-  return in_str.size(); // Break here to look at bad string
-}
-
-int main() {
-  std::wstring wempty(L"");
-  std::wstring s(L"hello world! מזל טוב!");
-  std::wstring S(L"!!!!");
-  const wchar_t *mazeltov = L"מזל טוב";
-  std::string empty("");
-  std::string q("hello world");
-  std::string Q("quite a long std::strin with lots of info inside it");
-  std::string overwritten_zero("abc");
-  const_cast<char *>(overwritten_zero.data())[3] = 'd';
-  // clang-format off
-  std::string TheVeryLongOne("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890someText1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
-  // clang-format on
-  std::string IHaveEmbeddedZeros("a\0b\0c\0d", 7);
-  std::wstring IHaveEmbeddedZerosToo(
-      L"hello world!\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監", 38);
-  std::u16string u16_string(u"ß水氶");
-  std::u16string u16_empty(u"");
-  std::u32string u32_string(U"🍄🍅🍆🍌");
-  std::u32string u32_empty(U"");
-  std::string *null_str = nullptr;
-
-  S.assign(L"!!!!!"); // Set break point at this line.
-  std::string *not_a_string = (std::string *)0x0;
-  touch_string(*not_a_string);
-  return 0;
-}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/Makefile
deleted file mode 100644
index 58558e6e15f78..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/msvcstl/u8string/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-CXX_SOURCES := main.cpp
-
-CXXFLAGS_EXTRAS := -std=c++20 -O0
-include Makefile.rules

@Michael137
Copy link
Member Author

FYI @Nerixyz

@labath
Copy link
Collaborator

labath commented Jul 8, 2025

But libc++ and libstdc++ print it as "abcd" (which seems like the more correct thing to do?)

I'm not so sure about that. std::string has a separate length field and it can contain embedded nul characters, so I can at least understand the idea of trusting the length field more than we trust the terminator. It would be an interesting experiment to see what happens when you take a corrupted string like this and try to e.g. << it to a stream. My guess is it would print "abc". (of course, that's undefined, so there's no guarantee all STLs will behave the same way)

For libstdc++, I guess this happens because we have the simple summary ${var._M_ptr} (or whatever), but I think this actually shows that this summary is wrong, as it will not print anything that comes after a (perfectly legal) internal nul character. I have no idea why this happens for libc++.

Given that the terminator is a part of the std::string contract, I can also imagine the formatter flagging this specially in some way ("abc" <unterminated> ?)

@Nerixyz
Copy link
Contributor

Nerixyz commented Jul 8, 2025

prints as "abc". But libc++ and libstdc++ print it as "abcd" (which seems like the more correct thing to do?)

This is too MSVC STL/libc++ specific, I think. std::string on MSVC's STL always has a valid size (regardless of SSO or not) and the test tests that this is respected. libc++ should also pass this test, but it currently doesn't, because the string is further up in main.cpp than expected (you can see that it has the expected output before null_str, but the check is after null_str).

@Michael137
Copy link
Member Author

But libc++ and libstdc++ print it as "abcd" (which seems like the more correct thing to do?)

I'm not so sure about that. std::string has a separate length field and it can contain embedded nul characters, so I can at least understand the idea of trusting the length field more than we trust the terminator.

Yea that's a fair point. Trusting the size makes sense given the embedded null case

For libstdc++, I guess this happens because we have the simple summary ${var._M_ptr} (or whatever), but I think this actually shows that this summary is wrong, as it will not print anything that comes after a (perfectly legal) internal nul character

Yea in fact we have XFAILed tests for those

Given that the terminator is a part of the std::string contract, I can also imagine the formatter flagging this specially in some way ("abc" <unterminated> ?)

That would be neat!

@Michael137 Michael137 merged commit 1e6dd8c into llvm:main Jul 9, 2025
9 checks passed
@Michael137 Michael137 deleted the lldb/move-msvcstl-string-tests branch July 9, 2025 13:20
Michael137 added a commit that referenced this pull request Jul 9, 2025
These were mistakenly changed during #147525
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