diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 21c73e6361904e..f0fe6c9e06d9d4 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1032,6 +1032,31 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { 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 " + "> >$", + 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 " + "> >$", + eTypeOptionHideChildren | eTypeOptionHideValue | + eTypeOptionCascade, + true); + // Chrono calendar types cpp_category_sp->AddTypeSummary( diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index d232a38adc029a..042e2262696998 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -1073,18 +1073,79 @@ bool lldb_private::formatters::LibcxxWStringViewSummaryProvider( bool success; ValueObjectSP dataobj; size_t size; - std::tie( success, dataobj, size ) = LibcxxExtractStringViewData(valobj); + std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj); if (!success) { stream << "Summary Unavailable"; return true; } - return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options, dataobj, size); } +bool lldb_private::formatters::LibcxxChronoSysSecondsSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { + ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_"); + if (!ptr_sp) + return false; + ptr_sp = ptr_sp->GetChildMemberWithName("__rep_"); + if (!ptr_sp) + return false; + + // 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 + + const std::time_t seconds = ptr_sp->GetValueAsSigned(0); + if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max) + stream.Printf("timestamp=%ld s", seconds); + else { + std::array str; + std::strftime(str.data(), str.size(), "%FT%H:%M:%SZ", gmtime(&seconds)); + stream.Printf("date/time=%s timestamp=%ld s", str.data(), seconds); + } + + return true; +} + +bool lldb_private::formatters::LibcxxChronoSysDaysSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { + ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_"); + if (!ptr_sp) + return false; + ptr_sp = ptr_sp->GetChildMemberWithName("__rep_"); + if (!ptr_sp) + return false; + + // 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 + + 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 str; + std::strftime(str.data(), str.size(), "%FZ", gmtime(&seconds)); + stream.Printf("date=%s timestamp=%d days", str.data(), days); + } + + return true; +} + 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 diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index 532d185b18543f..72da6b2426efec 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -261,6 +261,14 @@ 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 LibcxxChronoMonthSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // libc++ std::chrono::month diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py index d4bc140015fbb7..67372572dc4464 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py @@ -32,6 +32,106 @@ def test_with_run_command(self): self.expect("frame variable m", substrs=["m = 4321 months"]) self.expect("frame variable y", substrs=["y = 321 years"]) + self.expect( + "frame variable ss_tp", + substrs=["ss_tp = date/time=1970-01-01T00:00:00Z timestamp=0 s"], + ) + self.expect( + "frame variable ss_tp_d", + substrs=["ss_tp_d = date/time=1970-01-01T00:00:00Z timestamp=0 s"], + ) + self.expect( + "frame variable ss_tp_d_r", + substrs=["ss_tp_d_r = date/time=1970-01-01T00:00:00Z timestamp=0 s"], + ) + self.expect( + "frame variable ss_tp_d_r2", + substrs=["ss_tp_d_r2 = date/time=1970-01-01T00:00:00Z timestamp=0 s"], + ) + + self.expect( + "frame variable ss_0", + substrs=["ss_0 = date/time=1970-01-01T00:00:00Z timestamp=0 s"], + ) + + self.expect( + "frame variable ss_neg_date_time", + substrs=[ + "ss_neg_date_time = date/time=-32767-01-01T00:00:00Z timestamp=-1096193779200 s" + ], + ) + self.expect( + "frame variable ss_neg_seconds", + substrs=["ss_neg_seconds = timestamp=-1096193779201 s"], + ) + + self.expect( + "frame variable ss_pos_date_time", + substrs=[ + "ss_pos_date_time = date/time=32767-12-31T23:59:59Z timestamp=971890963199 s" + ], + ) + self.expect( + "frame variable ss_pos_seconds", + substrs=["ss_pos_seconds = timestamp=971890963200 s"], + ) + + self.expect( + "frame variable ss_min", + substrs=["ss_min = timestamp=-9223372036854775808 s"], + ) + self.expect( + "frame variable ss_max", + substrs=["ss_max = timestamp=9223372036854775807 s"], + ) + + self.expect( + "frame variable sd_tp", + substrs=["sd_tp = date=1970-01-01Z timestamp=0 days"], + ) + self.expect( + "frame variable sd_tp_d_r", + substrs=["sd_tp_d_r = date=1970-01-01Z timestamp=0 days"], + ) + self.expect( + "frame variable sd_tp_d_r2", + substrs=["sd_tp_d_r2 = date=1970-01-01Z timestamp=0 days"], + ) + + self.expect( + "frame variable sd_0", substrs=["sd_0 = date=1970-01-01Z timestamp=0 days"] + ) + self.expect( + "frame variable sd_neg_date", + substrs=["sd_neg_date = date=-32767-01-01Z timestamp=-12687428 days"], + ) + self.expect( + "frame variable sd_neg_days", + substrs=["sd_neg_days = timestamp=-12687429 days"], + ) + + self.expect( + "frame variable sd_pos_date", + substrs=["sd_pos_date = date=32767-12-31Z timestamp=11248737 days"], + ) + self.expect( + "frame variable sd_pos_days", + substrs=["sd_pos_days = timestamp=11248738 days"], + ) + + self.expect( + "frame variable sd_min", + substrs=["sd_min = timestamp=-2147483648 days"], + ) + self.expect( + "frame variable sd_max", + substrs=["sd_max = timestamp=2147483647 days"], + ) + + # self.expect("frame variable sd_min", substrs=["sd_min = date=1970-01-01Z timestamp=0 days"]) + # self.expect("frame variable sd_0", substrs=["sd_0 = date=1970-01-01Z timestamp=0 days"]) + # self.expect("frame variable XXXtp_d_0", substrs=["XXXtp_d_0 = date=1970-01-01Z timestamp=0 days"]) + self.expect("frame variable d_0", substrs=["d_0 = day=0"]) self.expect("frame variable d_1", substrs=["d_1 = day=1"]) self.expect("frame variable d_31", substrs=["d_31 = day=31"]) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/main.cpp index 57215aaf343f64..315c88a787d823 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/main.cpp @@ -15,6 +15,58 @@ int main() { std::chrono::months m{4321}; std::chrono::years y{321}; + // sys_seconds aliasses + std::chrono::time_point + ss_tp{std::chrono::seconds{0}}; + std::chrono::time_point> + ss_tp_d{std::chrono::seconds{0}}; + std::chrono::time_point>> + ss_tp_d_r{std::chrono::seconds{0}}; + std::chrono::time_point>> + ss_tp_d_r2{std::chrono::seconds{0}}; + + // sys_seconds + std::chrono::sys_seconds ss_0{std::chrono::seconds{0}}; + std::chrono::sys_seconds ss_neg_date_time{ + std::chrono::seconds{-1'096'193'779'200}}; + std::chrono::sys_seconds ss_neg_seconds{ + std::chrono::seconds{-1'096'193'779'201}}; + std::chrono::sys_seconds ss_pos_date_time{ + std::chrono::seconds{971'890'963'199}}; + std::chrono::sys_seconds ss_pos_seconds{ + std::chrono::seconds{971'890'963'200}}; + std::chrono::sys_seconds ss_min{ + std::chrono::seconds{std::numeric_limits::min()}}; + std::chrono::sys_seconds ss_max{ + std::chrono::seconds{std::numeric_limits::max()}}; + + // sys_days aliasses + std::chrono::time_point sd_tp{ + std::chrono::days{0}}; + std::chrono::time_point>> + sd_tp_d_r{std::chrono::days{0}}; + std::chrono::time_point>> + sd_tp_d_r2{std::chrono::days{0}}; + + // sys_days + std::chrono::sys_days sd_0{std::chrono::days{0}}; + + std::chrono::sys_days sd_neg_date{std::chrono::days{-12'687'428}}; + std::chrono::sys_days sd_neg_days{std::chrono::days{-12'687'429}}; + + std::chrono::sys_days sd_pos_date{std::chrono::days{11'248'737}}; + std::chrono::sys_days sd_pos_days{std::chrono::days{11'248'738}}; + + std::chrono::sys_days sd_min{ + std::chrono::days{std::numeric_limits::min()}}; + std::chrono::sys_days sd_max{ + std::chrono::days{std::numeric_limits::max()}}; + std::chrono::day d_0{0}; std::chrono::day d_1{1}; std::chrono::day d_31{31};