Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[lldb] Add print-braces setting for ValueObject printing#193812

Open
kastiglione wants to merge 3 commits intollvm:mainfrom
kastiglione:lldb-Add-print-braces-setting-for-ValueObject-printing
Open

[lldb] Add print-braces setting for ValueObject printing#193812
kastiglione wants to merge 3 commits intollvm:mainfrom
kastiglione:lldb-Add-print-braces-setting-for-ValueObject-printing

Conversation

@kastiglione
Copy link
Copy Markdown
Contributor

@kastiglione kastiglione commented Apr 23, 2026

Adds a new setting (print-braces) that controls whether curly brace "syntax" is emitted when printing the structure of ValueObjects. The default is true. Users who want to reduce the lines of output can set this to true, which eliminates lines containing only a closing } brace.

For large data types, this can reduce the output by a meaningful amount. For example types containing many shared_ptr/unique_ptr members.

Here's an example of output using the data type from the test:

Before:

(lldb) v
(Outer) s = {
  inner = {
    x = 1
    y = 2
  }
  z = 3
}

After:

(lldb) v
(Outer) s =
  inner =
    x = 1
    y = 2
  z = 3

Assisted-by: claude

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Apr 23, 2026

@llvm/pr-subscribers-lldb

Author: Dave Lee (kastiglione)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/193812.diff

11 Files Affected:

  • (modified) lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h (+3)
  • (modified) lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h (+1-1)
  • (modified) lldb/include/lldb/Target/Target.h (+2)
  • (modified) lldb/source/DataFormatters/DumpValueObjectOptions.cpp (+7-1)
  • (modified) lldb/source/DataFormatters/ValueObjectPrinter.cpp (+11-6)
  • (modified) lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp (+3)
  • (modified) lldb/source/Target/Target.cpp (+6)
  • (modified) lldb/source/Target/TargetProperties.td (+3)
  • (added) lldb/test/API/functionalities/data-formatter/print-braces/Makefile (+2)
  • (added) lldb/test/API/functionalities/data-formatter/print-braces/TestPrintBraces.py (+20)
  • (added) lldb/test/API/functionalities/data-formatter/print-braces/main.c (+14)
diff --git a/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h b/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
index 70166f33cfc45..4f3aeae3ad520 100644
--- a/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
+++ b/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
@@ -125,6 +125,8 @@ class DumpValueObjectOptions {
 
   DumpValueObjectOptions &SetRevealEmptyAggregates(bool reveal = true);
 
+  DumpValueObjectOptions &SetPrintBraces(bool print = true);
+
   DumpValueObjectOptions &SetExpandPointerTypeFlags(unsigned flags);
 
   DumpValueObjectOptions &SetElementCount(uint32_t element_count = 0);
@@ -162,6 +164,7 @@ class DumpValueObjectOptions {
   bool m_allow_oneliner_mode : 1;
   bool m_hide_pointer_value : 1;
   bool m_reveal_empty_aggregates : 1;
+  bool m_print_braces : 1;
 };
 
 } // namespace lldb_private
