[Lldb-commits] [lldb] [lldb] Add std::chrono formatters for libstdc++ and MSVC STL (PR #195125)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 30 09:55:32 PDT 2026
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/195125
>From a404c198821e3130879c9426f218140c9634cf05 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Thu, 30 Apr 2026 18:19:27 +0200
Subject: [PATCH] [lldb] Add std::chrono formatters for libstdc++ and MSVC STL
---
.../Plugins/Language/CPlusPlus/CMakeLists.txt | 1 +
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 365 +++++++------
.../Plugins/Language/CPlusPlus/Chrono.cpp | 491 ++++++++++++++++++
.../Plugins/Language/CPlusPlus/Chrono.h | 142 +++++
.../Plugins/Language/CPlusPlus/LibCxx.cpp | 188 -------
.../Plugins/Language/CPlusPlus/LibCxx.h | 28 -
.../chrono/TestDataFormatterStdChrono.py | 11 +
7 files changed, 820 insertions(+), 406 deletions(-)
create mode 100644 lldb/source/Plugins/Language/CPlusPlus/Chrono.cpp
create mode 100644 lldb/source/Plugins/Language/CPlusPlus/Chrono.h
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 68093f3c96017..611b885904429 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -12,6 +12,7 @@ lldb_tablegen(LanguageCPlusPlusProperties.json -dump-json
add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
BlockPointer.cpp
+ Chrono.cpp
Coroutines.cpp
CPlusPlusLanguage.cpp
CPlusPlusNameParser.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 7e68d25c0110f..e27dcfaaf8bc6 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -40,6 +40,7 @@
#include "BlockPointer.h"
#include "CPlusPlusNameParser.h"
+#include "Chrono.h"
#include "Coroutines.h"
#include "CxxStringTypes.h"
#include "Generic.h"
@@ -1095,213 +1096,195 @@ 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<.*, "
- "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);
- AddCXXSummary(
- cpp_category_sp,
- lldb_private::formatters::LibcxxChronoLocalSecondsSummaryProvider,
- "libc++ std::chrono::local_seconds summary provider",
- "^std::__[[:alnum:]]+::chrono::time_point<"
- "std::__[[:alnum:]]+::chrono::local_t, "
- "std::__[[:alnum:]]+::chrono::duration<.*, "
- "std::__[[:alnum:]]+::ratio<1, 1> "
- "> >$",
- eTypeOptionHideChildren | eTypeOptionHideValue | eTypeOptionCascade,
- true);
AddCXXSummary(cpp_category_sp,
- lldb_private::formatters::LibcxxChronoLocalDaysSummaryProvider,
- "libc++ std::chrono::local_seconds summary provider",
- "^std::__[[:alnum:]]+::chrono::time_point<"
- "std::__[[:alnum:]]+::chrono::local_t, "
- "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}")));
-
+ lldb_private::formatters::LibcxxPartialOrderingSummaryProvider,
+ "libc++ std::partial_ordering summary provider",
+ "^std::__[[:alnum:]]+::partial_ordering$",
+ eTypeOptionHideChildren | eTypeOptionHideValue, true);
AddCXXSummary(cpp_category_sp,
- lldb_private::formatters::LibcxxChronoMonthSummaryProvider,
- "libc++ std::chrono::month summary provider",
- "^std::__[[:alnum:]]+::chrono::month$",
+ lldb_private::formatters::LibcxxWeakOrderingSummaryProvider,
+ "libc++ std::weak_ordering summary provider",
+ "^std::__[[:alnum:]]+::weak_ordering$",
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$",
+ lldb_private::formatters::LibcxxStrongOrderingSummaryProvider,
+ "libc++ std::strong_ordering summary provider",
+ "^std::__[[:alnum:]]+::strong_ordering$",
eTypeOptionHideChildren | eTypeOptionHideValue, true);
+}
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::weekday_indexed$", eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(
- eTypeOptionHideChildren | eTypeOptionHideValue,
- "${var.__wd_} index=${var.__idx_%u}")));
+static void LoadStdChronoFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
+ TypeSummaryImpl::Flags chrono_flags;
+ chrono_flags.SetDontShowChildren(true).SetDontShowValue(true);
- 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")));
+ // Durations.
+ // These are typedefs. With PDB we don't have the typedef name, so match both
+ // the typedef'd name and the std::chrono::duration<> name.
+ AddCXXSummary(
+ cpp_category_sp, chrono::NanosecondsSummaryProvider,
+ "std::chrono::nanoseconds Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(nanoseconds|duration<__int64, ?std::"
+ "ratio<1, ?1000000000> ?>)",
+ chrono_flags, true);
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::month_weekday$", eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
- eTypeOptionHideValue,
- "${var.__m_} ${var.__wdi_}")));
+ AddCXXSummary(
+ cpp_category_sp, chrono::MicrosecondsSummaryProvider,
+ "std::chrono::microseconds Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(microseconds|duration<__int64, ?std::"
+ "ratio<1, ?1000000> ?>)",
+ chrono_flags, true);
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::month_weekday_last$", eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
- eTypeOptionHideValue,
- "${var.__m_} ${var.__wdl_}")));
+ AddCXXSummary(
+ cpp_category_sp, chrono::MillisecondsSummaryProvider,
+ "std::chrono::milliseconds Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(milliseconds|duration<__int64, ?std::"
+ "ratio<1, ?1000> ?>)",
+ chrono_flags, true);
+
+ AddCXXSummary(cpp_category_sp, chrono::SecondsSummaryProvider,
+ "std::chrono::seconds Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(seconds|duration<__int64, "
+ "?std::ratio<"
+ "1, ?1> ?>)",
+ chrono_flags, true);
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::year_month$", eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
- eTypeOptionHideValue,
- "${var.__y_} ${var.__m_}")));
+ AddCXXSummary(
+ cpp_category_sp, chrono::MinutesSummaryProvider,
+ "std::chrono::minutes Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(minutes|duration<int, ?std::ratio<"
+ "60, ?1> ?>)",
+ chrono_flags, true);
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, chrono::HoursSummaryProvider,
+ "std::chrono::hours Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(hours|duration<int, ?std::ratio<"
+ "3600, ?1> ?>)",
+ chrono_flags, true);
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::year_month_day_last$",
- eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
- eTypeOptionHideValue,
- "${var.__y_} ${var.__mdl_}")));
+ AddCXXSummary(
+ cpp_category_sp, chrono::DaysSummaryProvider, "std::chrono::days Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(days|duration<int, ?std::ratio<"
+ "86400, ?1> ?>)",
+ chrono_flags, true);
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::year_month_weekday$", eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(
- eTypeOptionHideChildren | eTypeOptionHideValue,
- "${var.__y_} ${var.__m_} ${var.__wdi_}")));
+ AddCXXSummary(
+ cpp_category_sp, chrono::WeeksSummaryProvider,
+ "std::chrono::weeks Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(weeks|duration<int, ?std::ratio<"
+ "604800, ?1> ?>)",
+ chrono_flags, true);
- cpp_category_sp->AddTypeSummary(
- "^std::__[[:alnum:]]+::chrono::year_month_weekday_last$",
- eFormatterMatchRegex,
- TypeSummaryImplSP(new StringSummaryFormat(
- eTypeOptionHideChildren | eTypeOptionHideValue,
- "${var.__y_} ${var.__m_} ${var.__wdl_}")));
+ AddCXXSummary(
+ cpp_category_sp, chrono::MonthsSummaryProvider,
+ "std::chrono::months Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(months|duration<int, ?std::ratio<"
+ "2629746, ?1> ?>)",
+ chrono_flags, true);
- AddCXXSummary(cpp_category_sp,
- lldb_private::formatters::LibcxxPartialOrderingSummaryProvider,
- "libc++ std::partial_ordering summary provider",
- "^std::__[[:alnum:]]+::partial_ordering$",
- eTypeOptionHideChildren | eTypeOptionHideValue, true);
- AddCXXSummary(cpp_category_sp,
- lldb_private::formatters::LibcxxWeakOrderingSummaryProvider,
- "libc++ std::weak_ordering summary provider",
- "^std::__[[:alnum:]]+::weak_ordering$",
- eTypeOptionHideChildren | eTypeOptionHideValue, true);
- AddCXXSummary(cpp_category_sp,
- lldb_private::formatters::LibcxxStrongOrderingSummaryProvider,
- "libc++ std::strong_ordering summary provider",
- "^std::__[[:alnum:]]+::strong_ordering$",
- eTypeOptionHideChildren | eTypeOptionHideValue, true);
+ AddCXXSummary(
+ cpp_category_sp, chrono::YearsSummaryProvider,
+ "std::chrono::years Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::(years|duration<int, ?std::ratio<"
+ "31556952, ?1> ?>)",
+ chrono_flags, true);
+
+ // Calendar types.
+ AddCXXSummary(cpp_category_sp, chrono::DaySummaryProvider,
+ "std::chrono::day Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::day$", chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::MonthSummaryProvider,
+ "std::chrono::month Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::month$", chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::YearSummaryProvider,
+ "std::chrono::year Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::year$", chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::WeekdaySummaryProvider,
+ "std::chrono::weekday Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::weekday$", chrono_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, chrono::WeekdayIndexedSummaryProvider,
+ "std::chrono::weekday_indexed Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::weekday_indexed$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::WeekdayLastSummaryProvider,
+ "std::chrono::weekday_last Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::weekday_last$", chrono_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, chrono::MonthDaySummaryProvider,
+ "std::chrono::month_day Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::month_day$", chrono_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, chrono::MonthDayLastSummaryProvider,
+ "std::chrono::month_day_last Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::month_day_last$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::MonthWeekdaySummaryProvider,
+ "std::chrono::month_weekday Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::month_weekday$", chrono_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, chrono::MonthWeekdayLastSummaryProvider,
+ "std::chrono::month_weekday_last Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::month_weekday_last$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::YearMonthSummaryProvider,
+ "std::chrono::year_month Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::year_month$", chrono_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, chrono::YearMonthDaySummaryProvider,
+ "std::chrono::year_month_day Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::year_month_day$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::YearMonthDayLastSummaryProvider,
+ "std::chrono::year_month_day_last Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::year_month_day_last$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::YearMonthWeekdaySummaryProvider,
+ "std::chrono::year_month_weekday Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::year_month_weekday$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::YearMonthWeekdayLastSummaryProvider,
+ "std::chrono::year_month_weekday_last Summary",
+ "^std(::__[[:alnum:]]+)?::chrono::year_month_weekday_last$",
+ chrono_flags, true);
+
+ // Timepoints.
+ chrono_flags.SetCascades(true);
+
+ AddCXXSummary(cpp_category_sp, chrono::SysSecondsSummaryProvider,
+ "std::chrono::sys_seconds summary provider",
+ "^std::(__[[:alnum:]]+::)?chrono::time_point<"
+ "std::(__[[:alnum:]]+::)?chrono::system_clock, ?"
+ "std::(__[[:alnum:]]+::)?chrono::duration<.*, ?"
+ "std::(__[[:alnum:]]+::)?ratio<1, 1> ?"
+ "> ?>$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::SysDaysSummaryProvider,
+ "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> ?"
+ "> ?>$",
+ chrono_flags, true);
+
+ AddCXXSummary(cpp_category_sp, chrono::LocalSecondsSummaryProvider,
+ "std::chrono::local_seconds summary provider",
+ "^std::(__[[:alnum:]]+::)?chrono::time_point<"
+ "std::(__[[:alnum:]]+::)?chrono::local_t, ?"
+ "std::(__[[:alnum:]]+::)?chrono::duration<.*, ?"
+ "std::(__[[:alnum:]]+::)?ratio<1, 1> ?"
+ "> ?>$",
+ chrono_flags, true);
+ AddCXXSummary(cpp_category_sp, chrono::LocalDaysSummaryProvider,
+ "std::chrono::local_seconds summary provider",
+ "^std::(__[[:alnum:]]+::)?chrono::time_point<"
+ "std::(__[[:alnum:]]+::)?chrono::local_t, ?"
+ "std::(__[[:alnum:]]+::)?chrono::duration<int, ?"
+ "std::(__[[:alnum:]]+::)?ratio<86400, 1> ?"
+ "> ?>$",
+ chrono_flags, true);
}
static void RegisterStdStringSummaryProvider(
@@ -1935,6 +1918,8 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"MSVC STL/libstdc++ std::strong_ordering summary provider",
"std::strong_ordering",
eTypeOptionHideChildren | eTypeOptionHideValue, false);
+
+ LoadStdChronoFormatters(cpp_category_sp);
}
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/Chrono.cpp b/lldb/source/Plugins/Language/CPlusPlus/Chrono.cpp
new file mode 100644
index 0000000000000..3e425b658b981
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/Chrono.cpp
@@ -0,0 +1,491 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "Chrono.h"
+
+#include "lldb/ValueObject/ValueObject.h"
+
+#include <ctime>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+/// Helper to get members of a type from different STLs.
+///
+/// The member names of the different STL types are expected to be unique.
+///
+/// \tparam N Number of members to get.
+template <size_t N = 1> struct TryStl {
+ static_assert(N > 0);
+
+ using Array = ValueObjectSP[N];
+
+ explicit TryStl(ValueObject &source) : source(source) {}
+ TryStl(const TryStl &) = delete;
+ TryStl(TryStl &&) = delete;
+ TryStl &operator=(const TryStl &) = delete;
+ TryStl &operator=(TryStl &&) = delete;
+
+ template <typename... Str> TryStl &Libcxx(Str... strs) {
+ return Try(std::forward<Str>(strs)...);
+ }
+ template <typename... Str> TryStl &Libstdcxx(Str... strs) {
+ return Try(std::forward<Str>(strs)...);
+ }
+ template <typename... Str> TryStl &Msvc(Str... strs) {
+ return Try(std::forward<Str>(strs)...);
+ }
+
+ ValueObjectSP TakeFirst() { return std::move(valobjs[0]); }
+
+ Array &&All() { return std::move(valobjs); }
+
+private:
+ template <typename... Str> TryStl &Try(llvm::StringRef first, Str... rest) {
+ if (done)
+ return *this;
+ static_assert(sizeof...(rest) + 1 == N, "Must provide exactly N strings");
+
+ // Only check the first member - if this matches, we can get the rest.
+ valobjs[0] = source.GetChildMemberWithName(first);
+ if (!valobjs[0])
+ return *this;
+
+ done = true;
+ size_t i = 1;
+ ((valobjs[i++] = source.GetChildMemberWithName(rest)), ...);
+ return *this;
+ }
+
+ bool done = false;
+ ValueObject &source;
+ ValueObjectSP valobjs[N]{};
+};
+
+TryStl(ValueObject &) -> TryStl<1>;
+
+ValueObjectSP TryOne(ValueObject &source, llvm::StringRef libcxx,
+ llvm::StringRef libstdcxx, llvm::StringRef msvc) {
+ return TryStl(source)
+ .Libcxx(libcxx)
+ .Libstdcxx(libstdcxx)
+ .Msvc(msvc)
+ .TakeFirst();
+}
+
+bool ChronoDurationFormat(ValueObject &valobj, Stream &stream,
+ llvm::StringRef unit) {
+ ValueObjectSP rep_sp = TryOne(valobj, "__rep_", "__r", "_MyRep");
+ if (!rep_sp)
+ return false;
+ int64_t rep = rep_sp->GetValueAsSigned(0);
+ stream << llvm::formatv("{0} {1}", rep, unit);
+ return true;
+}
+
+std::optional<int64_t> TimePointDuration(ValueObject &valobj) {
+ ValueObjectSP dur_sp = TryOne(valobj, "__d_", "__d", "_MyDur");
+ if (!dur_sp)
+ return std::nullopt;
+ dur_sp = dur_sp->GetChildAtIndex(0); // Rep
+ if (!dur_sp)
+ return std::nullopt;
+ return dur_sp->GetValueAsSigned(0);
+}
+
+bool TimePointSummary(ValueObject &valobj, Stream &stream, std::time_t to_sec,
+ const char *fmt, const char *suffix) {
+ std::optional<int64_t> tp_duration = TimePointDuration(valobj);
+ if (!tp_duration)
+ return false;
+
+#ifndef _WIN32
+ // The date time in the chrono library is valid in the range
+ // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a
+ // larger range, the function strftime is not able to format the entire range
+ // of time_t. The exact point has not been investigated; it's limited to
+ // chrono's range.
+ const std::time_t chrono_timestamp_min =
+ -1'096'193'779'200; // -32767-01-01T00:00:00Z
+ const std::time_t chrono_timestamp_max =
+ 971'890'963'199; // 32767-12-31T23:59:59Z
+#else
+ const std::time_t chrono_timestamp_min = -43'200; // 1969-12-31T12:00:00Z
+ const std::time_t chrono_timestamp_max =
+ 32'536'850'399; // 3001-01-19T21:59:59
+#endif
+
+ const std::time_t seconds = *tp_duration * to_sec;
+ if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max)
+ stream.Printf("timestamp=%" PRId64 " %s", *tp_duration, suffix);
+ else {
+ std::array<char, 128> str;
+ std::size_t size =
+ std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
+ if (size == 0)
+ return false;
+
+ const char *label = to_sec < (60 * 60 * 24) ? "date/time" : "date";
+
+ stream.Printf("%s=%s timestamp=%" PRId64 " %s", label, str.data(),
+ *tp_duration, suffix);
+ }
+
+ return true;
+}
+
+} // namespace
+
+namespace lldb_private::formatters::chrono {
+
+#pragma region Calendar
+
+/// std::chrono::day
+bool DaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP day_sp = TryOne(valobj, "__d_", "_M_d", "_Day");
+ if (!day_sp)
+ return false;
+
+ stream << llvm::formatv("day={0}", day_sp->GetValueAsUnsigned(0));
+ return true;
+}
+
+/// std::chrono::month
+bool MonthSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
+ // uses C++17 it's not possible to use the ostream operator directly.
+ static const std::array<std::string_view, 12> months = {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"};
+
+ ValueObjectSP ptr_sp = TryOne(valobj, "__m_", "_M_m", "_Month");
+ if (!ptr_sp)
+ return false;
+
+ const unsigned month = ptr_sp->GetValueAsUnsigned(0);
+ if (month >= 1 && month <= 12)
+ stream << "month=" << months[month - 1];
+ else
+ stream << llvm::formatv("month={0}", month);
+
+ return true;
+}
+
+/// std::chrono::year
+bool YearSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP year_sp = TryOne(valobj, "__y_", "_M_y", "_Year");
+ if (!year_sp)
+ return false;
+
+ stream << llvm::formatv("year={0}", year_sp->GetValueAsSigned(0));
+ return true;
+}
+
+/// std::chrono::weekday
+bool WeekdaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
+ // uses C++17 it's not possible to use the ostream operator directly.
+ static const std::array<std::string_view, 7> weekdays = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"};
+
+ ValueObjectSP ptr_sp = TryOne(valobj, "__wd_", "_M_wd", "_Weekday");
+ if (!ptr_sp)
+ return false;
+
+ const unsigned weekday = ptr_sp->GetValueAsUnsigned(0);
+ if (weekday < 7)
+ stream << "weekday=" << weekdays[weekday];
+ else
+ stream.Printf("weekday=%u", weekday);
+
+ return true;
+}
+
+/// std::chrono::weekday_indexed
+bool WeekdayIndexedSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [weekday_sp, idx_sp] = TryStl<2>(valobj)
+ .Libcxx("__wd_", "__idx_")
+ .Libstdcxx("_M_wd", "_M_index")
+ .Msvc("_Weekday", "_Index")
+ .All();
+ if (!weekday_sp || !idx_sp)
+ return false;
+
+ stream << llvm::formatv("{0} index={1}", weekday_sp->GetSummaryAsCString(),
+ idx_sp->GetValueAsUnsigned(0));
+ return true;
+}
+
+/// std::chrono::weekday_last
+bool WeekdayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP weekday_sp = TryOne(valobj, "__wd_", "_M_wd", "_Weekday");
+ if (!weekday_sp)
+ return false;
+
+ stream << llvm::formatv("{0} index=last", weekday_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::month_day
+bool MonthDaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [month_sp, day_sp] = TryStl<2>(valobj)
+ .Libcxx("__m_", "__d_")
+ .Libstdcxx("_M_m", "_M_d")
+ .Msvc("_Month", "_Day")
+ .All();
+ if (!month_sp || !day_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1}", month_sp->GetSummaryAsCString(),
+ day_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::month_day_last
+bool MonthDayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP month_sp = TryOne(valobj, "__m_", "_M_m", "_Month");
+ if (!month_sp)
+ return false;
+
+ stream << llvm::formatv("{0} day=last", month_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::month_weekday
+bool MonthWeekdaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [month_sp, weekday_sp] = TryStl<2>(valobj)
+ .Libcxx("__m_", "__wdi_")
+ .Libstdcxx("_M_m", "_M_wdi")
+ .Msvc("_Month", "_Weekday_index")
+ .All();
+ if (!month_sp || !weekday_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1}", month_sp->GetSummaryAsCString(),
+ weekday_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::month_weekday_last
+bool MonthWeekdayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [month_sp, weekday_sp] = TryStl<2>(valobj)
+ .Libcxx("__m_", "__wdl_")
+ .Libstdcxx("_M_m", "_M_wdl")
+ .Msvc("_Month", "_Weekday_last")
+ .All();
+ if (!month_sp || !weekday_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1}", month_sp->GetSummaryAsCString(),
+ weekday_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::year_month
+bool YearMonthSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [year_sp, month_sp] = TryStl<2>(valobj)
+ .Libcxx("__y_", "__m_")
+ .Libstdcxx("_M_y", "_M_m")
+ .Msvc("_Year", "_Month")
+ .All();
+ if (!year_sp || !month_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1}", year_sp->GetSummaryAsCString(),
+ month_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::year_month_day
+bool YearMonthDaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [year_sp, month_sp, day_sp] = TryStl<3>(valobj)
+ .Libcxx("__y_", "__m_", "__d_")
+ .Libstdcxx("_M_y", "_M_m", "_M_d")
+ .Msvc("_Year", "_Month", "_Day")
+ .All();
+ if (!year_sp || !month_sp || !day_sp)
+ return false;
+ year_sp = year_sp->GetChildAtIndex(0);
+ month_sp = month_sp->GetChildAtIndex(0);
+ day_sp = day_sp->GetChildAtIndex(0);
+ if (!year_sp || !month_sp || !day_sp)
+ return false;
+
+ int64_t year = year_sp->GetValueAsSigned(0);
+ uint64_t month = month_sp->GetValueAsUnsigned(0);
+ uint64_t day = day_sp->GetValueAsUnsigned(0);
+
+ stream << "date=";
+ if (year < 0) {
+ stream << '-';
+ year = -year;
+ }
+ stream << llvm::formatv("{0,0+4}-{1,0+2}-{2,0+2}", year, month, day);
+ return true;
+}
+
+/// std::chrono::year_month_day_last
+bool YearMonthDayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [year_sp, month_sp] = TryStl<2>(valobj)
+ .Libcxx("__y_", "__mdl_")
+ .Libstdcxx("_M_y", "_M_mdl")
+ .Msvc("_Year", "_Month_day_last")
+ .All();
+ if (!year_sp || !month_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1}", year_sp->GetSummaryAsCString(),
+ month_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::year_month_weekday
+bool YearMonthWeekdaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [year_sp, month_sp, wdi_sp] =
+ TryStl<3>(valobj)
+ .Libcxx("__y_", "__m_", "__wdi_")
+ .Libstdcxx("_M_y", "_M_m", "_M_wdi")
+ .Msvc("_Year", "_Month", "_Weekday_index")
+ .All();
+ if (!year_sp || !month_sp || !wdi_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1} {2}", year_sp->GetSummaryAsCString(),
+ month_sp->GetSummaryAsCString(),
+ wdi_sp->GetSummaryAsCString());
+ return true;
+}
+
+/// std::chrono::year_month_weekday_last
+bool YearMonthWeekdayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ auto [year_sp, month_sp, wdl_sp] =
+ TryStl<3>(valobj)
+ .Libcxx("__y_", "__m_", "__wdl_")
+ .Libstdcxx("_M_y", "_M_m", "_M_wdl")
+ .Msvc("_Year", "_Month", "_Weekday_last")
+ .All();
+ if (!year_sp || !month_sp || !wdl_sp)
+ return false;
+
+ stream << llvm::formatv("{0} {1} {2}", year_sp->GetSummaryAsCString(),
+ month_sp->GetSummaryAsCString(),
+ wdl_sp->GetSummaryAsCString());
+ return true;
+}
+
+#pragma region Durations
+
+/// std::chrono::nanoseconds
+bool NanosecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "ns");
+}
+
+/// std::chrono::microseconds
+bool MicrosecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "µs");
+}
+
+/// std::chrono::milliseconds
+bool MillisecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "ms");
+}
+
+/// std::chrono::seconds
+bool SecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "s");
+}
+
+/// std::chrono::minutes
+bool MinutesSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "min");
+}
+
+/// std::chrono::hours
+bool HoursSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "h");
+}
+
+/// std::chrono::days
+bool DaysSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "days");
+}
+
+/// std::chrono::weeks
+bool WeeksSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "weeks");
+}
+
+/// std::chrono::years
+bool YearsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "years");
+}
+
+/// std::chrono::months
+bool MonthsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return ChronoDurationFormat(valobj, stream, "months");
+}
+
+#pragma region Timepoints
+
+/// std::chrono::time_point<system_clock, seconds>
+bool SysSecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return TimePointSummary(valobj, stream, /*to_sec=*/1, "%FT%H:%M:%SZ",
+ /*suffix=*/"s");
+}
+
+/// std::chrono::time_point<system_clock, days>
+bool SysDaysSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return TimePointSummary(valobj, stream, /*to_sec=*/60 * 60 * 24, "%FZ",
+ /*suffix=*/"days");
+}
+
+/// std::chrono::time_point<local_t, seconds>
+bool LocalSecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return TimePointSummary(valobj, stream, /*to_sec=*/1, "%FT%H:%M:%S",
+ /*suffix=*/"s");
+}
+
+/// std::chrono::time_point<local_t, days>
+bool LocalDaysSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ return TimePointSummary(valobj, stream, /*to_sec=*/60 * 60 * 24, "%F",
+ /*suffix=*/"days");
+}
+
+} // namespace lldb_private::formatters::chrono
diff --git a/lldb/source/Plugins/Language/CPlusPlus/Chrono.h b/lldb/source/Plugins/Language/CPlusPlus/Chrono.h
new file mode 100644
index 0000000000000..d38bcfb6eec59
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/Chrono.h
@@ -0,0 +1,142 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CHRONO_H
+#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CHRONO_H
+
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/ValueObject/ValueObject.h"
+
+namespace lldb_private::formatters::chrono {
+
+#pragma region Calendar
+
+/// std::chrono::day
+bool DaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::month
+bool MonthSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::year
+bool YearSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::weekday
+bool WeekdaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::weekday_indexed
+bool WeekdayIndexedSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::weekday_last
+bool WeekdayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::month_day
+bool MonthDaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::month_day_last
+bool MonthDayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::month_weekday
+bool MonthWeekdaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::month_weekday_last
+bool MonthWeekdayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::year_month
+bool YearMonthSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::year_month_day
+bool YearMonthDaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::year_month_day_last
+bool YearMonthDayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::year_month_weekday
+bool YearMonthWeekdaySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::year_month_weekday_last
+bool YearMonthWeekdayLastSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+#pragma region Durations
+
+/// std::chrono::nanoseconds
+bool NanosecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::microseconds
+bool MicrosecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::milliseconds
+bool MillisecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::seconds
+bool SecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::minutes
+bool MinutesSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::hours
+bool HoursSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::days
+bool DaysSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::weeks
+bool WeeksSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::years
+bool YearsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::months
+bool MonthsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+#pragma region Timepoints
+
+/// std::chrono::time_point<system_clock, seconds>
+bool SysSecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::time_point<system_clock, days>
+bool SysDaysSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::time_point<local_t, seconds>
+bool LocalSecondsSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+/// std::chrono::time_point<local_t, days>
+bool LocalDaysSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
+} // namespace lldb_private::formatters::chrono
+
+#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CHRONO_H
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 0181910c12641..66063db782af9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -795,191 +795,3 @@ bool lldb_private::formatters::LibcxxWStringViewSummaryProvider(
}
return false;
}
-
-static bool
-LibcxxChronoTimePointSecondsSummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options,
- const char *fmt) {
- ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
- if (!ptr_sp)
- return false;
- ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
- if (!ptr_sp)
- return false;
-
-#ifndef _WIN32
- // The date time in the chrono library is valid in the range
- // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a
- // larger range, the function strftime is not able to format the entire range
- // of time_t. The exact point has not been investigated; it's limited to
- // chrono's range.
- const std::time_t chrono_timestamp_min =
- -1'096'193'779'200; // -32767-01-01T00:00:00Z
- const std::time_t chrono_timestamp_max =
- 971'890'963'199; // 32767-12-31T23:59:59Z
-#else
- const std::time_t chrono_timestamp_min = -43'200; // 1969-12-31T12:00:00Z
- const std::time_t chrono_timestamp_max =
- 32'536'850'399; // 3001-01-19T21:59:59
-#endif
-
- const std::time_t seconds = ptr_sp->GetValueAsSigned(0);
- if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max)
- stream.Printf("timestamp=%" PRId64 " s", static_cast<int64_t>(seconds));
- else {
- std::array<char, 128> str;
- std::size_t size =
- std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
- if (size == 0)
- return false;
-
- stream.Printf("date/time=%s timestamp=%" PRId64 " s", str.data(),
- static_cast<int64_t>(seconds));
- }
-
- return true;
-}
-
-bool lldb_private::formatters::LibcxxChronoSysSecondsSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
- "%FT%H:%M:%SZ");
-}
-
-bool lldb_private::formatters::LibcxxChronoLocalSecondsSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
- "%FT%H:%M:%S");
-}
-
-static bool
-LibcxxChronoTimepointDaysSummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options,
- const char *fmt) {
- ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
- if (!ptr_sp)
- return false;
- ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
- if (!ptr_sp)
- return false;
-
-#ifndef _WIN32
- // The date time in the chrono library is valid in the range
- // [-32767-01-01Z, 32767-12-31Z]. A 32-bit time_t has a larger range, the
- // function strftime is not able to format the entire range of time_t. The
- // exact point has not been investigated; it's limited to chrono's range.
- const int chrono_timestamp_min = -12'687'428; // -32767-01-01Z
- const int chrono_timestamp_max = 11'248'737; // 32767-12-31Z
-#else
- const int chrono_timestamp_min = 0; // 1970-01-01Z
- const int chrono_timestamp_max = 376'583; // 3001-01-19Z
-#endif
-
- const int days = ptr_sp->GetValueAsSigned(0);
- if (days < chrono_timestamp_min || days > chrono_timestamp_max)
- stream.Printf("timestamp=%d days", days);
-
- else {
- const std::time_t seconds = std::time_t(86400) * days;
-
- std::array<char, 128> str;
- std::size_t size =
- std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
- if (size == 0)
- return false;
-
- stream.Printf("date=%s timestamp=%d days", str.data(), days);
- }
-
- return true;
-}
-
-bool lldb_private::formatters::LibcxxChronoSysDaysSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
- "%FZ");
-}
-
-bool lldb_private::formatters::LibcxxChronoLocalDaysSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
- "%F");
-}
-
-bool lldb_private::formatters::LibcxxChronoMonthSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
- // uses C++17 it's not possible to use the ostream operator directly.
- static const std::array<std::string_view, 12> months = {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"};
-
- ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__m_");
- if (!ptr_sp)
- return false;
-
- const unsigned month = ptr_sp->GetValueAsUnsigned(0);
- if (month >= 1 && month <= 12)
- stream << "month=" << months[month - 1];
- else
- stream.Printf("month=%u", month);
-
- return true;
-}
-
-bool lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
- // uses C++17 it's not possible to use the ostream operator directly.
- static const std::array<std::string_view, 7> weekdays = {
- "Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday"};
-
- ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__wd_");
- if (!ptr_sp)
- return false;
-
- const unsigned weekday = ptr_sp->GetValueAsUnsigned(0);
- if (weekday < 7)
- stream << "weekday=" << weekdays[weekday];
- else
- stream.Printf("weekday=%u", weekday);
-
- return true;
-}
-
-bool lldb_private::formatters::LibcxxChronoYearMonthDaySummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__y_");
- if (!ptr_sp)
- return false;
- ptr_sp = ptr_sp->GetChildMemberWithName("__y_");
- if (!ptr_sp)
- return false;
- int year = ptr_sp->GetValueAsSigned(0);
-
- ptr_sp = valobj.GetChildMemberWithName("__m_");
- if (!ptr_sp)
- return false;
- ptr_sp = ptr_sp->GetChildMemberWithName("__m_");
- if (!ptr_sp)
- return false;
- const unsigned month = ptr_sp->GetValueAsUnsigned(0);
-
- ptr_sp = valobj.GetChildMemberWithName("__d_");
- if (!ptr_sp)
- return false;
- ptr_sp = ptr_sp->GetChildMemberWithName("__d_");
- if (!ptr_sp)
- return false;
- const unsigned day = ptr_sp->GetValueAsUnsigned(0);
-
- stream << "date=";
- if (year < 0) {
- stream << '-';
- year = -year;
- }
- stream.Printf("%04d-%02u-%02u", year, month, day);
-
- return true;
-}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index d9b3f3a694afc..59862ad848901 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -227,34 +227,6 @@ SyntheticChildrenFrontEnd *
LibcxxStdRangesRefViewSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
-bool LibcxxChronoSysSecondsSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::sys_seconds
-
-bool LibcxxChronoSysDaysSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::sys_days
-
-bool LibcxxChronoLocalSecondsSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::local_seconds
-
-bool LibcxxChronoLocalDaysSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::local_days
-
-bool LibcxxChronoMonthSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::month
-
-bool LibcxxChronoWeekdaySummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::weekday
-
-bool LibcxxChronoYearMonthDaySummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::chrono::year_month_day
-
} // namespace formatters
} // namespace lldb_private
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/chrono/TestDataFormatterStdChrono.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/chrono/TestDataFormatterStdChrono.py
index 762698a8e8a13..55b280ffa7b52 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/chrono/TestDataFormatterStdChrono.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/chrono/TestDataFormatterStdChrono.py
@@ -10,6 +10,7 @@
class StdChronoDataFormatterTestCase(TestBase):
SHARED_BUILD_TESTCASE = False
+ TEST_WITH_PDB_DEBUG_INFO = True
def do_test(self):
"""Test that that file and class static variables display correctly."""
@@ -437,3 +438,13 @@ def do_test(self):
def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test()
+
+ @add_test_categories(["libstdcxx"])
+ def test_libstdcpp(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ self.build()
+ self.do_test()
More information about the lldb-commits
mailing list