[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