Skip to content

Commit 45689b2

Browse files
authored
[LLDB] Add type summaries for MSVC STL strings (#143177)
This PR adds type summaries for `std::{string,wstring,u8string,u16string,u32string}` from the MSVC STL. See #24834 for the MSVC STL issue. The following changes were made: - `dotest.py` now detects if the MSVC STL is available. It does so by looking at the target triple, which is an additional argument passed from Lit. It specifically checks for `windows-msvc` to not match on `windows-gnu` (i.e. MinGW/Cygwin). - (The main part): Added support for summarizing `std::(w)string` from MSVC's STL. Because the type names from the libstdc++ (pre C++ 11) string types are the same as on MSVC's STL, `CXXCompositeSummaryFormat` is used with two entries, one for MSVC's STL and one for libstdc++. With MSVC's STL, `std::u{8,16,32}string` is also handled. These aren't handled for libstdc++, so I put them in `LoadMsvcStlFormatters`.
1 parent 2948775 commit 45689b2

File tree

15 files changed

+556
-35
lines changed

15 files changed

+556
-35
lines changed

lldb/packages/Python/lldbsuite/test/dotest.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,46 @@ def checkLibstdcxxSupport():
831831
configuration.skip_categories.append("libstdcxx")
832832

833833

834+
def canRunMsvcStlTests():
835+
from lldbsuite.test import lldbplatformutil
836+
837+
platform = lldbplatformutil.getPlatform()
838+
if platform != "windows":
839+
return False, f"Don't know how to build with MSVC's STL on {platform}"
840+
841+
with tempfile.NamedTemporaryFile() as f:
842+
cmd = [configuration.compiler, "-xc++", "-o", f.name, "-E", "-"]
843+
p = subprocess.Popen(
844+
cmd,
845+
stdin=subprocess.PIPE,
846+
stdout=subprocess.PIPE,
847+
stderr=subprocess.PIPE,
848+
universal_newlines=True,
849+
)
850+
_, stderr = p.communicate(
851+
"""
852+
#include <yvals_core.h>
853+
#ifndef _MSVC_STL_VERSION
854+
#error _MSVC_STL_VERSION not defined
855+
#endif
856+
"""
857+
)
858+
if not p.returncode:
859+
return True, "Compiling with MSVC STL"
860+
return (False, f"Not compiling with MSVC STL: {stderr}")
861+
862+
863+
def checkMsvcStlSupport():
864+
result, reason = canRunMsvcStlTests()
865+
if result:
866+
return # msvcstl supported
867+
if "msvcstl" in configuration.categories_list:
868+
return # msvcstl category explicitly requested, let it run.
869+
if configuration.verbose:
870+
print(f"msvcstl tests will not be run because: {reason}")
871+
configuration.skip_categories.append("msvcstl")
872+
873+
834874
def canRunWatchpointTests():
835875
from lldbsuite.test import lldbplatformutil
836876

@@ -1044,6 +1084,7 @@ def run_suite():
10441084

10451085
checkLibcxxSupport()
10461086
checkLibstdcxxSupport()
1087+
checkMsvcStlSupport()
10471088
checkWatchpointSupport()
10481089
checkDebugInfoSupport()
10491090
checkDebugServerSupport()

lldb/packages/Python/lldbsuite/test/test_categories.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"lldb-server": "Tests related to lldb-server",
3434
"lldb-dap": "Tests for the Debug Adapter Protocol with lldb-dap",
3535
"llgs": "Tests for the gdb-server functionality of lldb-server",
36+
"msvcstl": "Test for MSVC STL data formatters",
3637
"pexpect": "Tests requiring the pexpect library to be available",
3738
"objc": "Tests related to the Objective-C programming language support",
3839
"pyapi": "Tests related to the Python API",

lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
3232
LibStdcpp.cpp
3333
LibStdcppTuple.cpp
3434
LibStdcppUniquePointer.cpp
35+
MsvcStl.cpp
3536
MSVCUndecoratedNameParser.cpp
3637

3738
LINK_COMPONENTS

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 109 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "LibCxxVariant.h"
4747
#include "LibStdcpp.h"
4848
#include "MSVCUndecoratedNameParser.h"
49+
#include "MsvcStl.h"
4950
#include "lldb/lldb-enumerations.h"
5051

5152
using namespace lldb;
@@ -1331,6 +1332,37 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13311332
"${var.__y_} ${var.__m_} ${var.__wdl_}")));
13321333
}
13331334

1335+
static void RegisterStdStringSummaryProvider(
1336+
const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty,
1337+
llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) {
1338+
auto makeSpecifier = [](llvm::StringRef name) {
1339+
return std::make_shared<lldb_private::TypeNameSpecifierImpl>(
1340+
name, eFormatterMatchExact);
1341+
};
1342+
1343+
category_sp->AddTypeSummary(makeSpecifier(string_ty), summary_sp);
1344+
1345+
// std::basic_string<char>
1346+
category_sp->AddTypeSummary(
1347+
makeSpecifier(llvm::formatv("std::basic_string<{}>", char_ty).str()),
1348+
summary_sp);
1349+
// std::basic_string<char,std::char_traits<char>,std::allocator<char> >
1350+
category_sp->AddTypeSummary(
1351+
makeSpecifier(llvm::formatv("std::basic_string<{0},std::char_traits<{0}>,"
1352+
"std::allocator<{0}> >",
1353+
char_ty)
1354+
.str()),
1355+
summary_sp);
1356+
// std::basic_string<char, std::char_traits<char>, std::allocator<char> >
1357+
category_sp->AddTypeSummary(
1358+
makeSpecifier(
1359+
llvm::formatv("std::basic_string<{0}, std::char_traits<{0}>, "
1360+
"std::allocator<{0}> >",
1361+
char_ty)
1362+
.str()),
1363+
summary_sp);
1364+
}
1365+
13341366
static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13351367
if (!cpp_category_sp)
13361368
return;
@@ -1347,18 +1379,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13471379
lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(
13481380
stl_summary_flags, LibStdcppStringSummaryProvider,
13491381
"libstdc++ std::(w)string summary provider"));
1350-
1351-
cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact,
1352-
string_summary_sp);
1353-
cpp_category_sp->AddTypeSummary("std::basic_string<char>",
1354-
eFormatterMatchExact, string_summary_sp);
1355-
cpp_category_sp->AddTypeSummary(
1356-
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >",
1357-
eFormatterMatchExact, string_summary_sp);
1358-
cpp_category_sp->AddTypeSummary(
1359-
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
1360-
eFormatterMatchExact, string_summary_sp);
1361-
13621382
cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact,
13631383
string_summary_sp);
13641384
cpp_category_sp->AddTypeSummary(
@@ -1370,23 +1390,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13701390
"std::allocator<unsigned char> >",
13711391
eFormatterMatchExact, string_summary_sp);
13721392

1373-
// making sure we force-pick the summary for printing wstring (_M_p is a
1374-
// wchar_t*)
1375-
lldb::TypeSummaryImplSP std_wstring_summary_sp(
1376-
new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
1377-
1378-
cpp_category_sp->AddTypeSummary("std::wstring", eFormatterMatchExact,
1379-
std_wstring_summary_sp);
1380-
cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t>",
1381-
eFormatterMatchExact, std_wstring_summary_sp);
1382-
cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t,std::char_traits<"
1383-
"wchar_t>,std::allocator<wchar_t> >",
1384-
eFormatterMatchExact, std_wstring_summary_sp);
1385-
cpp_category_sp->AddTypeSummary(
1386-
"std::basic_string<wchar_t, std::char_traits<wchar_t>, "
1387-
"std::allocator<wchar_t> >",
1388-
eFormatterMatchExact, std_wstring_summary_sp);
1389-
13901393
cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact,
13911394
string_summary_sp);
13921395
cpp_category_sp->AddTypeSummary(
@@ -1595,6 +1598,81 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
15951598
"^std::optional<.+>(( )?&)?$", stl_summary_flags, true);
15961599
}
15971600

1601+
/// Load formatters that are formatting types from more than one STL
1602+
static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
1603+
if (!cpp_category_sp)
1604+
return;
1605+
1606+
TypeSummaryImpl::Flags stl_summary_flags;
1607+
stl_summary_flags.SetCascades(true)
1608+
.SetSkipPointers(false)
1609+
.SetSkipReferences(false)
1610+
.SetDontShowChildren(true)
1611+
.SetDontShowValue(false)
1612+
.SetShowMembersOneLiner(false)
1613+
.SetHideItemNames(false);
1614+
using StringElementType = StringPrinter::StringElementType;
1615+
1616+
RegisterStdStringSummaryProvider(
1617+
cpp_category_sp, "std::string", "char",
1618+
std::make_shared<CXXFunctionSummaryFormat>(
1619+
stl_summary_flags,
1620+
[](ValueObject &valobj, Stream &stream,
1621+
const TypeSummaryOptions &options) {
1622+
if (IsMsvcStlStringType(valobj))
1623+
return MsvcStlStringSummaryProvider<StringElementType::ASCII>(
1624+
valobj, stream, options);
1625+
return LibStdcppStringSummaryProvider(valobj, stream, options);
1626+
},
1627+
"MSVC STL/libstdc++ std::string summary provider"));
1628+
RegisterStdStringSummaryProvider(
1629+
cpp_category_sp, "std::wstring", "wchar_t",
1630+
std::make_shared<CXXFunctionSummaryFormat>(
1631+
stl_summary_flags,
1632+
[](ValueObject &valobj, Stream &stream,
1633+
const TypeSummaryOptions &options) {
1634+
if (IsMsvcStlStringType(valobj))
1635+
return MsvcStlWStringSummaryProvider(valobj, stream, options);
1636+
return LibStdcppStringSummaryProvider(valobj, stream, options);
1637+
},
1638+
"MSVC STL/libstdc++ std::wstring summary provider"));
1639+
}
1640+
1641+
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
1642+
if (!cpp_category_sp)
1643+
return;
1644+
1645+
TypeSummaryImpl::Flags stl_summary_flags;
1646+
stl_summary_flags.SetCascades(true)
1647+
.SetSkipPointers(false)
1648+
.SetSkipReferences(false)
1649+
.SetDontShowChildren(true)
1650+
.SetDontShowValue(false)
1651+
.SetShowMembersOneLiner(false)
1652+
.SetHideItemNames(false);
1653+
1654+
using StringElementType = StringPrinter::StringElementType;
1655+
1656+
RegisterStdStringSummaryProvider(
1657+
cpp_category_sp, "std::u8string", "char8_t",
1658+
std::make_shared<CXXFunctionSummaryFormat>(
1659+
stl_summary_flags,
1660+
MsvcStlStringSummaryProvider<StringElementType::UTF8>,
1661+
"MSVC STL std::u8string summary provider"));
1662+
RegisterStdStringSummaryProvider(
1663+
cpp_category_sp, "std::u16string", "char16_t",
1664+
std::make_shared<CXXFunctionSummaryFormat>(
1665+
stl_summary_flags,
1666+
MsvcStlStringSummaryProvider<StringElementType::UTF16>,
1667+
"MSVC STL std::u16string summary provider"));
1668+
RegisterStdStringSummaryProvider(
1669+
cpp_category_sp, "std::u32string", "char32_t",
1670+
std::make_shared<CXXFunctionSummaryFormat>(
1671+
stl_summary_flags,
1672+
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
1673+
"MSVC STL std::u32string summary provider"));
1674+
}
1675+
15981676
static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
15991677
if (!cpp_category_sp)
16001678
return;
@@ -1709,6 +1787,8 @@ lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
17091787
// LLDB prioritizes the last loaded matching formatter.
17101788
LoadLibCxxFormatters(g_category);
17111789
LoadLibStdcppFormatters(g_category);
1790+
LoadMsvcStlFormatters(g_category);
1791+
LoadCommonStlFormatters(g_category);
17121792
LoadSystemFormatters(g_category);
17131793
}
17141794
});

0 commit comments

Comments
 (0)