Skip to content

std::locale works unexpectedly with unsupported locale #22051

@hly2019

Description

@hly2019

Please include the following in your bug report:

Version of emscripten/emsdk:
3.1.54

Failing command line in full:

# emcc
emcc locale_not_support.cpp  -o main.js
node main.js

# g++
g++ locale_not_support.cpp  -o main
./main

Hi, it's a follow-up issue to #2630 and #2636. I'm trying to use std::locale. It seems that currently emscripten is not throwing any exceptions when a locale is not supported. It seems the locale name is set as given, but the functionality appears to be the same as the std::locale::classic().

As the code and results shown below, if I tried to print the date, number, etc., of POSIX locale and es_ES.UTF-8. In wasm, the results seem to be the same as the POSIX locale. But its name is set as given, and turns out to be different with the std::locale::classic() (POSIX locale) if I simply use == for comparison. It may not be a big problem, but I believe there could be some better ways to deal with unsupported locales, like simply returning std::locale::classic() whatever the given name is, or throwing exceptions like native execution does.

I saw the commit 3aa06ea trying to solve this to make the program fail when the locale is not supported. But it seems it was modified in the later version and now it won't fail given unsupported locales. Is that due to some special considerations?

Thank you very much!

Code

#include <iostream>
#include <locale>
#include <iomanip>
#include <ctime>

void printNumber(const std::locale& loc) {
    std::cout.imbue(loc);
    std::cout << "Formatted number: " << std::fixed << std::setprecision(2) << 12345.67 << std::endl;
}

void printDate(const std::locale& loc) {
    std::time_t t = std::time(nullptr);
    std::tm* tm = std::localtime(&t);
    std::cout.imbue(loc);
    std::cout << "Formatted date: " << std::put_time(tm, "%c") << std::endl;
}

int main() {
    printf("flag before set posix locale\n");
    std::locale posix("C");
    
    std::cout << "locale C, name: " << posix.name() << std::endl;
    printNumber(posix);
    printDate(posix);

    std::cout << std::endl;

    printf("flag before set spanish locale\n");
    std::locale spanish("es_ES.UTF-8");

    std::cout << "es_ES.UTF-8, locale name: " << spanish.name() << std::endl;
    printNumber(spanish);
    printDate(spanish);

    std::cout << std::endl;

    std::cout << "is C equal?: " << (posix == std::locale::classic()) << std::endl;
    std::cout << "is spanish equal?: " << (spanish == std::locale::classic()) << std::endl;
    return 0;
}

Results

# in wasm:
flag before set posix locale
locale C, name: C
Formatted number: 12345.67
Formatted date: Mon Jun 03 18:36:20 2024

flag before set spanish locale
es_ES.UTF-8, locale name: es_ES.UTF-8
Formatted number: 12345.67
Formatted date: Mon Jun 03 18:36:20 2024

is C equal?: 1
is spanish equal?: 0

# in native (one that doesn't have es_ES.UTF-8 support):
flag before set posix locale
locale C, name: C
Formatted number: 12345.67
Formatted date: Mon Jun  3 19:08:59 2024

flag before set spanish locale
terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid
Aborted (core dumped)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions