This is an archive of the discontinued LLVM Phabricator instance.

[libc++][chrono] Implements formatter day.
ClosedPublic

Authored by Mordante on Jun 25 2022, 2:39 AM.

Details

Reviewers
ldionne
vitaut
Group Reviewers
Restricted Project
Commits
rGe5d2d3eafbb3: [libc++][chrono] Implements formatter day.
Summary

This implements the enabled specializaton
template<class charT> struct formatter<chrono::day, charT>;

and
template<class charT, class traits>

basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>& os, const day& d);

Implements:

  • LWG 3241 chrono-spec grammar ambiguity in §[time.format]

Partially implements:

  • P1361 Integration of chrono with text formatting

Diff Detail

Event Timeline

Mordante created this revision.Jun 25 2022, 2:39 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 25 2022, 2:39 AM
Herald added a subscriber: mgorny. · View Herald Transcript
Mordante requested review of this revision.Jun 25 2022, 2:39 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 25 2022, 2:39 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Mordante updated this revision to Diff 439976.Jun 25 2022, 5:05 AM

Fixes some CI issue.
Note temporary disable quite some CI runs, since I expect several non-Linux systems to still fail.

Mordante updated this revision to Diff 439977.Jun 25 2022, 5:17 AM

Attempt to fix buildkite

Mordante updated this revision to Diff 439980.Jun 25 2022, 5:54 AM

More CI fixes.

Mordante updated this revision to Diff 439987.Jun 25 2022, 7:20 AM

More CI fixes.

Mordante updated this revision to Diff 439988.Jun 25 2022, 7:50 AM

More CI fixes and disables more green CIs

Mordante updated this revision to Diff 439990.Jun 25 2022, 8:25 AM

With the CI green, reenable all CI jobs.

Mordante added subscribers: vitaut, ldionne.
Mordante added inline comments.
libcxx/docs/Status/Cxx20Issues.csv
170

@ldionne, @vitaut this is the first chrono formatter. A rough draft with more formatters is available in D126592.

This patch adds the basic framework and one formatter specialization to keep the review manageable. I will chop the large patch in smaller reviewable patches.

Note there's an issue with Windows somehow the values for invalid days are odd and the CI doesn't provide good feedback. I'll test to see whether I can run the Windows test locally otherwise I'll ask assistance of people with access to Windows.

libcxx/include/__chrono/formatter.h
105

Note the number of "special cases" will grow in future patches. For example '%S' needs to show subsecond resolution. '%Y' requires 4 digits, which C doesn't do.

141

Basically the mentioned paper gives direct access to the buffer's data with a view. That avoids the need for the temporary string to create a view.

libcxx/include/__chrono/parser_std_format_spec.h
51

Note most of these __flags aren't used and the functions below also not yet, except for the unit tests. There have been used in the large patch.

ldionne added inline comments.Jun 28 2022, 9:29 AM
libcxx/include/__chrono/formatter.h
16

I think it's fine to guard the header here, but I would remove the comment, which seems a bit redundant.

The usual tradition in libc++ is to guard the header itself (as done here) so that the header can always be included (although it might be empty). Note that this isn't really done consistently everywhere, for example _LIBCPP_HAS_NO_LOCALIZATION is usually checked before including the header, since the header will #error out if included.

So yeah, bottom line: you can keep as-is, and I guess we don't have a ton of consistency here in the library.

28–32

Instead, I think our validation for #pragma GCC system_header should be less strict.

44
49
54

This seems like a leftover.

61–62

Suggestion:

  .tm_sec = 0
, .tm_min = 0
, .tm_hour = 0
...
#ifdef __GLIBC__
, .tm_gmtoff = 0
, .tm_zone = "UTC"
#endif

IDK if clang-format will handle that gracefully.

87

ADL

libcxx/include/__chrono/statically_widen.h
34

This should be called _LIBCPP_STATICALLY_WIDEN. We don't define macros that are not prefix with _LIBCPP (except _NOEXCEPT and _NOEXCEPT_, and IMO those were mistakes if only for consistency).

Also, we shouldn't be using _CharT in this macro without taking it as an argument. This creates a really weird dependency that the macro can only be used within a template with a suitably named template parameter.

libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp
86

Why are we checking 255 if it's not a valid input? (and hence has these various weird results on AIX and other platforms)

Mordante marked 8 inline comments as done.Jul 3 2022, 2:04 AM
Mordante added inline comments.
libcxx/include/__chrono/formatter.h
16

I think moving has another advantage. All other preprocessor are no longer in a global one, thus decreasing their indention level.
(This avoid reformatting when the guard is removed.)

28–32

Agreed I'll look at that in a separate commit.

61–62

