On Thu, Mar 20, 2025 at 5:29 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> On Thu, 20 Mar 2025 at 16:16, Jonathan Wakely <jwak...@redhat.com> wrote:
> >
> > When using std::time_put to format a chrono value, we should imbue the
> > formatting locale into the stream. This ensures that when
> > std::time_put::do_put uses a ctype or __timepunct facet from the locale,
> > it gets the correct facets.
> >
> > libstdc++-v3/ChangeLog:
> >
> >         * include/bits/chrono_io.h (__formatter_chrono::_M_locale_fmt):
> >         Imbue locale into ostringstream.
> >         * testsuite/std/time/format/localized.cc: Check that correct
> >         locale is used for call to time_put::put.
> > ---
> >
> > Now with a test that shows the bug independent of the PR117214 patches
> > to use std::time_put for %c formats.
> >
> > Tested x86_64-linux.
> >
> >  libstdc++-v3/include/bits/chrono_io.h         |  1 +
> >  .../testsuite/std/time/format/localized.cc    | 30 +++++++++++++++++++
> >  2 files changed, 31 insertions(+)
> >
> > diff --git a/libstdc++-v3/include/bits/chrono_io.h
> b/libstdc++-v3/include/bits/chrono_io.h
> > index c16b555df29..55ebd4ee061 100644
> > --- a/libstdc++-v3/include/bits/chrono_io.h
> > +++ b/libstdc++-v3/include/bits/chrono_io.h
> > @@ -1697,6 +1697,7 @@ namespace __format
> >                       char __fmt, char __mod) const
> >         {
> >           basic_ostringstream<_CharT> __os;
> > +         __os.imbue(__loc);
> >           const auto& __tp = use_facet<time_put<_CharT>>(__loc);
> >           __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
> >           if (__os)
> > diff --git a/libstdc++-v3/testsuite/std/time/format/localized.cc
> b/libstdc++-v3/testsuite/std/time/format/localized.cc
> > index 393d0d200e4..437a4a011b2 100644
> > --- a/libstdc++-v3/testsuite/std/time/format/localized.cc
> > +++ b/libstdc++-v3/testsuite/std/time/format/localized.cc
> > @@ -13,6 +13,7 @@
> >
> >  #include <chrono>
> >  #include <format>
> > +#include <locale>
> >  #include <stdio.h>
> >  #include <testsuite_hooks.h>
> >
> > @@ -81,6 +82,35 @@ test_en()
> >      }
> >  }
> >
> > +void
> > +test_locale_imbued()
> > +{
> > +  // Custom time_put facet which returns %b string for %Om
> > +  struct TimePut : std::time_put<char>
> > +  {
> > +    iter_type
> > +    do_put(iter_type out, std::ios_base& io, char_type fill, const tm*
> t,
> > +          char format, char modifier) const override
> > +    {
> > +      if (format == 'm' && modifier == 'O')
> > +       format = 'b';
> > +      return std::time_put<char>::do_put(out, io, fill, t, format, 0);
> > +    }
> > +  };
> > +
> > +  auto m = std::chrono::March;
> > +
> > +  std::locale fr(ISO_8859(1,fr_FR));
> > +  std::locale fr2(fr, new TimePut);
> > +  auto s1 = std::format(fr2, "{:L%Om}", m);
> > +  VERIFY( s1 == std::format(fr, "{:L}", m) );
> > +
> > +  std::locale es(ISO_8859(1,es_ES));
> > +  std::locale es2(es, new TimePut);
> > +  auto s2 = std::format(es2, "{:L%Om}", m);
> > +  VERIFY( s2 == std::format(es, "{:L}", m) );
> > +}
> > +
> >  int main()
> >  {
> >    test_ru();
>
> It would help if I added the new test_locale_imbued() function to main
> so that it actually runs.
>
LGTM with that addition.

>
> Luckily it passes when I do that.
>
>

Reply via email to