diff --git a/libcxx/include/locale b/libcxx/include/locale index 7e861f880555fa..bf52071374f82f 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -1085,7 +1085,7 @@ num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, int __base = 16; // Stage 2 char_type __atoms[26]; - char_type __thousands_sep = 0; + char_type __thousands_sep = char_type(); string __grouping; std::use_facet >(__iob.getloc()).widen(__num_get_base::__src, __num_get_base::__src + 26, __atoms); diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/user_defined_char_type.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/user_defined_char_type.pass.cpp new file mode 100644 index 00000000000000..d7b4b816d975b9 --- /dev/null +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/user_defined_char_type.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// +// Make sure that num_get works with a user-defined char_type that has a +// constructor making initialization from bare `int` invalid. + +#include +#include +#include +#include + +#include "test_macros.h" + +struct Char { + Char() = default; + Char(char c) : underlying_(c) {} + Char(unsigned i) : underlying_(i) {} + explicit Char(std::int32_t i) : underlying_(i) {} + operator std::int32_t() const { return underlying_; } + + char underlying_; +}; + +namespace std { +template <> +struct char_traits { + using char_type = Char; + using int_type = int; + using off_type = streamoff; + using pos_type = streampos; + using state_type = mbstate_t; + + static void assign(char_type& a, const char_type& b) { a = b; } + static bool eq(char_type a, char_type b) { return a.underlying_ == b.underlying_; } + static bool lt(char_type a, char_type b) { return a.underlying_ < b.underlying_; } + + static int compare(const char_type* s1, const char_type* s2, std::size_t n) { + return char_traits::compare(reinterpret_cast(s1), reinterpret_cast(s2), n); + } + static std::size_t length(const char_type* s) { return char_traits::length(reinterpret_cast(s)); } + static const char_type* find(const char_type* p, std::size_t n, const char_type& c) { + for (size_t i = 0; i != n; ++i) { + if (static_cast(p[i]) == static_cast(c)) { + return p + n; + } + } + return nullptr; + } + static char_type* move(char_type* dest, const char_type* source, std::size_t count) { + char_traits::move(reinterpret_cast(dest), reinterpret_cast(source), count); + return dest; + } + static char_type* copy(char_type* dest, const char_type* source, std::size_t count) { + char_traits::copy(reinterpret_cast(dest), reinterpret_cast(source), count); + return dest; + } + static char_type* assign(char_type* dest, std::size_t n, char_type c) { + char_traits::assign(reinterpret_cast(dest), n, c.underlying_); + return dest; + } + + static int_type not_eof(int_type i) { return char_traits::not_eof(i); } + static char_type to_char_type(int_type i) { return Char(char_traits::to_char_type(i)); } + static int_type to_int_type(char_type c) { return char_traits::to_int_type(c.underlying_); } + static bool eq_int_type(int_type i, int_type j) { return i == j; } + static int_type eof() { return char_traits::eof(); } +}; + +template <> +class ctype : public locale::facet { +public: + static locale::id id; + Char toupper(Char c) const { return Char(std::toupper(c.underlying_)); } + const char* widen(const char* first, const char* last, Char* dst) const { + for (; first != last;) + *dst++ = Char(*first++); + return last; + } +}; + +locale::id ctype::id; + +template <> +class numpunct : public locale::facet { +public: + typedef basic_string string_type; + static locale::id id; + Char decimal_point() const { return Char('.'); } + Char thousands_sep() const { return Char(','); } + string grouping() const { return ""; } + string_type truename() const { + static Char yes[] = {Char('t')}; + return string_type(yes, 1); + } + string_type falsename() const { + static Char no[] = {Char('f')}; + return string_type(no, 1); + } +}; + +locale::id numpunct::id; + +} // namespace std + +int main(int, char**) { + std::locale l(std::locale::classic(), new std::num_get); + + return 0; +}