https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/194916
>From 84963638195f4d5d86ea783f1b8db4ec4176c3aa Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Sat, 6 Jun 2026 11:44:23 +0200 Subject: [PATCH] [lldb][Docs] Add examples section for variable formatting --- lldb/docs/use/variable.md | 107 +++++++++++++++++++++++++++++++ llvm/utils/lldbDataFormatters.py | 4 ++ 2 files changed, 111 insertions(+) diff --git a/lldb/docs/use/variable.md b/lldb/docs/use/variable.md index 35096cf2f2cc7..7b484cf7d9bcf 100644 --- a/lldb/docs/use/variable.md +++ b/lldb/docs/use/variable.md @@ -1451,6 +1451,113 @@ displayed. The reason the debugger warns you is that enabling an empty category might be a typo, and you effectively wanted to enable a similarly-named but not-empty category. +## Examples + +These are a few examples of summaries and synthetic children providers for +types you may want to format. + +You can find further examples here: + +- [LLVM Data Formatters](https://github.com/llvm/llvm-project/blob/main/llvm/utils/lldbDataFormatters.py) +- [Coca (Objective-C) Formatters](https://github.com/llvm/llvm-project/tree/main/lldb/examples/summaries/cocoa) + +<!-- TODO: Add libc++ formatters here --> + +### Type Summaries + +- **Strings**: Many libraries have a user-defined string type that is + implemented with a data pointer and a size. For example, + [`llvm::StringRef`](https://llvm.org/doxygen/classllvm_1_1StringRef.html) is + implemented like: + + ```cpp + struct StringRef { + /// The start of the string, in an external buffer. + const char *Data; + /// The length of the string. + size_t Length; + }; + ``` + + We can use a `char[N]` array to create a summary for this string. + This technique handles escaping of non-printable characters like tabs or + newlines. + + ```{literalinclude} ../../../llvm/utils/lldbDataFormatters.py + :start-after: "[SNIP-StringRef-Summary]" + :end-before: "[/SNIP-StringRef-Summary]" + ``` + +- **Containers**: For most containers, displaying the number of elements in the + summary is sufficient. LLDB usually displays the number as `size=42` for + C++ STL types. If your container has a + [Synthetic Children](#synthetic-children) provider, you can use + [Summary Strings](#summary-strings): + + ``` + type summary add -s "size=${svar%#}" MyContainer + # Of if the container is a template: + type summary add -s "size=${svar%#}" -x "^MyContainer<.+>$" + ``` + +### Synthetic Children + +- **Spans**: This shows a synthetic children provider for + [`llvm::ArrayRef`](https://llvm.org/doxygen/classllvm_1_1ArrayRef.html). + This is similar to a `std::span`. It consists of a data pointer and a size: + + ```cpp + template <typename T> + struct ArrayRef { + /// The start of the array, in an external buffer. + const T *Data; + /// The number of elements. + size_t Length; + }; + ``` + + The two methods of interest here are `get_child_at_index` and `update`. + We're using `CreateChildAtOffset` to create the children when requested. + Note that this takes an offset in bytes, so we need to multiply by the size + of `T`. + + ```{literalinclude} ../../../llvm/utils/lldbDataFormatters.py + :start-after: "[SNIP-ArrayRef-Synth]" + :end-before: "[/SNIP-ArrayRef-Synth]" + ``` + +- **Synthetic Values**: You might have some types that wrap primitive types. + For example, you might have a class that provides checked arithmetic to guard + against overflow: + + ```cpp + struct CheckedInt { + int Value; + // Defines operator+, operator-, etc. + }; + ``` + + We can use `lldb.SBSyntheticValueProvider` to show the type as if it was + the inner `Value`: + + ```py + class CheckedIntSynthProvider(lldb.SBSyntheticValueProvider): + + valobj: lldb.SBValue + value: Optional[lldb.SBValue] + + def __init__(self, valobj: lldb.SBValue, internal_dict): + self.valobj = valobj + self.value = None + + def update(self): + self.value = self.valobj.GetChildAtIndex(0) + return False + + def get_value(self): + return self.value + ``` + ## Finding Formatters 101 Searching for a formatter (including formats, since LLDB 3.4.0) given a diff --git a/llvm/utils/lldbDataFormatters.py b/llvm/utils/lldbDataFormatters.py index c986f6695f88f..a69894d239a2b 100644 --- a/llvm/utils/lldbDataFormatters.py +++ b/llvm/utils/lldbDataFormatters.py @@ -146,6 +146,7 @@ def update(self): assert self.type_size != 0 +# [SNIP-ArrayRef-Synth] class ArrayRefSynthProvider: """Provider for llvm::ArrayRef""" @@ -183,6 +184,7 @@ def update(self): self.data_type = self.data.GetType().GetPointeeType() self.type_size = self.data_type.GetByteSize() assert self.type_size != 0 + # [/SNIP-ArrayRef-Synth] def SmallStringSummaryProvider(valobj: lldb.SBValue, internal_dict) -> str: @@ -198,6 +200,7 @@ def SmallStringSummaryProvider(valobj: lldb.SBValue, internal_dict) -> str: return res +# [SNIP-StringRef-Summary] def StringRefSummaryProvider(valobj: lldb.SBValue, internal_dict) -> str: data_pointer = valobj.GetChildMemberWithName("Data") length = valobj.GetChildMemberWithName("Length").unsigned @@ -217,6 +220,7 @@ def StringRefSummaryProvider(valobj: lldb.SBValue, internal_dict) -> str: # Use the builtin summary for its support of max-string-summary-length and # display of non-printable bytes. return char_array.summary + # [/SNIP-StringRef-Summary] def ConstStringSummaryProvider(valobj: lldb.SBValue, internal_dict) -> str: _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
