-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Description
On #131921, it was noted that the change caused an undefined symbol in some situations. What happens is that libcxx_static.a
ends up containing a definition of std::__1::basic_streambuf<char, std::__1::char_traits<char>>::seekoff(long long, std::__1::ios_base::seekdir, unsigned int)
and a reference to std::__1::basic_streambuf<char, std::__1::char_traits<char>>::seekoff(long, std::__1::ios_base::seekdir, unsigned int)
. The difference is the type of the first parameter: long long
vs. long
.
At link time, this will result in an error such as
error: undefined symbol: std::__1::basic_streambuf<char, std::__1::char_traits<char>>::seekoff(long, std::__1::ios_base::seekdir, unsigned int)
with references from vtable for std::__1::__stdinbuf<char>
and similar.
The difference is caused by these lines in libcxx/include/__fwd/ios.h
:
#if defined(_NEWLIB_VERSION)
// On newlib, off_t is 'long int'
using streamoff = long int; // for char_traits in <string>
#else
using streamoff = long long; // for char_traits in <string>
#endif
On systems with newlib, it is possible to get to this code with or without _NEWLIB_VERSION
being defined. The inclusion of newlib header files causes _NEWLIB_VERSION
to be defined, so including libc headers before libcxx headers will cause _NEWLIB_VERSION
to be defined, resulting in streamoff being long int
. However, if libcxx headers are included without first including newlib headers, _NEWLIB_VERSION
will be undefined and streamoff will be long long
. The inconsistency results in the link error.
An attempt was made in #131921 to fix this issue by adding the following lines to libcxx/include/__configuration/platform.h
:
// This is required in order for _NEWLIB_VERSION to be defined in places where we use it.
// TODO: We shouldn't be including arbitrarily-named headers from libc++ since this can break valid
// user code. Move code paths that need _NEWLIB_VERSION to another customization mechanism.
#if __has_include(<picolibc.h>)
# include <picolibc.h>
#endif
This presumably works on systems with picolibc, but systems that use newlib but not picolibc, the error still happens.