Description
This simple program
#include <cstdio>
#include <string>
int main() { std::printf("%s\n", std::to_string(3.14).c_str()); }
fails to compile with LTO in the latest version of gcc (and also in older versions), when using OpenOSC 1.0.7.
$ g++ --version
g++ (GCC) 15.1.1 20250521 (Red Hat 15.1.1-2)
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -O2 -flto -o test test.cpp -include /usr/local/include/openosc.h
/usr/local/include/openosc_redirect_map.h: In function '__to_xstring.constprop':
/usr/local/include/openosc_redirect_map.h:601:1: error: inlining failed in call to 'always_inline' 'vsnprintf': function body can be overwritten at link time
601 | __NTH (vsnprintf (char *__restrict __pass_objsize1 dst, size_t len, const char *__restrict fmt, va_list ap))
| ^
/usr/include/c++/15/ext/string_conversions.h:115:32: note: called from here
115 | const int __len = __convf(__s, __n, __fmt, __args);
| ^
lto-wrapper: fatal error: g++ returned 1 exit status
compilation terminated.
/usr/sbin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
The problem seems to be that, according to the always_inline documentation,
Failure to inline such a function is diagnosed as an error. Note that if such a function is called indirectly the compiler may or may not inline it depending on optimization level and a failure to inline an indirect call may or may not be diagnosed.
And std::to_string in libstdc++ is implemented via a helper template that takes a pointer to vsnprint. The template is here.
Since vsnprintf is called indirectly, always_inline may fail.
You could argue the same problem applies to _FORTIFY_SOURCE but, since its implementation is way simpler, the inliner seems to be happier to inline it.