Skip to content

charconv function to_chars silently casts long double to double #22121

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

Closed
WarrenWeckesser opened this issue Jun 20, 2024 · 2 comments
Closed

Comments

@WarrenWeckesser
Copy link

This is main.cpp:

#include <cstdio>
#include <charconv>
#include <system_error>
#include <limits>

template<typename T>
static inline void
print_value(const T x)
{
    char buf[100];
    const std::to_chars_result res = std::to_chars(buf, buf + sizeof(buf), x);
    if (res.ec == std::errc{}) {
        printf("%.*s", static_cast<int>(res.ptr - buf), buf);
    }
    else {
        printf("<to_chars() failed!>");
    }
}

int main()
{
    printf("std::numeric_limits<long double>::digits = %d\n",
           std::numeric_limits<long double>::digits);

    long double x = 0.333333333333333333333333333333333333L;
    printf("x = ");
    print_value(x);
    printf("\n");

    printf("x = %-40.33Lf\n", x);
}

Here are the commands I use to build and run it:

% em++ main.cpp -sPRINTF_LONG_DOUBLE
% node a.out.js
std::numeric_limits<long double>::digits = 113
x = 0.3333333333333333
x = 0.333333333333333333333333333333333

I expect the first output of x to be the same as the second (other than possibly the last digit or two).

It looks like the culprit is the use of static_cast<double>(__value) here:

to_chars_result to_chars(char* __first, char* __last, long double __value) {
return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(
__first, __last, static_cast<double>(__value), chars_format{}, 0);
}

Personally I would rather have an error than a silent cast to double.

I labeled this issue a bug report, but you might not consider it a bug. In that case, this is an enhancement request!

Version of emscripten/emsdk:

% emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.61 (67fa4c16496b157a7fc3377afd69ee0445e8a6e3)
clang version 19.0.0git (https:/github.com/llvm/llvm-project 7cfffe74eeb68fbb3fb9706ac7071f8caeeb6520)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/warren/repos/git/forks/emsdk/upstream/bin

Full link command and output with -v appended:

Here's the build command again, with -v included:

% em++ -v main.cpp -sPRINTF_LONG_DOUBLE
 "/Users/warren/repos/git/forks/emsdk/upstream/bin/clang++" -target wasm32-unknown-emscripten -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --sysroot=/Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot -DEMSCRIPTEN -Xclang -iwithsysroot/include/fakesdl -Xclang -iwithsysroot/include/compat -v main.cpp -c -o /var/folders/6f/wyccw81j5kj1c7v6p47zr9fr0000gn/T/emscripten_temp__vzc3gnf/main_0.o
clang version 19.0.0git (https:/github.com/llvm/llvm-project 7cfffe74eeb68fbb3fb9706ac7071f8caeeb6520)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/warren/repos/git/forks/emsdk/upstream/bin
 (in-process)
 "/Users/warren/repos/git/forks/emsdk/upstream/bin/clang-19" -cc1 -triple wasm32-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -fvisibility=hidden -debugger-tuning=gdb -fdebug-compilation-dir=/Users/warren/code-snippets/c++/test-emscripten-stuff -v -fcoverage-compilation-dir=/Users/warren/code-snippets/c++/test-emscripten-stuff -resource-dir /Users/warren/repos/git/forks/emsdk/upstream/lib/clang/19 -D EMSCRIPTEN -isysroot /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot -internal-isystem /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1 -internal-isystem /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1 -internal-isystem /Users/warren/repos/git/forks/emsdk/upstream/lib/clang/19/include -internal-isystem /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten -internal-isystem /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fignore-exceptions -fexceptions -fcolor-diagnostics -iwithsysroot/include/fakesdl -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /var/folders/6f/wyccw81j5kj1c7v6p47zr9fr0000gn/T/emscripten_temp__vzc3gnf/main_0.o -x c++ main.cpp
clang -cc1 version 19.0.0git based upon LLVM 19.0.0git default target x86_64-apple-darwin22.6.0
ignoring nonexistent directory "/Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1"
ignoring nonexistent directory "/Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten"
#include "..." search starts here:
#include <...> search starts here:
 /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/fakesdl
 /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/compat
 /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1
 /Users/warren/repos/git/forks/emsdk/upstream/lib/clang/19/include
 /Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/include
End of search list.
 /Users/warren/repos/git/forks/emsdk/upstream/bin/clang --version
 /Users/warren/repos/git/forks/emsdk/upstream/bin/wasm-ld -o a.out.wasm -L/Users/warren/repos/git/forks/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten /var/folders/6f/wyccw81j5kj1c7v6p47zr9fr0000gn/T/emscripten_temp__vzc3gnf/main_0.o -lGL-getprocaddr -lal -lhtml5 -lprintf_long_double-debug -lstubs-debug -lnoexit -lc-debug -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-debug-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /var/folders/6f/wyccw81j5kj1c7v6p47zr9fr0000gn/T/tmpa9mob5fklibemscripten_js_symbols.so --strip-debug --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_get_current --export=emscripten_stack_init --export=_emscripten_stack_alloc --export=__get_temp_ret --export=__set_temp_ret --export=__wasm_call_ctors --export=_emscripten_stack_restore --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --no-growable-memory --initial-heap=16777216 --no-entry --stack-first --table-base=1
 /Users/warren/repos/git/forks/emsdk/upstream/bin/llvm-objcopy a.out.wasm a.out.wasm --remove-section=.debug* --remove-section=producers
 /Users/warren/repos/git/forks/emsdk/upstream/bin/wasm-emscripten-finalize --dyncalls-i64 --pass-arg=legalize-js-interface-exported-helpers a.out.wasm -o a.out.wasm --detect-features
 /Users/warren/repos/git/forks/emsdk/node/18.20.3_64bit/bin/node /Users/warren/repos/git/forks/emsdk/upstream/emscripten/src/compiler.mjs /var/folders/6f/wyccw81j5kj1c7v6p47zr9fr0000gn/T/tmpdn_74rpb.json
@sbc100
Copy link
Collaborator

sbc100 commented Jun 20, 2024

the code in question here is part of libc++ which itself is part of LLVM. If you really think this is a bug perhaps its best to file that bug upstream?

@WarrenWeckesser
Copy link
Author

Ah, right. In fact, there is already this: llvm/llvm-project#56261

Sorry for the noise!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants