LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 45739 - Fix failing locale tests on Apple platforms with the RU locale
Summary: Fix failing locale tests on Apple platforms with the RU locale
Status: CONFIRMED
Alias: None
Product: libc++
Classification: Unclassified
Component: All Bugs (show other bugs)
Version: unspecified
Hardware: PC All
: P enhancement
Assignee: Louis Dionne
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-04-29 09:39 PDT by Louis Dionne
Modified: 2020-11-10 07:52 PST (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Louis Dionne 2020-04-29 09:39:55 PDT
The following tests are failing on Apple platforms:

    test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp
    test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp

We should figure out why and fix them.
Comment 1 Louis Dionne 2020-04-29 09:42:01 PDT
Here's a reproducer for one of these failing tests. I suspect they are all the same failure under the hood:

$ clang++ repro.cpp -g -std=c++2a -nostdinc++ -I libcxx/include -isysroot $(xcrun --show-sdk-path) -I libcxx/test/support -L build/lib -nostdlib++ -lc++ -Wl,-rpath,$PWD/build/lib -o a.out && ./a.out

$ cat repro.cpp
    #include <locale>
    #include <ios>
    #include <streambuf>
    #include <cassert>
    #include "test_macros.h"
    #include "test_iterators.h"

    #include "platform_support.h" // locale name macros

    typedef std::money_get<char, input_iterator<const char*> > Fn;

    struct my_facet : Fn {
        explicit my_facet(std::size_t refs) : Fn(refs) {}
    };

    int main(int, char**) {
        std::ios ios(0);
        std::string loc_name(LOCALE_ru_RU_UTF_8);
        ios.imbue(std::locale(ios.getloc(),
                              new std::moneypunct_byname<char, false>(loc_name)));
        ios.imbue(std::locale(ios.getloc(),
                              new std::moneypunct_byname<char, true>(loc_name)));
        ios.imbue(std::locale(ios.getloc(),
                              new std::moneypunct_byname<wchar_t, false>(loc_name)));
        ios.imbue(std::locale(ios.getloc(),
                              new std::moneypunct_byname<wchar_t, true>(loc_name)));

        const my_facet f(1);
        {   // zero, showbase
            std::string v = "0,00 RUB ";
            showbase(ios);
            typedef input_iterator<const char*> I;
            long double ex;
            std::ios_base::iostate err = std::ios_base::goodbit;
            I beg(v.data());
            I end(v.data() + v.size());
            I iter = f.get(beg, end, true, ios, err, ex);
            assert(iter.base() == v.data() + v.size());
            assert(err == std::ios_base::eofbit);
            assert(ex == 0);
            noshowbase(ios);
        }

        return 0;
    }
Comment 2 Alexander Richardson 2020-11-10 07:35:23 PST
I also ran into this while testing on FreeBSD. It appears that the problem is that the space after "RUB " is not consumed on Apple and FreeBSD.

I can upload a patch for this shortly. Would you prefer

a)

#if defined(__FreeBSD__) || defined(__APPLE__)
            // FreeBSD's and Apple's libc do not consume the space.
            assert(iter.base() == v.data() + v.size() - 1);
            assert(err == std::ios_base::goodbit);
#else
            assert(iter.base() == v.data() + v.size());
            assert(err == std::ios_base::eofbit);
#endif

Or b)

Changing e.g. "-1 234 567,89 RUB " to "-1 234 567,89 RUB". I'm not sure if the space is important, but removing it fixes the test for me.
Comment 3 Alexander Richardson 2020-11-10 07:36:30 PST
The fr_FR tests seem to use "1 234 567,89 EUR" without the trailing space, so I guess that means omitting it is fine?
Comment 4 Louis Dionne 2020-11-10 07:52:13 PST
I think I would do b), so that the tests are as streamlined as possible.

TBH, I don't understand why there's subtle differences like:

    #if !defined(APPLE_FIXME)
    {   // zero, showbase
        std::string v = "0,00 RUB ";
        showbase(ios);
        typedef input_iterator<const char*> I;
        long double ex;
        std::ios_base::iostate err = std::ios_base::goodbit;
        I iter = f.get(I(v.data()), I(v.data() + v.size()),
                                            true, ios, err, ex);
        assert(iter.base() == v.data() + v.size());
        assert(err == std::ios_base::eofbit);
        assert(ex == 0);
        noshowbase(ios);
    }
    #endif
    {   // negative one, showbase
        std::string v = "-0,01 RUB ";
        typedef input_iterator<const char*> I;
        long double ex;
        std::ios_base::iostate err = std::ios_base::goodbit;
        I iter = f.get(I(v.data()), I(v.data() + v.size()),
                                            true, ios, err, ex);
        assert(iter.base() == v.data() + 6);
        assert(err == std::ios_base::goodbit);
        assert(ex == -1);
    }

Why do we check for eofbit when parsing 0,00 RUB, but goodbit when parsing -0,01 RUB?

I would try to remove the trailing space and see whether that still works. If you upload a patch on Phabricator, that'll also run the tests on Linux and macOS automatically, so you can experiment that way.

Thanks for looking into it.. these locale APIs are terrible. :-)