I haven't found a clang-format option to do this. Only for the constructor. But I agree it would be great when clang-format would have an option to do this.

libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp
86

As discussed in our private conversation. 255 is the minimum of the maximum supported value for a day. I'm not happy with how this works in practice and want to look at alternative solutions. (I will most likely file an LWG issue or write a paper.)

For now I leave it as is since I want to look closer are when exactly happens on Windows; however I want to have a better solution before landing this.

Mordante updated this revision to Diff 441929.Jul 3 2022, 2:04 AM
Mordante marked 3 inline comments as done.

Addresses most review comments.

philnik added a subscriber: philnik.Jul 3 2022, 3:31 AM
philnik added inline comments.
libcxx/include/__chrono/formatter.h
61–62

What's wrong with just using a trailing comma?

Mordante marked an inline comment as done.Jul 3 2022, 5:13 AM
Mordante added inline comments.
libcxx/include/__chrono/formatter.h
61–62

In general nothing, but line 62 now has a single comma. It would be really nice of clang-format could detect these cases an used leading commas instead. IMO that would be nice to have, but I've no objection against the single comma.

philnik added inline comments.Jul 3 2022, 5:28 AM
libcxx/include/__chrono/formatter.h
61–62

I meant "Why not put the comma at the end of line 60?"
Another thought: Why do you explicitly initialize all the struct members? They get value-initialized anyways if you omit them. That would leave you with just

tm __result {
#ifdef __GLIBC__
  .tm_zone = "UTC",
#endif
};
Mordante updated this revision to Diff 441949.Jul 3 2022, 6:48 AM
Mordante marked an inline comment as done.

Attempt to fix CI and determine Windows status.

Mordante updated this revision to Diff 441954.Jul 3 2022, 8:02 AM

Fix modular build.

Mordante updated this revision to Diff 441967.Jul 3 2022, 10:47 AM

Only build Windows to validate the output.

Mordante updated this revision to Diff 441969.Jul 3 2022, 11:16 AM

Some win32 fixes.

Mordante updated this revision to Diff 441970.Jul 3 2022, 11:59 AM

More fixes.

Mordante planned changes to this revision.Jul 3 2022, 12:23 PM

Needs additional work to get a good result for invalid values.

Mordante updated this revision to Diff 445230.Jul 16 2022, 6:03 AM

Use alternative approach for formatting invalid day values.

vitaut added inline comments.Jul 16 2022, 8:11 AM
libcxx/include/__chrono/formatter.h
37

module -> modulo

41–42

Submit an LWG issue to clarify this?

52

You could make this more robust and shorter:

tm __result = tm();
#ifdef __GLIBC__
__result.tm_zone = "UTC";
#endif
80

Is this expensive? Maybe extract a facet lazily since it's often unused.

117–131

Not necessarily in the current diff but you might want to refactor this to only use iostreams for localized formatting. Nonlocalized can be implemented much more efficiently.

libcxx/include/__chrono/ostream.h
36–40

Could you give an example of a format call illustrating the problem on AIX and Windows?

libcxx/include/__chrono/parser_std_format_spec.h
86

a -> an

Thanks for the review! I'll have a look at your other review comments after I have the results of the CI run.

libcxx/include/__chrono/formatter.h
41–42

At the moment I'm collecting the issues I've found. When the number is low I'll file LWG issues, but otherwise I probably write a paper with all issues.

80

I haven't benchmarked it.

Interesting, I expected it to be used often since most of the formatting can be done by __facet.put. That saves me implementing all locale specific behaviour.

One optimization I've seen in {fmt} is that you handle the C locale as a special case and have written your own output routines for that case. I have that on my todo list.

117–131

Agreed. For now I've been mainly looking at getting things to work. But optimizing it most definitely on my todo list.

libcxx/include/__chrono/ostream.h
36–40

These are examples of the previous iteration of this patch.
Windows check.template operator()<"{:*^23}">(SV("*** is not a valid day*"), 0d); (the same for other invalid days.)
AIX check.template operator()<fmt>(SV("%d='55'\t%Od='55'\t%e='55'\t%Oe='55'\n"), 255d);

Mordante updated this revision to Diff 445344.Jul 17 2022, 12:37 PM

Attempts to fix the CI.

Mordante marked 5 inline comments as done.Jul 17 2022, 10:59 PM
Mordante added inline comments.
libcxx/include/__chrono/formatter.h
61–62

@vitaut suggested something similar. I like this approach better, modulo the trailing comma.

Mordante updated this revision to Diff 445390.Jul 17 2022, 11:00 PM
Mordante marked an inline comment as done.

Addresses review comments and attempts to fix the CI.

Mordante updated this revision to Diff 445529.Jul 18 2022, 8:59 AM

Attempt to fix CI.

ldionne added inline comments.Jul 26 2022, 9:48 AM
libcxx/include/__chrono/formatter.h
52

I think it might be important to use = tm() to get proper zero initialization, otherwise some members might be left uninitialized.

ldionne requested changes to this revision.Aug 9 2022, 9:38 AM
ldionne added inline comments.
libcxx/docs/Status/Cxx20Issues.csv
178
libcxx/include/__chrono/formatter.h
51

I don't think this should be in formatter.h or in the __formatter namespace. This seems generally useful, don't you think? I might suggest something like __chrono/convert_to_tm.h to mirror convert_to_timespec.h.

libcxx/include/__chrono/statically_widen.h
14
36

Equivalent since _LIBCPP_STATICALLY_WIDEN should only be used in our namespace, but still more idiomatic since this is a macro.

46

Ditto.

libcxx/include/module.modulemap.in
497

This shouldn't be here.

511

Not needed.

515

Not needed.

libcxx/test/libcxx/utilities/format/format.formatter/format.formatter.spec/formattable.compile.pass.cpp
144

I would prefer instead:

// The chrono formatters require localization support because {XXXXXXXX}
#ifndef TEST_HAS_NO_LOCALIZATION
  assert_is_formattable<std::chrono::day, CharT>();
#endif

We don't need to test that it's not formattable when localization is disabled.

libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp
35–37

Leftover?

90–91

Leftover?

libcxx/test/std/time/time.syn/formatter_tests.h
8

Missing header guard.

61–67
89–93

I would suggest putting that above so it doesn't clutter the body of the function so much. You could use something like using Context = ..... The same comment applies above too.

104–105
libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp
119

Same comment as above for TEST_HAS_NO_LOCALIZATION.

This revision now requires changes to proceed.Aug 9 2022, 9:38 AM
Mordante updated this revision to Diff 451231.Aug 9 2022, 12:05 PM
Mordante marked 16 inline comments as done.
  • Rebased
  • Addresses most review comments
  • Qualify several calls
  • Comment out some transitive includes that caused include cycles
Mordante planned changes to this revision.Aug 9 2022, 12:05 PM
Mordante updated this revision to Diff 451474.Aug 10 2022, 8:04 AM

Adds work-around to test CI.

Mordante updated this revision to Diff 451552.Aug 10 2022, 10:46 AM

Attempts to fix Windows build.
Adds convert_to_tm private header.

Mordante updated this revision to Diff 452413.Aug 13 2022, 5:00 AM

Fixes CI.

Mordante updated this revision to Diff 452491.Aug 14 2022, 1:05 AM

Attempts to fix CI.

Mordante updated this revision to Diff 452538.Aug 14 2022, 10:22 AM

Tests failing CI.

Mordante updated this revision to Diff 452696.Aug 15 2022, 8:55 AM

Attempt to fix the CI.

Mordante updated this revision to Diff 452727.Aug 15 2022, 10:14 AM

Remove more parts of the experimental library.

Mordante updated this revision to Diff 452756.Aug 15 2022, 11:41 AM

Another attempt to fix the CI.

Notes from live review:

  1. Let's move transitive includes to the end of each file to break cycles
  2. Let's guard transitive includes on standard versions

Also, please update this to its final form and we can take a look at the Windows DLL errors.

Mordante updated this revision to Diff 453056.Aug 16 2022, 10:01 AM

Restore CI and try to fix circular dependencies.

Mordante updated this revision to Diff 453074.Aug 16 2022, 11:02 AM

Disable a test and test CI

Mordante added inline comments.Aug 25 2022, 8:51 AM
libcxx/include/chrono
700

As tested in D132284.

704

The header can be unconditional again.

Mordante updated this revision to Diff 457342.Sep 1 2022, 11:59 AM

Rebased and integrated all upstream changes.

Mordante updated this revision to Diff 457607.Sep 2 2022, 8:31 AM

Attempts to fix CI.

Mordante updated this revision to Diff 457787.Sep 3 2022, 5:58 AM

Rebased and some final polishing.

ldionne accepted this revision.Sep 6 2022, 8:48 AM
ldionne added inline comments.
libcxx/include/chrono
699

Is this comment still required? I think it is no longer needed since we inlined the destructor of format_error to workaround Windows DLL issues.

This revision is now accepted and ready to land.Sep 6 2022, 8:48 AM
Mordante marked 3 inline comments as done.Sep 7 2022, 9:43 AM
Mordante added inline comments.
libcxx/include/chrono
699

No it's not, removed it.

This revision was automatically updated to reflect the committed changes.
Mordante marked an inline comment as done.