https://github.com/adrian-prantl updated 
https://github.com/llvm/llvm-project/pull/184926

>From b1ef0ccaa846e61ae3b57595efbf86a71e419b5b Mon Sep 17 00:00:00 2001
From: Adrian Prantl <[email protected]>
Date: Thu, 5 Mar 2026 17:12:56 -0800
Subject: [PATCH 1/2] [LLDB] Allow one-line summaries in the presence of
 synthetic child providers

This is driven by the Swift language. In Swift many data types such as
Int, and String are structs, and LLDB provides summary formatters and
synthetic child providers for them. For String, for example, a summary
formatter pulls out the string data from the implementation, while a
synthetic child provider hides the implementation details from users,
so strings don't expand their children.

rdar://171646109
---
 lldb/source/DataFormatters/FormatManager.cpp  |  2 +-
 .../synth_oneline_summaries/Makefile          |  3 +++
 .../MyStringFormatter.py                      | 12 +++++++++++
 .../TestSyntheticOneLineSummaries.py          | 21 +++++++++++++++++++
 .../synth_oneline_summaries/main.c            | 16 ++++++++++++++
 5 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 
lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/Makefile
 create mode 100644 
lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/MyStringFormatter.py
 create mode 100644 
lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/TestSyntheticOneLineSummaries.py
 create mode 100644 
lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/main.c

diff --git a/lldb/source/DataFormatters/FormatManager.cpp 
b/lldb/source/DataFormatters/FormatManager.cpp
index 6d3faa5742d63..301b924a5625d 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -526,7 +526,7 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject 
&valobj) {
       if (!synth_sp->MightHaveChildren() &&
           synth_sp->DoesProvideSyntheticValue())
         is_synth_val = true;
-      else
+      else if (synth_sp->MightHaveChildren())
         return false;
     }
 
diff --git 
a/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/Makefile 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git 
a/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/MyStringFormatter.py
 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/MyStringFormatter.py
new file mode 100644
index 0000000000000..938194ee78146
--- /dev/null
+++ 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/MyStringFormatter.py
@@ -0,0 +1,12 @@
+import lldb
+
+
+class MyStringSynthProvider:
+    def __init__(self, valobj, dict):
+        self.valobj = valobj
+
+    def num_children(self, max_num_children):
+        return 0
+
+    def has_children(self):
+        return False
diff --git 
a/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/TestSyntheticOneLineSummaries.py
 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/TestSyntheticOneLineSummaries.py
new file mode 100644
index 0000000000000..4cada6efcca85
--- /dev/null
+++ 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/TestSyntheticOneLineSummaries.py
@@ -0,0 +1,21 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class SyntheticOneLineSummariesTestCase(TestBase):
+    def test(self):
+        """Test that the presence of a synthetic child provider doesn't 
prevent one-line-summaries."""
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "break here", 
lldb.SBFileSpec("main.c"))
+
+        # set up the synthetic children provider
+        self.runCmd("script from MyStringFormatter import *")
+        self.runCmd("type synth add -l MyStringSynthProvider MyString")
+        self.runCmd('type summary add --summary-string "${var.guts}" MyString')
+
+        self.expect(
+            "frame variable s",
+            substrs=['a = "hello", b = "world"'],
+        )
diff --git 
a/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/main.c 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/main.c
new file mode 100644
index 0000000000000..947be634f5b9b
--- /dev/null
+++ 
b/lldb/test/API/functionalities/data-formatter/synth_oneline_summaries/main.c
@@ -0,0 +1,16 @@
+struct MyString {
+  const char *guts;
+};
+
+struct S {
+  struct MyString a;
+  struct MyString b;
+};
+void stop() {}
+int main() {
+  struct S s;
+  s.a.guts = "hello";
+  s.b.guts = "world";
+  stop(); // break here
+  return 0;
+}

>From 7051eaaca2c7b71ca8aadcd167598bbf58bc2920 Mon Sep 17 00:00:00 2001
From: Adrian Prantl <[email protected]>
Date: Fri, 6 Mar 2026 08:21:17 -0800
Subject: [PATCH 2/2] [LLDB] Reformat comments

---
 lldb/source/DataFormatters/FormatManager.cpp | 57 ++++++++++----------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/lldb/source/DataFormatters/FormatManager.cpp 
b/lldb/source/DataFormatters/FormatManager.cpp
index 301b924a5625d..aa03f458e034a 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -458,11 +458,11 @@ lldb::Format 
FormatManager::GetSingleItemFormat(lldb::Format vector_format) {
 
 bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
   TargetSP target_sp = valobj.GetTargetSP();
-  // if settings say no oneline whatsoever
+  // If settings say no oneline whatsoever then don't oneline.
   if (target_sp && !target_sp->GetDebugger().GetAutoOneLineSummaries())
-    return false; // then don't oneline
+    return false;
 
-  // if this object has a summary, then ask the summary
+  // If this object has a summary, then ask the summary.
   if (valobj.GetSummaryFormat().get() != nullptr)
     return valobj.GetSummaryFormat()->IsOneLiner();
 
@@ -474,12 +474,12 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject 
&valobj) {
     llvm::consumeError(num_children.takeError());
     return true;
   }
-  // no children, no party
+  // No children, no party.
   if (*num_children == 0)
     return false;
 
-  // ask the type if it has any opinion about this eLazyBoolCalculate == no
-  // opinion; other values should be self explanatory
+  // Ask the type if it has any opinion about this:
+  //   eLazyBoolCalculate == no opinion
   CompilerType compiler_type(valobj.GetCompilerType());
   if (compiler_type.IsValid()) {
     switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) {
@@ -497,35 +497,36 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject 
&valobj) {
   for (size_t idx = 0; idx < *num_children; idx++) {
     bool is_synth_val = false;
     ValueObjectSP child_sp(valobj.GetChildAtIndex(idx));
-    // something is wrong here - bail out
+    // Something is wrong here - bail out.
     if (!child_sp)
       return false;
 
-    // also ask the child's type if it has any opinion
+    // Also ask the child's type if it has any opinion.
     CompilerType child_compiler_type(child_sp->GetCompilerType());
     if (child_compiler_type.IsValid()) {
       switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) {
       case eLazyBoolYes:
-      // an opinion of yes is only binding for the child, so keep going
+      // An opinion of yes is only binding for the child, so keep going,
       case eLazyBoolCalculate:
         break;
       case eLazyBoolNo:
-        // but if the child says no, then it's a veto on the whole thing
+        // but if the child says no, then it's a veto on the whole thing.
         return false;
       }
     }
 
-    // if we decided to define synthetic children for a type, we probably care
-    // enough to show them, but avoid nesting children in children
+    // If we decided to define synthetic children for a type, we probably care
+    // enough to show them, but avoid nesting children in children.
     if (child_sp->GetSyntheticChildren().get() != nullptr) {
       ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
-      // wait.. wat? just get out of here..
+      // Bail out if there was an error.
       if (!synth_sp)
         return false;
-      // but if we only have them to provide a value, keep going
+      // If we only have them to provide a value, keep going.
       if (!synth_sp->MightHaveChildren() &&
           synth_sp->DoesProvideSyntheticValue())
         is_synth_val = true;
+      // If there are synthetic children, the user probably wants to see them.
       else if (synth_sp->MightHaveChildren())
         return false;
     }
@@ -533,30 +534,30 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject 
&valobj) {
     total_children_name_len += child_sp->GetName().GetLength();
 
     // 50 itself is a "randomly" chosen number - the idea is that
-    // overly long structs should not get this treatment
+    // overly long structs should not get this treatment.
     // FIXME: maybe make this a user-tweakable setting?
     if (total_children_name_len > 50)
       return false;
 
-    // if a summary is there..
+    // If a summary is there...
     if (child_sp->GetSummaryFormat()) {
-      // and it wants children, then bail out
+      // and it wants children, then bail out.
       if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
         return false;
     }
 
-    // if this child has children..
+    // If this child has children,
     if (child_sp->HasChildren()) {
-      // ...and no summary...
-      // (if it had a summary and the summary wanted children, we would have
-      // bailed out anyway
-      //  so this only makes us bail out if this has no summary and we would
-      //  then print children)
-      if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do
-                                                          // that if not a
-                                                          // synthetic valued
-                                                          // child
-        return false;                                     // then bail out
+      // and no summary...
+      //
+      // Note that if it had a summary and the summary
+      // wanted children, we would have bailed out anyway so this only
+      // makes us bail out if this has no summary and we would then
+      // print children.
+      if (!child_sp->GetSummaryFormat() && !is_synth_val)
+        // But again only do that if not a synthetic valued child then
+        // bail out.
+        return false;
     }
   }
   return true;

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to