diff options
| author | Mark de Wever <koraq@xs4all.nl> | 2023-06-02 11:25:50 +0200 |
|---|---|---|
| committer | Mark de Wever <koraq@xs4all.nl> | 2023-07-15 11:52:19 +0200 |
| commit | 1c1edd1b5d00daae2efdfbc5754a9fae77597dd4 (patch) | |
| tree | 54458931bd17d2c4657005333cd5f205ebf2fd39 /libcxx/include/__thread | |
| parent | 4675a3261e53edef772932debd8a05eb8ccb61b9 (diff) | |
[libc++] Fixes thread::id's operator<<.
The output of
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& out, thread::id id);
is affected by the state of out. The wording states
[thread.thread.id]/2
The text representation for the character type charT of an object of
type thread::id is an unspecified sequence of charT such that, for two
objects of type thread::id x and y, if x == y is true, the thread::id
objects have the same text representation, and if x != y is true, the
thread::id objects have distinct text representations.
[thread.thread.id]/9
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<< (basic_ostream<charT, traits>& out, thread::id id);
Effects: Inserts the text representation for charT of id into out.
This wording changed in C++23 due to adding a formatter specialization for
thread::id. However the requirement was the same in older versions of C++.
This issue is that thread::id is an integral or pointer and affected by the
formatting manipulators for them. Thus the text representation can differ if
x == y which violates the requirements.
The fix has to hard-code some formatting style for the text
representation. It uses the Standard specified default values
Table 124: basic_ios::init() effectsâ[tab:basic.ios.cons] flags()
flags() skipws | dec
Fixes PR: https://llvm.org/PR62073
Reviewed By: #libc, ldionne
Differential Revision: https://reviews.llvm.org/D153336
Diffstat (limited to 'libcxx/include/__thread')
| -rw-r--r-- | libcxx/include/__thread/thread.h | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h index 3d52d87f7026..dec40c7dc1f0 100644 --- a/libcxx/include/__thread/thread.h +++ b/libcxx/include/__thread/thread.h @@ -24,6 +24,10 @@ #include <iosfwd> #include <tuple> +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include <locale> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -126,11 +130,32 @@ struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> } }; -template<class _CharT, class _Traits> -_LIBCPP_INLINE_VISIBILITY -basic_ostream<_CharT, _Traits>& -operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) -{return __os << __id.__id_;} +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +template <class _CharT, class _Traits> +_LIBCPP_INLINE_VISIBILITY basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) { + // [thread.thread.id]/9 + // Effects: Inserts the text representation for charT of id into out. + // + // [thread.thread.id]/2 + // The text representation for the character type charT of an + // object of type thread::id is an unspecified sequence of charT + // such that, for two objects of type thread::id x and y, if + // x == y is true, the thread::id objects have the same text + // representation, and if x != y is true, the thread::id objects + // have distinct text representations. + // + // Since various flags in the output stream can affect how the + // thread id is represented (e.g. numpunct or showbase), we + // use a temporary stream instead and just output the thread + // id representation as a string. + + basic_ostringstream<_CharT, _Traits> __sstr; + __sstr.imbue(locale::classic()); + __sstr << __id.__id_; + return __os << __sstr.str(); +} +#endif // _LIBCPP_HAS_NO_LOCALIZATION class _LIBCPP_EXPORTED_FROM_ABI thread { |
