Skip to content

[cherry-pick][stable/20230725] [lldb] Add std::chrono and std::valarray libc++ formatters #8190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions lldb/include/lldb/DataFormatters/TypeSynthetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ class SyntheticChildrenFrontEnd {

virtual size_t GetIndexOfChildWithName(ConstString name) = 0;

// this function is assumed to always succeed and it if fails, the front-end
// should know to deal with it in the correct way (most probably, by refusing
// to return any children) the return value of Update() should actually be
// interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
// ValueObjectSyntheticFilter is allowed to use the children it fetched
// previously and cached if =false, ValueObjectSyntheticFilter must throw
// away its cache, and query again for children
virtual bool Update() = 0;
/// This function is assumed to always succeed and if it fails, the front-end
/// should know to deal with it in the correct way (most probably, by refusing
/// to return any children). The return value of \ref Update should actually
/// be interpreted as "ValueObjectSyntheticFilter cache is good/bad". If this
/// function returns \ref lldb::ChildCacheState::eReuse, \ref
/// ValueObjectSyntheticFilter is allowed to use the children it fetched
/// previously and cached. Otherwise, \ref ValueObjectSyntheticFilter must
/// throw away its cache, and query again for children.
virtual lldb::ChildCacheState Update() = 0;

// if this function returns false, then CalculateNumChildren() MUST return 0
// since UI frontends might validly decide not to inquire for children given
Expand Down Expand Up @@ -116,7 +117,9 @@ class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
return UINT32_MAX;
}

bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}

bool MightHaveChildren() override { return false; }

Expand Down Expand Up @@ -328,7 +331,9 @@ class TypeFilterImpl : public SyntheticChildren {
filter->GetExpressionPathAtIndex(idx), true);
}

bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}

bool MightHaveChildren() override { return filter->GetCount() > 0; }

Expand Down Expand Up @@ -427,7 +432,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren {

lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

bool Update() override;
lldb::ChildCacheState Update() override;

bool MightHaveChildren() override;

Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/DataFormatters/VectorIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

bool Update() override;
lldb::ChildCacheState Update() override;

bool MightHaveChildren() override;

Expand Down
9 changes: 9 additions & 0 deletions lldb/include/lldb/lldb-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,15 @@ enum CompletionType {
eCustomCompletion = (1u << 25)
};

/// Specifies if children need to be re-computed
/// after a call to \ref SyntheticChildrenFrontEnd::Update.
enum class ChildCacheState {
eRefetch = 0, ///< Children need to be recomputed dynamically.

eReuse = 1, ///< Children did not change and don't need to be recomputed;
///< re-use what we computed the last time we called Update.
};

} // namespace lldb

#endif // LLDB_LLDB_ENUMERATIONS_H
6 changes: 4 additions & 2 deletions lldb/source/Core/ValueObjectSyntheticFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd {

bool MightHaveChildren() override { return true; }

bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}
};

ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
Expand Down Expand Up @@ -177,7 +179,7 @@ bool ValueObjectSynthetic::UpdateValue() {
}

