diff options
author | A. Jiang <de34@live.cn> | 2024-05-22 01:05:51 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-21 19:05:51 +0200 |
commit | 3e15c97fa3812993bdc319827a5c6d867b765ae8 (patch) | |
tree | 6bef3557b4c2256766c50b9514f4022322cdccaa /libcxx | |
parent | 0eca2655843e1b79e6c65c7239bce8c9a1509568 (diff) | |
download | llvm-3e15c97fa3812993bdc319827a5c6d867b765ae8.zip llvm-3e15c97fa3812993bdc319827a5c6d867b765ae8.tar.gz llvm-3e15c97fa3812993bdc319827a5c6d867b765ae8.tar.bz2 |
[libc++] LWG2381: Inconsistency in parsing floating point numbers (#77948)
This PR implements [LWG2381](https://cplusplus.github.io/LWG/issue2381)
by rejecting `'i'`, `'I'`, `'n'`, `'N'` in FP parsing, as inf and NaN
are intendedly rejected by that LWG issue.
The source character array used for parsing is
`"0123456789abcdefABCDEFxX+-pPiInN"`, whose first 26 or 28 characters
are used for parsing integers or floating-point values respectively.
Previously, libc++ used 32 characters, including `'i'`, `'I'`, `'n'`,
`'N'`, for FP parsing, which was inconsistent with LWG2381. This PR also
replaces magic numbers 26 and 28 (formerly 32) with named constants.
Drive-by change: when the first character (possibly after the leading
`'+'` or `'-'`) is not a decimal digit but an acceptable character
(e.g., `'p'` or `'e'`), the character is not accumulated now (per Stage
2 in [facet.num.get.virtuals]/3).
#65168 may be rendered invalid, see
https://github.com/llvm/llvm-project/pull/65168#issuecomment-1868533342.
Apple back-deployment targets remain broken, likely due to dylib. XFAIL
is marked in related tests.
---------
Co-authored-by: Mark de Wever <koraq@xs4all.nl>
Diffstat (limited to 'libcxx')
5 files changed, 467 insertions, 71 deletions
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index d421fee..cc601b3 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -98,7 +98,7 @@ `3555 <https://wg21.link/LWG3555>`__,"``{transform,elements}_view::iterator::iterator_concept`` should consider const-qualification of the underlying range","June 2021","","","|ranges|" "","","","","","" `2191 <https://wg21.link/LWG2191>`__,"Incorrect specification of ``match_results(match_results&&)``","October 2021","|Nothing To Do|","" -`2381 <https://wg21.link/LWG2381>`__,"Inconsistency in parsing floating point numbers","October 2021","","" +`2381 <https://wg21.link/LWG2381>`__,"Inconsistency in parsing floating point numbers","October 2021","|Complete|","19.0" `2762 <https://wg21.link/LWG2762>`__,"``unique_ptr operator*()`` should be ``noexcept``","October 2021","","" `3121 <https://wg21.link/LWG3121>`__,"``tuple`` constructor constraints for ``UTypes&&...`` overloads","October 2021","","" `3123 <https://wg21.link/LWG3123>`__,"``duration`` constructor from representation shouldn't be effectively non-throwing","October 2021","","","|chrono|" diff --git a/libcxx/include/locale b/libcxx/include/locale index 748b276..041d7bc 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -368,7 +368,11 @@ struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { static const int __num_get_buf_sz = 40; static int __get_base(ios_base&); - static const char __src[33]; + static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN" + // count of leading characters in __src used for parsing integers ("012..X+-") + static const size_t __int_chr_cnt = 26; + // count of leading characters in __src used for parsing floating-point values ("012..-pP") + static const size_t __fp_chr_cnt = 28; }; _LIBCPP_EXPORTED_FROM_ABI void @@ -431,7 +435,7 @@ private: template <typename _Tp> const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { locale __loc = __iob.getloc(); - use_facet<ctype<_Tp> >(__loc).widen(__src, __src + 26, __atoms); + use_facet<ctype<_Tp> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); return __atoms; } @@ -447,7 +451,7 @@ private: template <class _CharT> string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms); + std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc); __thousands_sep = __np.thousands_sep(); return __np.grouping(); @@ -458,7 +462,7 @@ template <class _CharT> string __num_get<_CharT>::__stage2_float_prep( ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms); + std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms); const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc); __decimal_point = __np.decimal_point(); __thousands_sep = __np.thousands_sep(); @@ -490,7 +494,7 @@ __num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& } return 0; } - ptrdiff_t __f = std::find(__atoms, __atoms + 26, __ct) - __atoms; + ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms; if (__f >= 24) return -1; switch (__base) { @@ -546,8 +550,8 @@ int __num_get<_CharT>::__stage2_float_loop( } return 0; } - ptrdiff_t __f = std::find(__atoms, __atoms + 32, __ct) - __atoms; - if (__f >= 32) + ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms; + if (__f >= static_cast<ptrdiff_t>(__num_get_base::__fp_chr_cnt)) return -1; char __x = __src[__f]; if (__x == '-' || __x == '+') { @@ -846,7 +850,7 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed( int __base = this->__get_base(__iob); // Stage 2 char_type __thousands_sep; - const int __atoms_size = 26; + const int __atoms_size = __num_get_base::__int_chr_cnt; #ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET char_type __atoms1[__atoms_size]; const char_type* __atoms = this->__do_widen(__iob, __atoms1); @@ -895,7 +899,7 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned( int __base = this->__get_base(__iob); // Stage 2 char_type __thousands_sep; - const int __atoms_size = 26; + const int __atoms_size = __num_get_base::__int_chr_cnt; #ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET char_type __atoms1[__atoms_size]; const char_type* __atoms = this->__do_widen(__iob, __atoms1); @@ -942,7 +946,7 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { // Stage 1, nothing to do // Stage 2 - char_type __atoms[32]; + char_type __atoms[__num_get_base::__fp_chr_cnt]; char_type __decimal_point; char_type __thousands_sep; string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); @@ -951,10 +955,11 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( char* __a = &__buf[0]; char* __a_end = __a; unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - bool __in_units = true; - char __exp = 'E'; + unsigned* __g_end = __g; + unsigned __dc = 0; + bool __in_units = true; + char __exp = 'E'; + bool __is_leading_parsed = false; for (; __b != __e; ++__b) { if (__a_end == __a + __buf.size()) { size_t __tmp = __buf.size(); @@ -977,6 +982,21 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( __dc, __atoms)) break; + + // the leading character excluding the sign must be a decimal digit + if (!__is_leading_parsed) { + if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { + if ('0' <= __a[0] && __a[0] <= '9') + __is_leading_parsed = true; + else + break; + } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { + if ('0' <= __a[1] && __a[1] <= '9') + __is_leading_parsed = true; + else + break; + } + } } if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) *__g_end++ = __dc; @@ -996,10 +1016,11 @@ _InputIterator num_get<_CharT, _InputIterator>::do_get( // Stage 1 int __base = 16; // Stage 2 - char_type __atoms[26]; + char_type __atoms[__num_get_base::__int_chr_cnt]; char_type __thousands_sep = char_type(); string __grouping; - std::use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src, __num_get_base::__src + 26, __atoms); + std::use_facet<ctype<_CharT> >(__iob.getloc()) + .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp index c802ab7..fbd1c7c 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// The fix for LWG2381 (https://github.com/llvm/llvm-project/pull/77948) changed +// behavior of FP parsing, while Apple back-deployment targets remain broken due +// to the dylib. +// UNSUPPORTED: using-built-library-before-llvm-19 + // <locale> // class num_get<charT, InputIterator> @@ -116,9 +121,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "INF"; @@ -128,9 +133,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "-inf"; @@ -140,9 +145,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "-INF"; @@ -152,9 +157,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "nan"; @@ -164,9 +169,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "NAN"; @@ -176,9 +181,129 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); } { v = -1; diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp index 79c8480..b5ac7d8 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// The fix for LWG2381 (https://github.com/llvm/llvm-project/pull/77948) changed +// behavior of FP parsing, while Apple back-deployment targets remain broken due +// to the dylib. +// UNSUPPORTED: using-built-library-before-llvm-19 + // <locale> // class num_get<charT, InputIterator> @@ -105,9 +110,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "INF"; @@ -117,9 +122,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "-inf"; @@ -129,9 +134,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "-INF"; @@ -141,9 +146,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "nan"; @@ -153,9 +158,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "NAN"; @@ -165,9 +170,129 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); } { v = -1; diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp index e2b2aeaf..9617899 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// The fix for LWG2381 (https://github.com/llvm/llvm-project/pull/77948) changed +// behavior of FP parsing, while Apple back-deployment targets remain broken due +// to the dylib. +// UNSUPPORTED: using-built-library-before-llvm-19 + // <locale> // class num_get<charT, InputIterator> @@ -105,9 +110,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "INF"; @@ -117,9 +122,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "-inf"; @@ -129,9 +134,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "-INF"; @@ -141,9 +146,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "nan"; @@ -153,9 +158,9 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "NAN"; @@ -165,9 +170,129 @@ int main(int, char**) f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator<const char*> iter = f.get( + cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "1.189731495357231765021264e+49321"; |