Skip to content

Commit 04f9fac

Browse files
authored
[lldb] optionally match the __debug namespace for libstdc++ containers. (llvm#140727)
If libstdc++ is compiled with `_GLIBCXX_DEBUG` flag it puts the containers in the namespace `std::__debug`. this causes the summary and synthetic formatters not to match the types. The formatters is updated to optionally match the `__debug::`. The formatters now clashed with the libc++ containers namespace regex which uses `std::__1` namespace The libc++ formatter is loaded first, then the libstdc++ since the priority of the formatters in lldb is the last one added. Fixes llvm#60841
1 parent 782a9e9 commit 04f9fac

File tree

5 files changed

+76
-35
lines changed

5 files changed

+76
-35
lines changed

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

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ class NodeAllocator {
592592
public:
593593
void reset() { Alloc.Reset(); }
594594

595-
template <typename T, typename... Args> T *makeNode(Args &&... args) {
595+
template <typename T, typename... Args> T *makeNode(Args &&...args) {
596596
return new (Alloc.Allocate(sizeof(T), alignof(T)))
597597
T(std::forward<Args>(args)...);
598598
}
@@ -614,7 +614,7 @@ class ManglingSubstitutor
614614
ManglingSubstitutor() : Base(nullptr, nullptr) {}
615615

616616
template <typename... Ts>
617-
ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) {
617+
ConstString substitute(llvm::StringRef Mangled, Ts &&...Vals) {
618618
this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
619619
return substituteImpl(Mangled);
620620
}
@@ -1449,47 +1449,50 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
14491449
stl_deref_flags.SetFrontEndWantsDereference();
14501450

14511451
cpp_category_sp->AddTypeSynthetic(
1452-
"^std::vector<.+>(( )?&)?$", eFormatterMatchRegex,
1452+
"^std::(__debug::)?vector<.+>(( )?&)?$", eFormatterMatchRegex,
14531453
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14541454
stl_synth_flags,
14551455
"lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
14561456
cpp_category_sp->AddTypeSynthetic(
1457-
"^std::map<.+> >(( )?&)?$", eFormatterMatchRegex,
1457+
"^std::(__debug::)?map<.+> >(( )?&)?$", eFormatterMatchRegex,
14581458
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14591459
stl_synth_flags,
14601460
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
14611461
cpp_category_sp->AddTypeSynthetic(
1462-
"^std::deque<.+>(( )?&)?$", eFormatterMatchRegex,
1462+
"^std::(__debug)?deque<.+>(( )?&)?$", eFormatterMatchRegex,
14631463
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14641464
stl_deref_flags,
14651465
"lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider")));
14661466
cpp_category_sp->AddTypeSynthetic(
1467-
"^std::set<.+> >(( )?&)?$", eFormatterMatchRegex,
1467+
"^std::(__debug::)?set<.+> >(( )?&)?$", eFormatterMatchRegex,
14681468
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14691469
stl_deref_flags,
14701470
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
14711471
cpp_category_sp->AddTypeSynthetic(
1472-
"^std::multimap<.+> >(( )?&)?$", eFormatterMatchRegex,
1472+
"^std::(__debug::)?multimap<.+> >(( )?&)?$", eFormatterMatchRegex,
14731473
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14741474
stl_deref_flags,
14751475
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
14761476
cpp_category_sp->AddTypeSynthetic(
1477-
"^std::multiset<.+> >(( )?&)?$", eFormatterMatchRegex,
1477+
"^std::(__debug::)?multiset<.+> >(( )?&)?$", eFormatterMatchRegex,
14781478
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14791479
stl_deref_flags,
14801480
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
14811481
cpp_category_sp->AddTypeSynthetic(
1482-
"^std::unordered_(multi)?(map|set)<.+> >$", eFormatterMatchRegex,
1482+
"^std::(__debug::)?unordered_(multi)?(map|set)<.+> >$",
1483+
eFormatterMatchRegex,
14831484
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14841485
stl_deref_flags,
14851486
"lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider")));
14861487
cpp_category_sp->AddTypeSynthetic(
1487-
"^std::(__cxx11::)?list<.+>(( )?&)?$", eFormatterMatchRegex,
1488+
"^std::((__debug::)?|(__cxx11::)?)list<.+>(( )?&)?$",
1489+
eFormatterMatchRegex,
14881490
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14891491
stl_deref_flags,
14901492
"lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
14911493
cpp_category_sp->AddTypeSynthetic(
1492-
"^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex,
1494+
"^std::((__debug::)?|(__cxx11::)?)forward_list<.+>(( )?&)?$",
1495+
eFormatterMatchRegex,
14931496
SyntheticChildrenSP(new ScriptedSyntheticChildren(
14941497
stl_synth_flags,
14951498
"lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider")));
@@ -1501,44 +1504,47 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
15011504

15021505
stl_summary_flags.SetDontShowChildren(false);
15031506
stl_summary_flags.SetSkipPointers(false);
1504-
cpp_category_sp->AddTypeSummary("^std::bitset<.+>(( )?&)?$",
1505-
eFormatterMatchRegex,
1506-
TypeSummaryImplSP(new StringSummaryFormat(
1507-
stl_summary_flags, "size=${svar%#}")));
1508-
cpp_category_sp->AddTypeSummary("^std::vector<.+>(( )?&)?$",
1509-
eFormatterMatchRegex,
1510-
TypeSummaryImplSP(new StringSummaryFormat(
1511-
stl_summary_flags, "size=${svar%#}")));
1512-
cpp_category_sp->AddTypeSummary("^std::map<.+> >(( )?&)?$",
1507+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?bitset<.+>(( )?&)?$",
15131508
eFormatterMatchRegex,
15141509
TypeSummaryImplSP(new StringSummaryFormat(
15151510
stl_summary_flags, "size=${svar%#}")));
1516-
cpp_category_sp->AddTypeSummary("^std::set<.+> >(( )?&)?$",
1511+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?vector<.+>(( )?&)?$",
15171512
eFormatterMatchRegex,
15181513
TypeSummaryImplSP(new StringSummaryFormat(
15191514
stl_summary_flags, "size=${svar%#}")));
1520-
cpp_category_sp->AddTypeSummary("^std::deque<.+>(( )?&)?$",
1515+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?map<.+> >(( )?&)?$",
15211516
eFormatterMatchRegex,
15221517
TypeSummaryImplSP(new StringSummaryFormat(
15231518
stl_summary_flags, "size=${svar%#}")));
1524-
cpp_category_sp->AddTypeSummary("^std::multimap<.+> >(( )?&)?$",
1519+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?set<.+> >(( )?&)?$",
15251520
eFormatterMatchRegex,
15261521
TypeSummaryImplSP(new StringSummaryFormat(
15271522
stl_summary_flags, "size=${svar%#}")));
1528-
cpp_category_sp->AddTypeSummary("^std::multiset<.+> >(( )?&)?$",
1523+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?deque<.+>(( )?&)?$",
15291524
eFormatterMatchRegex,
15301525
TypeSummaryImplSP(new StringSummaryFormat(
15311526
stl_summary_flags, "size=${svar%#}")));
1532-
cpp_category_sp->AddTypeSummary("^std::unordered_(multi)?(map|set)<.+> >$",
1527+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?multimap<.+> >(( )?&)?$",
15331528
eFormatterMatchRegex,
15341529
TypeSummaryImplSP(new StringSummaryFormat(
15351530
stl_summary_flags, "size=${svar%#}")));
1536-
cpp_category_sp->AddTypeSummary("^std::(__cxx11::)?list<.+>(( )?&)?$",
1531+
cpp_category_sp->AddTypeSummary("^std::(__debug::)?multiset<.+> >(( )?&)?$",
15371532
eFormatterMatchRegex,
15381533
TypeSummaryImplSP(new StringSummaryFormat(
15391534
stl_summary_flags, "size=${svar%#}")));
15401535
cpp_category_sp->AddTypeSummary(
1541-
"^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex,
1536+
"^std::(__debug::)?unordered_(multi)?(map|set)<.+> >$",
1537+
eFormatterMatchRegex,
1538+
TypeSummaryImplSP(
1539+
new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
1540+
cpp_category_sp->AddTypeSummary(
1541+
"^std::((__debug::)?|(__cxx11::)?)list<.+>(( )?&)?$",
1542+
eFormatterMatchRegex,
1543+
TypeSummaryImplSP(
1544+
new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
1545+
cpp_category_sp->AddTypeSummary(
1546+
"^std::((__debug::)?|(__cxx11::)?)forward_list<.+>(( )?&)?$",
1547+
eFormatterMatchRegex,
15421548
TypeSummaryImplSP(new ScriptSummaryFormat(
15431549
stl_summary_flags,
15441550
"lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider")));
@@ -1592,7 +1598,7 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
15921598
AddCXXSynthetic(
15931599
cpp_category_sp,
15941600
lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator,
1595-
"std::bitset synthetic child", "^std::bitset<.+>(( )?&)?$",
1601+
"std::bitset synthetic child", "^std::(__debug::)?bitset<.+>(( )?&)?$",
15961602
stl_deref_flags, true);
15971603

15981604
AddCXXSynthetic(
@@ -1731,8 +1737,12 @@ lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
17311737
DataVisualization::Categories::GetCategory(ConstString(GetPluginName()),
17321738
g_category);
17331739
if (g_category) {
1734-
LoadLibStdcppFormatters(g_category);
1740+
// NOTE: the libstdcpp formatters are loaded after libcxx formatters
1741+
// because we don't want to the libcxx formatters to match the potential
1742+
// `__debug` inline namespace that libstdcpp may use.
1743+
// LLDB prioritizes the last loaded matching formatter.
17351744
LoadLibCxxFormatters(g_category);
1745+
LoadLibStdcppFormatters(g_category);
17361746
LoadSystemFormatters(g_category);
17371747
}
17381748
});

lldb/test/API/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,5 +335,7 @@ def cleanup():
335335

336336
# and also validate that one can print formatters for a language
337337
self.expect(
338-
"type summary list -l c++", substrs=["vector", "map", "list", "string"]
338+
"type summary list -l c++",
339+
substrs=["vector", "map", "list", "string"],
340+
ordered=False,
339341
)

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Test lldb data formatter subsystem.
33
"""
44

5-
5+
from typing import Optional
66
import lldb
77
from lldbsuite.test.decorators import *
88
from lldbsuite.test.lldbtest import *
@@ -19,8 +19,17 @@ def setUp(self):
1919
@add_test_categories(["libstdcxx"])
2020
@expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
2121
def test_with_run_command(self):
22+
self.with_run_command()
23+
24+
@add_test_categories(["libstdcxx"])
25+
@expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
26+
def test_with_run_command_debug(self):
27+
build_args = {"CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
28+
self.with_run_command("__debug::", build_args)
29+
30+
def with_run_command(self, namespace: str = "", dictionary: Optional[dict] = None):
2231
"""Test that that file and class static variables display correctly."""
23-
self.build()
32+
self.build(dictionary=dictionary)
2433
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
2534

2635
lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line.")
@@ -48,7 +57,7 @@ def cleanup():
4857
self.runCmd("frame variable ii --show-types")
4958

5059
self.runCmd(
51-
'type summary add -x "std::map<" --summary-string "map has ${svar%#} items" -e'
60+
f'type summary add -x "std::{namespace}map<" --summary-string "map has ${{svar%#}} items" -e'
5261
)
5362

5463
self.expect("frame variable ii", substrs=["map has 0 items", "{}"])

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55

6+
from typing import Optional
67
import lldb
78
from lldbsuite.test.decorators import *
89
from lldbsuite.test.lldbtest import *
@@ -16,10 +17,19 @@ def setUp(self):
1617
# Find the line number to break at.
1718
self.line = line_number("main.cpp", "// Set break point at this line.")
1819

20+
@skip
1921
@add_test_categories(["libstdcxx"])
2022
def test_with_run_command(self):
23+
self.with_run_command()
24+
25+
@add_test_categories(["libstdcxx"])
26+
def test_with_run_command_debug(self):
27+
build_args = {"CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
28+
self.with_run_command(build_args)
29+
30+
def with_run_command(self, dictionary: Optional[dict] = None):
2131
"""Test that that file and class static variables display correctly."""
22-
self.build()
32+
self.build(dictionary=dictionary)
2333
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
2434

2535
lldbutil.run_break_set_by_file_and_line(

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55

6+
from typing import Optional
67
import lldb
78
from lldbsuite.test.decorators import *
89
from lldbsuite.test.lldbtest import *
@@ -19,8 +20,17 @@ def setUp(self):
1920
@add_test_categories(["libstdcxx"])
2021
@expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
2122
def test_with_run_command(self):
23+
self.with_run_command()
24+
25+
@add_test_categories(["libstdcxx"])
26+
@expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
27+
def test_with_run_command_debug(self):
28+
build_args = {"CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
29+
self.with_run_command(build_args)
30+
31+
def with_run_command(self, dictionary: Optional[dict] = None):
2232
"""Test that that file and class static variables display correctly."""
23-
self.build()
33+
self.build(dictionary=dictionary)
2434
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
2535

2636
lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line.")

0 commit comments

Comments
 (0)