// let our backend do its update
if (!m_synth_filter_up->Update()) {
if (m_synth_filter_up->Update() == lldb::ChildCacheState::eRefetch) {
LLDB_LOGF(log,
"[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
"filter said caches are stale - clearing",
Expand Down
8 changes: 5 additions & 3 deletions lldb/source/DataFormatters/TypeSynthetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,13 @@ size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) {
return m_interpreter->CalculateNumChildren(m_wrapper_sp, max);
}

bool ScriptedSyntheticChildren::FrontEnd::Update() {
lldb::ChildCacheState ScriptedSyntheticChildren::FrontEnd::Update() {
if (!m_wrapper_sp || m_interpreter == nullptr)
return false;
return lldb::ChildCacheState::eRefetch;

return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp);
return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp)
? lldb::ChildCacheState::eReuse
: lldb::ChildCacheState::eRefetch;
}

bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() {
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/DataFormatters/VectorType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
return child_sp;
}

bool Update() override {
lldb::ChildCacheState Update() override {
m_parent_format = m_backend.GetFormat();
CompilerType parent_type(m_backend.GetCompilerType());
CompilerType element_type;
Expand All @@ -258,7 +258,7 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
::CalculateNumChildren(element_type, num_elements, m_child_type)
.value_or(0);
m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
return false;
return lldb::ChildCacheState::eRefetch;
}

bool MightHaveChildren() override { return true; }
Expand Down
4 changes: 3 additions & 1 deletion lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

// return true if this object is now safe to use forever without ever
// updating again; the typical (and tested) answer here is 'false'
bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}

// maybe return false if the block pointer is, say, null
bool MightHaveChildren() override { return true; }
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
LibCxxVariant.cpp
LibCxxValarray.cpp
LibCxxVector.cpp
LibStdcpp.cpp
LibStdcppTuple.cpp
Expand Down
177 changes: 177 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
"libc++ std::vector synthetic children",
"^std::__[[:alnum:]]+::vector<.+>(( )?&)?$", stl_deref_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator,
"libc++ std::valarray synthetic children",
"^std::__[[:alnum:]]+::valarray<.+>$", stl_deref_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
Expand Down Expand Up @@ -887,6 +892,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::list summary provider",
"^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$",
stl_summary_flags, true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxContainerSummaryProvider,
"libc++ std::valarray summary provider",
"^std::__[[:alnum:]]+::valarray<.+>$", stl_summary_flags, true);
AddCXXSummary(
cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
"libc++ std::list summary provider",
Expand Down Expand Up @@ -986,6 +995,174 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::unordered_map iterator synthetic children",
"^std::__[[:alnum:]]+::__hash_map_(const_)?iterator<.+>$",
stl_synth_flags, true);
// Chrono duration typedefs
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::nanoseconds", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} ns")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::microseconds", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} µs")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::milliseconds", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} ms")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::seconds", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} s")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::minutes", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__rep_} min")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::hours", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} h")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::days", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__rep_} days")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::weeks", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__rep_} weeks")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::months", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__rep_} months")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::years", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__rep_} years")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::seconds", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} s")));

// Chrono time point types

AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoSysSecondsSummaryProvider,
"libc++ std::chrono::sys_seconds summary provider",
"^std::__[[:alnum:]]+::chrono::time_point<"
"std::__[[:alnum:]]+::chrono::system_clock, "
"std::__[[:alnum:]]+::chrono::duration<long long, "
"std::__[[:alnum:]]+::ratio<1, 1> "
"> >$",
eTypeOptionHideChildren | eTypeOptionHideValue |
eTypeOptionCascade,
true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoSysDaysSummaryProvider,
"libc++ std::chrono::sys_seconds summary provider",
"^std::__[[:alnum:]]+::chrono::time_point<"
"std::__[[:alnum:]]+::chrono::system_clock, "
"std::__[[:alnum:]]+::chrono::duration<int, "
"std::__[[:alnum:]]+::ratio<86400, 1> "
"> >$",
eTypeOptionHideChildren | eTypeOptionHideValue |
eTypeOptionCascade,
true);

// Chrono calendar types

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::day$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"day=${var.__d_%u}")));

AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoMonthSummaryProvider,
"libc++ std::chrono::month summary provider",
"^std::__[[:alnum:]]+::chrono::month$",
eTypeOptionHideChildren | eTypeOptionHideValue, true);

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "year=${var.__y_}")));

AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider,
"libc++ std::chrono::weekday summary provider",
"^std::__[[:alnum:]]+::chrono::weekday$",
eTypeOptionHideChildren | eTypeOptionHideValue, true);

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::weekday_indexed$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue,
"${var.__wd_} index=${var.__idx_%u}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::weekday_last$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__wd_} index=last")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_day$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} ${var.__d_}")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_day_last$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} day=last")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_weekday$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} ${var.__wdi_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_weekday_last$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} ${var.__wdl_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__y_} ${var.__m_}")));

AddCXXSummary(
cpp_category_sp,
lldb_private::formatters::LibcxxChronoYearMonthDaySummaryProvider,
"libc++ std::chrono::year_month_day summary provider",
"^std::__[[:alnum:]]+::chrono::year_month_day$",
eTypeOptionHideChildren | eTypeOptionHideValue, true);

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month_day_last$",
eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__y_} ${var.__mdl_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month_weekday$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue,
"${var.__y_} ${var.__m_} ${var.__wdi_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month_weekday_last$",
eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue,
"${var.__y_} ${var.__m_} ${var.__wdl_}")));
}

static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
Expand Down
Loading