emscripten-core / emscripten-core/emscripten
-fshort-wchar is broken with -O2/-Os
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
Using -fshort-wchar with em++ produces incorrect results that vary depending on the optimization level.
**Version of emscripten/emsdk:**
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 5.0.4 (62e22652509fbe7a00609ce48a653d0d66f27ba5)
clang version 23.0.0git (https:/github.com/llvm/llvm-project dcaab6dd99a33edbf98ad1ade0ea0d196b797910)
Target: wasm32-unknown-emscripten
Thread model: posix
```
**Failing command line in full:**
I've tested with the following code (
[u16.cpp](https://github.com/user-attachments/files/26367473/u16.cpp)
[wchar.cpp](https://github.com/user-attachments/files/26367474/wchar.cpp)
[wcslen.cpp](https://github.com/user-attachments/files/26367475/wcslen.cpp)
).
**Command line**:
```
em++ -fshort-wchar u16.cpp -O0 && env node ./a.out.js
em++ -fshort-wchar u16.cpp -O2 && env node ./a.out.js
em++ -fshort-wchar u16.cpp -Os && env node ./a.out.js
```
**Results**:
```
length: 10 == 10
find: 6 == -1
length: 10 == 10
find: 6 == -1
length: 10 == 56
find: 6 == -1
```
u16string::size() — fails when -Os is used
u16string::find() — always fails
**u16.cpp**:
```cpp
#include
#include
int main()
{
std::u16string s = u"0123456789";
std::u16string::size_type l = s.size();
printf("length: %d == %zd\n", 10, l);
std::u16string::size_type p = s.find(u"678");
printf("find: %d == %zd\n", 6, p);
return 0;
}
```
`wchar_t` behavior is also unstable.
The `my_wcslen()` function malfunctions when -O2 or -Os is used.
**Command line**:
```
make
```
**Results**:
```
em++ -fshort-wchar -c wcslen.cpp -O0
em++ -fshort-wchar -c wchar.cpp -O0
em++ -fshort-wchar -o wchar.js wchar.o wcslen.o
env node ./wchar.js
wchar_t size: 2
len: 10 == 10
em++ -fshort-wchar -c wcslen.cpp -O2
em++ -fshort-wchar -c wchar.cpp -O2
em++ -fshort-wchar -o wchar.js wchar.o wcslen.o
env node ./wchar.js
wchar_t size: 2
len: 10 == 5
em++ -fshort-wchar -c wcslen.cpp -Os
em++ -fshort-wchar -c wchar.cpp -Os
em++ -fshort-wchar -o wchar.js wchar.o wcslen.o
env node ./wchar.js
wchar_t size: 2
len: 10 == 5
```
**wcslen.cpp**:
```cpp
#include
extern "C" size_t my_wcslen(const wchar_t* s)
{
const wchar_t* e = s;
while (*e) {
++e;
}
return e - s;
}
```
**wchar.cpp**:
```cpp
#include
#include
extern "C" size_t my_wcslen(const wchar_t* s);
int
main()
{
printf("wchar_t size: %zu\n", sizeof(wchar_t));
wchar_t str[] = L"0123456789";
size_t l1 = sizeof(str) / sizeof(str[0]) - 1;
size_t l2 = my_wcslen(str);
printf("len: %zu == %zu\n", l1, l2);
return 0;
}
```
**Makefile**:
```makefile
OPTFLAGS =
run: run0 run2 runs
run0: OPTFLAGS = -O0
run0:
em++ -fshort-wchar -c wcslen.cpp $(OPTFLAGS)
em++ -fshort-wchar -c wchar.cpp $(OPTFLAGS)
em++ -fshort-wchar -o wchar.js wchar.o wcslen.o
env node ./wchar.js
run2: OPTFLAGS = -O2
run2:
em++ -fshort-wchar -c wcslen.cpp $(OPTFLAGS)
em++ -fshort-wchar -c wchar.cpp $(OPTFLAGS)
em++ -fshort-wchar -o wchar.js wchar.o wcslen.o
env node ./wchar.js
runs: OPTFLAGS = -Os
runs:
em++ -fshort-wchar -c wcslen.cpp $(OPTFLAGS)
em++ -fshort-wchar -c wchar.cpp $(OPTFLAGS)
em++ -fshort-wchar -o wchar.js wchar.o wcslen.o
env node ./wchar.js
```
This wcslen bug is reproducible when `my_wcslen()` is compiled in a separate translation unit.
Contributor guide
Assessment
This issue has not been assessed yet.