diff --git a/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
index 4fd552a6700b8..fe0251b12d364 100644
--- a/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
+++ b/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
@@ -44,7 +44,7 @@ class OptionGroupValueObjectDisplay : public OptionGroup {
 
   bool show_types : 1, show_location : 1, flat_output : 1, use_object_desc : 1,
       use_synth : 1, be_raw : 1, ignore_cap : 1, run_validator : 1,
-      max_depth_is_default : 1;
+      max_depth_is_default : 1, print_braces : 1;
 
   uint32_t no_summary_depth;
   uint32_t max_depth;
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 913e10eaf3479..0c2f61135953a 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -202,6 +202,8 @@ class TargetProperties : public Properties {
   /// otherwise false.
   std::pair<uint32_t, bool> GetMaximumDepthOfChildrenToDisplay() const;
 
+  bool GetPrintBraces() const;
+
   uint32_t GetMaximumSizeOfStringSummary() const;
 
   uint32_t GetMaximumMemReadSize() const;
diff --git a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
index e1df9522256fa..60158e7eec628 100644
--- a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
+++ b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
@@ -21,7 +21,8 @@ DumpValueObjectOptions::DumpValueObjectOptions()
       m_hide_root_type(false), m_hide_root_name(false), m_hide_name(false),
       m_hide_value(false), m_run_validator(false),
       m_use_type_display_name(true), m_allow_oneliner_mode(true),
-      m_hide_pointer_value(false), m_reveal_empty_aggregates(true) {}
+      m_hide_pointer_value(false), m_reveal_empty_aggregates(true),
+      m_print_braces(true) {}
 
 DumpValueObjectOptions::DumpValueObjectOptions(ValueObject &valobj)
     : DumpValueObjectOptions() {
@@ -210,6 +211,11 @@ DumpValueObjectOptions::SetRevealEmptyAggregates(bool reveal) {
   return *this;
 }
 
+DumpValueObjectOptions &DumpValueObjectOptions::SetPrintBraces(bool print) {
+  m_print_braces = print;
+  return *this;
+}
+
 DumpValueObjectOptions &
 DumpValueObjectOptions::SetExpandPointerTypeFlags(unsigned flags) {
   m_expand_ptr_type_flags = flags;
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 002638024c64b..4142ce383bb11 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -583,12 +583,16 @@ void ValueObjectPrinter::PrintChildrenPreamble(bool value_printed,
       m_stream->EOL();
   } else {
     if (ShouldPrintValueObject()) {
-      if (IsRef()) {
-        m_stream->PutCString(": ");
-      } else if (value_printed || summary_printed || ShouldShowName()) {
-        m_stream->PutChar(' ');
+      if (m_options.m_print_braces) {
+        if (IsRef()) {
+          m_stream->PutCString(": ");
+        } else if (value_printed || summary_printed || ShouldShowName()) {
+          m_stream->PutChar(' ');
+        }
+
+        m_stream->PutChar('{');
       }
-      m_stream->PutCString("{\n");
+      m_stream->EOL();
     }
     m_stream->IndentMore();
   }
@@ -667,7 +671,8 @@ void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {
       m_stream->Indent("...\n");
     }
     m_stream->IndentLess();
-    m_stream->Indent("}\n");
+    if (m_options.m_print_braces)
+      m_stream->Indent("}\n");
   }
 }
 
diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index 1939d79fec6a9..df75ba2681aa9 100644
--- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -172,6 +172,7 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting(
   be_raw = false;
   ignore_cap = false;
   run_validator = false;
+  print_braces = true;
 
   TargetSP target_sp =
       execution_context ? execution_context->GetTargetSP() : TargetSP();
@@ -180,6 +181,7 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting(
     auto max_depth_config = target_sp->GetMaximumDepthOfChildrenToDisplay();
     max_depth = std::get<uint32_t>(max_depth_config);
     max_depth_is_default = std::get<bool>(max_depth_config);
+    print_braces = target_sp->GetPrintBraces();
   } else {
     // If we don't have any targets, then dynamic values won't do us much good.
     use_dynamic = lldb::eNoDynamicValues;
@@ -203,6 +205,7 @@ DumpValueObjectOptions OptionGroupValueObjectDisplay::GetAsDumpOptions(
       .SetUseSyntheticValue(use_synth)
       .SetFlatOutput(flat_output)
       .SetIgnoreCap(ignore_cap)
+      .SetPrintBraces(print_braces)
       .SetFormat(format)
       .SetSummary(summary_sp);
 
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 27ddc4e7e5092..fbd156e40f4cd 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -5004,6 +5004,12 @@ TargetProperties::GetMaximumDepthOfChildrenToDisplay() const {
   return {option_value->GetCurrentValue(), is_default};
 }
 
+bool TargetProperties::GetPrintBraces() const {
+  const uint32_t idx = ePropertyPrintBraces;
+  return GetPropertyAtIndexAs<bool>(
+      idx, g_target_properties[idx].default_uint_value != 0);
+}
+
 uint32_t TargetProperties::GetMaximumSizeOfStringSummary() const {
   const uint32_t idx = ePropertyMaxSummaryLength;
   return GetPropertyAtIndexAs<uint64_t>(
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 223a12e059258..a694fe4145188 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -101,6 +101,9 @@ let Definition = "target", Path = "target" in {
   def MaxChildrenDepth: Property<"max-children-depth", "UInt64">,
     DefaultUnsignedValue<5>,
     Desc<"Maximum depth to expand children.">;
+  def PrintBraces: Property<"print-braces", "Boolean">,
+    DefaultTrue,
+    Desc<"Print curly braces around structures when displaying variable values.">;
   def MaxSummaryLength: Property<"max-string-summary-length", "UInt64">,
     DefaultUnsignedValue<1024>,
     Desc<"Maximum number of characters to show when using %s in summary strings.">;
diff --git a/lldb/test/API/functionalities/data-formatter/print-braces/Makefile b/lldb/test/API/functionalities/data-formatter/print-braces/Makefile
new file mode 100644
index 0000000000000..c9319d6e6888a
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/print-braces/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := main.c
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/print-braces/TestPrintBraces.py b/lldb/test/API/functionalities/data-formatter/print-braces/TestPrintBraces.py
new file mode 100644
index 0000000000000..866d562ab7f0a
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/print-braces/TestPrintBraces.py
@@ -0,0 +1,20 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestPrintBraces(TestBase):
+    def test_default_has_braces(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.c"))
+        self.expect("frame variable s", substrs=["{", "}"])
+
+    def test_no_braces(self):
+        self.build()
+        self.runCmd("settings set target.print-braces false")
+        lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.c"))
+        self.expect(
+            "frame variable s", matching=False, substrs=["{", "}"]
+        )
+        self.expect("frame variable s", substrs=["x = 1", "y = 2", "z = 3"])
diff --git a/lldb/test/API/functionalities/data-formatter/print-braces/main.c b/lldb/test/API/functionalities/data-formatter/print-braces/main.c
new file mode 100644
index 0000000000000..52345c7a1503a
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/print-braces/main.c
@@ -0,0 +1,14 @@
+struct Inner {
+  int x;
+  int y;
+};
+
+struct Outer {
+  struct Inner inner;
+  int z;
+};
+
+int main(void) {
+  struct Outer s = {{1, 2}, 3};
+  return s.z; // break here
+}

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 23, 2026

✅ With the latest revision this PR passed the Python code formatter.

@jimingham
Copy link
Copy Markdown
Collaborator

jimingham commented Apr 23, 2026

Seems likely some folks will like this. The implementation seems fine.

It's a little odd that it lives in debugger, not target. Debugger has the following that control ValueObject printing:

auto-one-line-summaries
dwim-print-verbosity

whereas Target has:

enable-synthetic-value
max-children-count
max-children-depth
max-string-summary-length
max-zero-padding-in-float-format
prefer-dynamic-value
show-hex-variable-values-with-leading-zeroes

What was your reasoning?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants