Author: Ebuka Ezike
Date: 2025-05-27T20:52:51+01:00
New Revision: 04f9fac62238a4af2755e40b8020c64b3055c19a

URL: 
https://github.com/llvm/llvm-project/commit/04f9fac62238a4af2755e40b8020c64b3055c19a
DIFF: 
https://github.com/llvm/llvm-project/commit/04f9fac62238a4af2755e40b8020c64b3055c19a.diff

LOG: [lldb] optionally match the `__debug` namespace for libstdc++ containers. 
(#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 #60841

Added: 
    

Modified: 
    lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
    
lldb/test/API/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
    
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
    
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
    
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 542f13bef23e7..b178e06a975cd 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -592,7 +592,7 @@ class NodeAllocator {
 public:
   void reset() { Alloc.Reset(); }
 
-  template <typename T, typename... Args> T *makeNode(Args &&... args) {
+  template <typename T, typename... Args> T *makeNode(Args &&...args) {
     return new (Alloc.Allocate(sizeof(T), alignof(T)))
         T(std::forward<Args>(args)...);
   }
@@ -614,7 +614,7 @@ class ManglingSubstitutor
   ManglingSubstitutor() : Base(nullptr, nullptr) {}
 
   template <typename... Ts>
-  ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) {
+  ConstString substitute(llvm::StringRef Mangled, Ts &&...Vals) {
     this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
     return substituteImpl(Mangled);
   }
@@ -1449,47 +1449,50 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   stl_deref_flags.SetFrontEndWantsDereference();
 
   cpp_category_sp->AddTypeSynthetic(
-      "^std::vector<.+>(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug::)?vector<.+>(( )?&)?$", eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_synth_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::map<.+> >(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug::)?map<.+> >(( )?&)?$", eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_synth_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::deque<.+>(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug)?deque<.+>(( )?&)?$", eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::set<.+> >(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug::)?set<.+> >(( )?&)?$", eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::multimap<.+> >(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug::)?multimap<.+> >(( )?&)?$", eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::multiset<.+> >(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug::)?multiset<.+> >(( )?&)?$", eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::unordered_(multi)?(map|set)<.+> >$", eFormatterMatchRegex,
+      "^std::(__debug::)?unordered_(multi)?(map|set)<.+> >$",
+      eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::(__cxx11::)?list<.+>(( )?&)?$", eFormatterMatchRegex,
+      "^std::((__debug::)?|(__cxx11::)?)list<.+>(( )?&)?$",
+      eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
   cpp_category_sp->AddTypeSynthetic(
-      "^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex,
+      "^std::((__debug::)?|(__cxx11::)?)forward_list<.+>(( )?&)?$",
+      eFormatterMatchRegex,
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_synth_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider")));
@@ -1501,44 +1504,47 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
 
   stl_summary_flags.SetDontShowChildren(false);
   stl_summary_flags.SetSkipPointers(false);
-  cpp_category_sp->AddTypeSummary("^std::bitset<.+>(( )?&)?$",
-                                  eFormatterMatchRegex,
-                                  TypeSummaryImplSP(new StringSummaryFormat(
-                                      stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::vector<.+>(( )?&)?$",
-                                  eFormatterMatchRegex,
-                                  TypeSummaryImplSP(new StringSummaryFormat(
-                                      stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::map<.+> >(( )?&)?$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?bitset<.+>(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::set<.+> >(( )?&)?$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?vector<.+>(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::deque<.+>(( )?&)?$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?map<.+> >(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::multimap<.+> >(( )?&)?$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?set<.+> >(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::multiset<.+> >(( )?&)?$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?deque<.+>(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::unordered_(multi)?(map|set)<.+> >$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?multimap<.+> >(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
-  cpp_category_sp->AddTypeSummary("^std::(__cxx11::)?list<.+>(( )?&)?$",
+  cpp_category_sp->AddTypeSummary("^std::(__debug::)?multiset<.+> >(( )?&)?$",
                                   eFormatterMatchRegex,
                                   TypeSummaryImplSP(new StringSummaryFormat(
                                       stl_summary_flags, "size=${svar%#}")));
   cpp_category_sp->AddTypeSummary(
-      "^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex,
+      "^std::(__debug::)?unordered_(multi)?(map|set)<.+> >$",
+      eFormatterMatchRegex,
+      TypeSummaryImplSP(
+          new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+  cpp_category_sp->AddTypeSummary(
+      "^std::((__debug::)?|(__cxx11::)?)list<.+>(( )?&)?$",
+      eFormatterMatchRegex,
+      TypeSummaryImplSP(
+          new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+  cpp_category_sp->AddTypeSummary(
+      "^std::((__debug::)?|(__cxx11::)?)forward_list<.+>(( )?&)?$",
+      eFormatterMatchRegex,
       TypeSummaryImplSP(new ScriptSummaryFormat(
           stl_summary_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider")));
@@ -1592,7 +1598,7 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   AddCXXSynthetic(
       cpp_category_sp,
       lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator,
-      "std::bitset synthetic child", "^std::bitset<.+>(( )?&)?$",
+      "std::bitset synthetic child", "^std::(__debug::)?bitset<.+>(( )?&)?$",
       stl_deref_flags, true);
 
   AddCXXSynthetic(
@@ -1731,8 +1737,12 @@ lldb::TypeCategoryImplSP 
CPlusPlusLanguage::GetFormatters() {
     DataVisualization::Categories::GetCategory(ConstString(GetPluginName()),
                                                g_category);
     if (g_category) {
-      LoadLibStdcppFormatters(g_category);
+      // NOTE: the libstdcpp formatters are loaded after libcxx formatters
+      // because we don't want to the libcxx formatters to match the potential
+      // `__debug` inline namespace that libstdcpp may use.
+      // LLDB prioritizes the last loaded matching formatter.
       LoadLibCxxFormatters(g_category);
+      LoadLibStdcppFormatters(g_category);
       LoadSystemFormatters(g_category);
     }
   });

diff  --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
index f602d017f28b7..f659f1edd1fc9 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
@@ -335,5 +335,7 @@ def cleanup():
 
         # and also validate that one can print formatters for a language
         self.expect(
-            "type summary list -l c++", substrs=["vector", "map", "list", 
"string"]
+            "type summary list -l c++",
+            substrs=["vector", "map", "list", "string"],
+            ordered=False,
         )

diff  --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
index 1f3fa911256f6..2d76c02657a7d 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
@@ -2,7 +2,7 @@
 Test lldb data formatter subsystem.
 """
 
-
+from typing import Optional
 import lldb
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
@@ -19,8 +19,17 @@ def setUp(self):
     @add_test_categories(["libstdcxx"])
     @expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
     def test_with_run_command(self):
+        self.with_run_command()
+
+    @add_test_categories(["libstdcxx"])
+    @expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
+    def test_with_run_command_debug(self):
+        build_args = {"CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
+        self.with_run_command("__debug::", build_args)
+
+    def with_run_command(self, namespace: str = "", dictionary: Optional[dict] 
= None):
         """Test that that file and class static variables display correctly."""
-        self.build()
+        self.build(dictionary=dictionary)
         self.runCmd("file " + self.getBuildArtifact("a.out"), 
CURRENT_EXECUTABLE_SET)
 
         lldbutil.run_break_set_by_source_regexp(self, "Set break point at this 
line.")
@@ -48,7 +57,7 @@ def cleanup():
         self.runCmd("frame variable ii --show-types")
 
         self.runCmd(
-            'type summary add -x "std::map<" --summary-string "map has 
${svar%#} items" -e'
+            f'type summary add -x "std::{namespace}map<" --summary-string "map 
has ${{svar%#}} items" -e'
         )
 
         self.expect("frame variable ii", substrs=["map has 0 items", "{}"])

diff  --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
index df98fd5e2899c..f3371bc014b17 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
@@ -3,6 +3,7 @@
 """
 
 
+from typing import Optional
 import lldb
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
@@ -16,10 +17,19 @@ def setUp(self):
         # Find the line number to break at.
         self.line = line_number("main.cpp", "// Set break point at this line.")
 
+    @skip
     @add_test_categories(["libstdcxx"])
     def test_with_run_command(self):
+        self.with_run_command()
+
+    @add_test_categories(["libstdcxx"])
+    def test_with_run_command_debug(self):
+        build_args = {"CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
+        self.with_run_command(build_args)
+
+    def with_run_command(self, dictionary: Optional[dict] = None):
         """Test that that file and class static variables display correctly."""
-        self.build()
+        self.build(dictionary=dictionary)
         self.runCmd("file " + self.getBuildArtifact("a.out"), 
CURRENT_EXECUTABLE_SET)
 
         lldbutil.run_break_set_by_file_and_line(

diff  --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py
index bb9ffcfc9a77e..6cfd17a39304e 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py
@@ -3,6 +3,7 @@
 """
 
 
+from typing import Optional
 import lldb
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
@@ -19,8 +20,17 @@ def setUp(self):
     @add_test_categories(["libstdcxx"])
     @expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
     def test_with_run_command(self):
+        self.with_run_command()
+
+    @add_test_categories(["libstdcxx"])
+    @expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc")
+    def test_with_run_command_debug(self):
+        build_args = {"CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
+        self.with_run_command(build_args)
+
+    def with_run_command(self, dictionary: Optional[dict] = None):
         """Test that that file and class static variables display correctly."""
-        self.build()
+        self.build(dictionary=dictionary)
         self.runCmd("file " + self.getBuildArtifact("a.out"), 
CURRENT_EXECUTABLE_SET)
 
         lldbutil.run_break_set_by_source_regexp(self, "Set break point at this 
line.")


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to