Skip to content

[lldb][libc++] Adds system_clock data formatters. #78609

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<long long, "
"std::__[[:alnum:]]+::ratio<1, 1> "
"> >$",
eTypeOptionHideChildren | eTypeOptionHideValue |
eTypeOptionCascade,
true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoSysDaysSummaryProvider,
"libc++ std::chrono::sys_seconds summary provider",
"^std::__[[:alnum:]]+::chrono::time_point<"
"std::__[[:alnum:]]+::chrono::system_clock, "
"std::__[[:alnum:]]+::chrono::duration<int, "
"std::__[[:alnum:]]+::ratio<86400, 1> "
"> >$",
eTypeOptionHideChildren | eTypeOptionHideValue |
eTypeOptionCascade,
true);

// Chrono calendar types

cpp_category_sp->AddTypeSummary(
Expand Down
73 changes: 71 additions & 2 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1073,18 +1073,87 @@ 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<char, 128> str;
std::size_t size =
std::strftime(str.data(), str.size(), "%FT%H:%M:%SZ", gmtime(&seconds));
if (size == 0)
return false;

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<char, 128> str;
std::size_t size =
std::strftime(str.data(), str.size(), "%FZ", gmtime(&seconds));
if (size == 0)
return false;

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
Expand Down
8 changes: 8 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,102 @@ 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 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"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,58 @@ int main() {
std::chrono::months m{4321};
std::chrono::years y{321};

// sys_seconds aliasses
std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>
ss_tp{std::chrono::seconds{0}};
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<long long>>
ss_tp_d{std::chrono::seconds{0}};
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<long long, std::ratio<1>>>
ss_tp_d_r{std::chrono::seconds{0}};
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<long long, std::ratio<1>>>
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<long long>::min()}};
std::chrono::sys_seconds ss_max{
std::chrono::seconds{std::numeric_limits<long long>::max()}};

// sys_days aliasses
std::chrono::time_point<std::chrono::system_clock, std::chrono::days> sd_tp{
std::chrono::days{0}};
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<int, std::ratio<86400>>>
sd_tp_d_r{std::chrono::days{0}};
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<int, std::ratio<86400, 1>>>
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<int>::min()}};
std::chrono::sys_days sd_max{
std::chrono::days{std::numeric_limits<int>::max()}};

std::chrono::day d_0{0};
std::chrono::day d_1{1};
std::chrono::day d_31{31};
Expand Down