Files
llvm-project/lldb/source/DataFormatters/FormattersHelpers.cpp
Michael Buch 8f1cd07e3f [lldb][Format] Introduce a FormatEntity::Formatter class and move the Format API into it (#174618)
This patch creates a new `FormatEntity::Formatter` class and moves
`FormatEntity::Format` (and related APIs) into it. Most of the
parameters to `Format` are immutable across all recursive calls, so I
made them `const` member variables of `Formatter`. The main changes are
just mechanical renaming of:
```
FormatEntity::Format(...)
```
to
```
FormatEntity::Formatter(...).Format(stream, entry, valobj)
```
and making use of the member variables from inside `Format`.

We can probably make most of the parameters to the `Formatter`
constructor defaulted, but I chose not to in this patch to keep the diff
smaller.

The motivation for this is that I'm planning on adding logic to detect
recursive format entities (which would crash LLDB). That requires some
state, which in my opinion is best kept inside the `Formatter` class
instead of another parameter to `Format`.

The patch should be entirely NFC.
2026-01-07 15:40:55 +00:00

155 lines
5.7 KiB
C++

//===-- FormattersHelpers.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
void lldb_private::formatters::AddFormat(
TypeCategoryImpl::SharedPointer category_sp, lldb::Format format,
llvm::StringRef type_name, TypeFormatImpl::Flags flags, bool regex) {
lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags));
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeFormat(type_name, match_type, format_sp);
}
void lldb_private::formatters::AddSummary(
TypeCategoryImpl::SharedPointer category_sp, TypeSummaryImplSP summary_sp,
llvm::StringRef type_name, bool regex) {
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeSummary(type_name, match_type, summary_sp);
}
void lldb_private::formatters::AddStringSummary(
TypeCategoryImpl::SharedPointer category_sp, const char *string,
llvm::StringRef type_name, TypeSummaryImpl::Flags flags, bool regex) {
lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, string));
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeSummary(type_name, match_type, summary_sp);
}
void lldb_private::formatters::AddOneLineSummary(
TypeCategoryImpl::SharedPointer category_sp, llvm::StringRef type_name,
TypeSummaryImpl::Flags flags, bool regex) {
flags.SetShowMembersOneLiner(true);
lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, ""));
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeSummary(type_name, match_type, summary_sp);
}
void lldb_private::formatters::AddCXXSummary(
TypeCategoryImpl::SharedPointer category_sp,
CXXFunctionSummaryFormat::Callback funct, const char *description,
llvm::StringRef type_name, TypeSummaryImpl::Flags flags, bool regex) {
lldb::TypeSummaryImplSP summary_sp(
new CXXFunctionSummaryFormat(flags, funct, description));
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeSummary(type_name, match_type, summary_sp);
}
void lldb_private::formatters::AddCXXSynthetic(
TypeCategoryImpl::SharedPointer category_sp,
CXXSyntheticChildren::CreateFrontEndCallback generator,
const char *description, llvm::StringRef type_name,
ScriptedSyntheticChildren::Flags flags, bool regex) {
lldb::SyntheticChildrenSP synth_sp(
new CXXSyntheticChildren(flags, description, generator));
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeSynthetic(type_name, match_type, synth_sp);
}
void lldb_private::formatters::AddFilter(
TypeCategoryImpl::SharedPointer category_sp,
std::vector<std::string> children, const char *description,
llvm::StringRef type_name, ScriptedSyntheticChildren::Flags flags,
bool regex) {
TypeFilterImplSP filter_sp(new TypeFilterImpl(flags));
for (auto child : children)
filter_sp->AddExpressionPath(child);
FormatterMatchType match_type =
regex ? eFormatterMatchRegex : eFormatterMatchExact;
category_sp->AddTypeFilter(type_name, match_type, filter_sp);
}
std::optional<size_t>
lldb_private::formatters::ExtractIndexFromString(const char *item_name) {
if (!item_name || !*item_name)
return std::nullopt;
if (*item_name != '[')
return std::nullopt;
item_name++;
char *endptr = nullptr;
unsigned long int idx = ::strtoul(item_name, &endptr, 0);
if ((idx == 0 && endptr == item_name) || idx == ULONG_MAX)
return std::nullopt;
return idx;
}
Address
lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
ValueObject::AddrAndType data_addr;
if (valobj.IsPointerType())
data_addr = valobj.GetPointerValue();
else if (valobj.IsArrayType())
data_addr = valobj.GetAddressOf(/*scalar_is_load_address=*/true);
if (data_addr.address != LLDB_INVALID_ADDRESS &&
data_addr.type == eAddressTypeFile)
return Address(data_addr.address, valobj.GetModule()->GetSectionList());
return data_addr.address;
}
void lldb_private::formatters::DumpCxxSmartPtrPointerSummary(
Stream &stream, ValueObject &ptr, const TypeSummaryOptions &options) {
if (ptr.GetValueAsUnsigned(0) == 0) {
stream.Printf("nullptr");
return;
}
Status error;
ValueObjectSP pointee_sp = ptr.Dereference(error);
if (!pointee_sp || !error.Success())
return;
if (!pointee_sp->DumpPrintableRepresentation(
stream, ValueObject::eValueObjectRepresentationStyleSummary,
lldb::eFormatInvalid,
ValueObject::PrintableRepresentationSpecialCases::eDisable, false))
stream.Printf("ptr = 0x%" PRIx64, ptr.GetValueAsUnsigned(0));
}
bool lldb_private::formatters::ContainerSizeSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
return FormatEntity::Formatter(nullptr, nullptr, nullptr, false, false)
.FormatStringRef("size=${svar%#}", stream, &valobj);
}