Skip to content

[LLDB] Add type summaries for MSVC STL strings #143177

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions lldb/packages/Python/lldbsuite/test/dotest.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,46 @@ def checkLibstdcxxSupport():
configuration.skip_categories.append("libstdcxx")


def canRunMsvcStlTests():
from lldbsuite.test import lldbplatformutil

platform = lldbplatformutil.getPlatform()
if platform != "windows":
return False, f"Don't know how to build with MSVC's STL on {platform}"

with tempfile.NamedTemporaryFile() as f:
cmd = [configuration.compiler, "-xc++", "-o", f.name, "-E", "-"]
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
_, stderr = p.communicate(
"""
#include <yvals_core.h>
#ifndef _MSVC_STL_VERSION
#error _MSVC_STL_VERSION not defined
#endif
"""
)
if not p.returncode:
return True, "Compiling with MSVC STL"
return (False, f"Not compiling with MSVC STL: {stderr}")


def checkMsvcStlSupport():
result, reason = canRunMsvcStlTests()
if result:
return # msvcstl supported
if "msvcstl" in configuration.categories_list:
return # msvcstl category explicitly requested, let it run.
if configuration.verbose:
print(f"msvcstl tests will not be run because: {reason}")
configuration.skip_categories.append("msvcstl")


def canRunWatchpointTests():
from lldbsuite.test import lldbplatformutil

Expand Down Expand Up @@ -1044,6 +1084,7 @@ def run_suite():

checkLibcxxSupport()
checkLibstdcxxSupport()
checkMsvcStlSupport()
checkWatchpointSupport()
checkDebugInfoSupport()
checkDebugServerSupport()
Expand Down
1 change: 1 addition & 0 deletions lldb/packages/Python/lldbsuite/test/test_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"lldb-server": "Tests related to lldb-server",
"lldb-dap": "Tests for the Debug Adapter Protocol with lldb-dap",
"llgs": "Tests for the gdb-server functionality of lldb-server",
"msvcstl": "Test for MSVC STL data formatters",
"pexpect": "Tests requiring the pexpect library to be available",
"objc": "Tests related to the Objective-C programming language support",
"pyapi": "Tests related to the Python API",
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibStdcpp.cpp
LibStdcppTuple.cpp
LibStdcppUniquePointer.cpp
MsvcStl.cpp
MSVCUndecoratedNameParser.cpp

LINK_COMPONENTS
Expand Down
138 changes: 109 additions & 29 deletions lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "LibCxxVariant.h"
#include "LibStdcpp.h"
#include "MSVCUndecoratedNameParser.h"
#include "MsvcStl.h"
#include "lldb/lldb-enumerations.h"

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

static void RegisterStdStringSummaryProvider(
const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty,
llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) {
auto makeSpecifier = [](llvm::StringRef name) {
return std::make_shared<lldb_private::TypeNameSpecifierImpl>(
name, eFormatterMatchExact);
};

category_sp->AddTypeSummary(makeSpecifier(string_ty), summary_sp);

// std::basic_string<char>
category_sp->AddTypeSummary(
makeSpecifier(llvm::formatv("std::basic_string<{}>", char_ty).str()),
summary_sp);
// std::basic_string<char,std::char_traits<char>,std::allocator<char> >
category_sp->AddTypeSummary(
makeSpecifier(llvm::formatv("std::basic_string<{0},std::char_traits<{0}>,"
"std::allocator<{0}> >",
char_ty)
.str()),
summary_sp);
// std::basic_string<char, std::char_traits<char>, std::allocator<char> >
category_sp->AddTypeSummary(
makeSpecifier(
llvm::formatv("std::basic_string<{0}, std::char_traits<{0}>, "
"std::allocator<{0}> >",
char_ty)
.str()),
summary_sp);
}

static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
return;
Expand All @@ -1347,18 +1379,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(
stl_summary_flags, LibStdcppStringSummaryProvider,
"libstdc++ std::(w)string summary provider"));

cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact,
string_summary_sp);
cpp_category_sp->AddTypeSummary("std::basic_string<char>",
eFormatterMatchExact, string_summary_sp);
cpp_category_sp->AddTypeSummary(
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >",
eFormatterMatchExact, string_summary_sp);
cpp_category_sp->AddTypeSummary(
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
eFormatterMatchExact, string_summary_sp);

cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact,
string_summary_sp);
cpp_category_sp->AddTypeSummary(
Expand All @@ -1370,23 +1390,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::allocator<unsigned char> >",
eFormatterMatchExact, string_summary_sp);

// making sure we force-pick the summary for printing wstring (_M_p is a
// wchar_t*)
lldb::TypeSummaryImplSP std_wstring_summary_sp(
new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));

cpp_category_sp->AddTypeSummary("std::wstring", eFormatterMatchExact,
std_wstring_summary_sp);
cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t>",
eFormatterMatchExact, std_wstring_summary_sp);
cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t,std::char_traits<"
"wchar_t>,std::allocator<wchar_t> >",
eFormatterMatchExact, std_wstring_summary_sp);
cpp_category_sp->AddTypeSummary(
"std::basic_string<wchar_t, std::char_traits<wchar_t>, "
"std::allocator<wchar_t> >",
eFormatterMatchExact, std_wstring_summary_sp);

cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact,
string_summary_sp);
cpp_category_sp->AddTypeSummary(
Expand Down Expand Up @@ -1581,6 +1584,81 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"^std::optional<.+>(( )?&)?$", stl_summary_flags, true);
}

/// Load formatters that are formatting types from more than one STL
static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
return;

TypeSummaryImpl::Flags stl_summary_flags;
stl_summary_flags.SetCascades(true)
.SetSkipPointers(false)
.SetSkipReferences(false)
.SetDontShowChildren(true)
.SetDontShowValue(false)
.SetShowMembersOneLiner(false)
.SetHideItemNames(false);
using StringElementType = StringPrinter::StringElementType;

RegisterStdStringSummaryProvider(
cpp_category_sp, "std::string", "char",
std::make_shared<CXXFunctionSummaryFormat>(
stl_summary_flags,
[](ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options) {
if (IsMsvcStlStringType(valobj))
return MsvcStlStringSummaryProvider<StringElementType::ASCII>(
valobj, stream, options);
return LibStdcppStringSummaryProvider(valobj, stream, options);
},
"MSVC STL/libstdc++ std::string summary provider"));
RegisterStdStringSummaryProvider(
cpp_category_sp, "std::wstring", "wchar_t",
std::make_shared<CXXFunctionSummaryFormat>(
stl_summary_flags,
[](ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options) {
if (IsMsvcStlStringType(valobj))
return MsvcStlWStringSummaryProvider(valobj, stream, options);
return LibStdcppStringSummaryProvider(valobj, stream, options);
},
"MSVC STL/libstdc++ std::wstring summary provider"));
}

static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
return;

TypeSummaryImpl::Flags stl_summary_flags;
stl_summary_flags.SetCascades(true)
.SetSkipPointers(false)
.SetSkipReferences(false)
.SetDontShowChildren(true)
.SetDontShowValue(false)
.SetShowMembersOneLiner(false)
.SetHideItemNames(false);

using StringElementType = StringPrinter::StringElementType;

RegisterStdStringSummaryProvider(
cpp_category_sp, "std::u8string", "char8_t",
std::make_shared<CXXFunctionSummaryFormat>(
stl_summary_flags,
MsvcStlStringSummaryProvider<StringElementType::UTF8>,
"MSVC STL std::u8string summary provider"));
RegisterStdStringSummaryProvider(
cpp_category_sp, "std::u16string", "char16_t",
std::make_shared<CXXFunctionSummaryFormat>(
stl_summary_flags,
MsvcStlStringSummaryProvider<StringElementType::UTF16>,
"MSVC STL std::u16string summary provider"));
RegisterStdStringSummaryProvider(
cpp_category_sp, "std::u32string", "char32_t",
std::make_shared<CXXFunctionSummaryFormat>(
stl_summary_flags,
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
"MSVC STL std::u32string summary provider"));
}

static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
return;
Expand Down Expand Up @@ -1695,6 +1773,8 @@ lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
// LLDB prioritizes the last loaded matching formatter.
LoadLibCxxFormatters(g_category);
LoadLibStdcppFormatters(g_category);
LoadMsvcStlFormatters(g_category);
LoadCommonStlFormatters(g_category);
LoadSystemFormatters(g_category);
}
});
Expand Down
Loading
Loading