diff options
Diffstat (limited to 'test')
6 files changed, 554 insertions, 0 deletions
diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index c98cc8065..8d08db4fd 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -34,6 +34,7 @@ #include <cerrno> #include <cfenv> #include <cfloat> +#include <charconv> #include <chrono> #include <cinttypes> #include <ciso646> diff --git a/test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp b/test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp new file mode 100644 index 000000000..d21b638d0 --- /dev/null +++ b/test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// <charconv> + +// In +// +// from_chars_result from_chars(const char* first, const char* last, +// Integral& value, int base = 10) +// +// Integral cannot be bool. + +#include <charconv> + +int main() +{ + using std::from_chars; + char buf[] = "01001"; + bool lv; + + from_chars(buf, buf + sizeof(buf), lv); // expected-error {{call to deleted function}} + from_chars(buf, buf + sizeof(buf), lv, 16); // expected-error {{call to deleted function}} +} diff --git a/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp b/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp new file mode 100644 index 000000000..e5a93b497 --- /dev/null +++ b/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp @@ -0,0 +1,181 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// <charconv> + +// from_chars_result from_chars(const char* first, const char* last, +// Integral& value, int base = 10) + +#include "charconv_test_helpers.h" + +template <typename T> +struct test_basics : roundtrip_test_base<T> +{ + using roundtrip_test_base<T>::test; + + void operator()() + { + test(0); + test(42); + test(32768); + test(0, 10); + test(42, 10); + test(32768, 10); + test(0xf, 16); + test(0xdeadbeaf, 16); + test(0755, 8); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits<T>; + + test(1, b); + test(xl::lowest(), b); + test((xl::max)(), b); + test((xl::max)() / 2, b); + } + + using std::from_chars; + std::from_chars_result r; + T x; + + { + char s[] = "001x"; + + // the expected form of the subject sequence is a sequence of + // letters and digits representing an integer with the radix + // specified by base (C11 7.22.1.4/3) + r = from_chars(s, s + sizeof(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == 1); + } + + { + char s[] = "0X7BAtSGHDkEIXZg "; + + // The letters from a (or A) through z (or Z) are ascribed the + // values 10 through 35; (C11 7.22.1.4/3) + r = from_chars(s, s + sizeof(s), x, 36); + assert(r.ec == std::errc::result_out_of_range); + // The member ptr of the return value points to the first character + // not matching the pattern + assert(r.ptr == s + sizeof(s) - 2); + assert(x == 1); + + // no "0x" or "0X" prefix shall appear if the value of base is 16 + r = from_chars(s, s + sizeof(s), x, 16); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 1); + assert(x == 0); + + // only letters and digits whose ascribed values are less than that + // of base are permitted. (C11 7.22.1.4/3) + r = from_chars(s + 2, s + sizeof(s), x, 12); + // If the parsed value is not in the range representable by the type + // of value, + if (!fits_in<T>(1150)) + { + // value is unmodified and + assert(x == 0); + // the member ec of the return value is equal to + // errc::result_out_of_range + assert(r.ec == std::errc::result_out_of_range); + } + else + { + // Otherwise, value is set to the parsed value, + assert(x == 1150); + // and the member ec is value-initialized. + assert(r.ec == std::errc{}); + } + assert(r.ptr == s + 5); + } + } +}; + +template <typename T> +struct test_signed : roundtrip_test_base<T> +{ + using roundtrip_test_base<T>::test; + + void operator()() + { + test(-1); + test(-12); + test(-1, 10); + test(-12, 10); + test(-21734634, 10); + test(-2647, 2); + test(-0xcc1, 16); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits<T>; + + test(0, b); + test(xl::lowest(), b); + test((xl::max)(), b); + } + + using std::from_chars; + std::from_chars_result r; + T x; + + { + // If the pattern allows for an optional sign, + // but the string has no digit characters following the sign, + char s[] = "- 9+12"; + r = from_chars(s, s + sizeof(s), x); + // no characters match the pattern. + assert(r.ptr == s); + assert(r.ec == std::errc::invalid_argument); + } + + { + char s[] = "9+12"; + r = from_chars(s, s + sizeof(s), x); + assert(r.ec == std::errc{}); + // The member ptr of the return value points to the first character + // not matching the pattern, + assert(r.ptr == s + 1); + assert(x == 9); + } + + { + char s[] = "12"; + r = from_chars(s, s + 2, x); + assert(r.ec == std::errc{}); + // or has the value last if all characters match. + assert(r.ptr == s + 2); + assert(x == 12); + } + + { + // '-' is the only sign that may appear + char s[] = "+30"; + // If no characters match the pattern, + r = from_chars(s, s + sizeof(s), x); + // value is unmodified, + assert(x == 12); + // the member ptr of the return value is first and + assert(r.ptr == s); + // the member ec is equal to errc::invalid_argument. + assert(r.ec == std::errc::invalid_argument); + } + } +}; + +int +main() +{ + run<test_basics>(integrals); + run<test_signed>(all_signed); +} diff --git a/test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp b/test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp new file mode 100644 index 000000000..e3d702a3a --- /dev/null +++ b/test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// <charconv> + +// In +// +// to_chars_result to_chars(char* first, char* last, Integral value, +// int base = 10) +// +// Integral cannot be bool. + +#include <charconv> + +int main() +{ + using std::to_chars; + char buf[10]; + bool lv = true; + + to_chars(buf, buf + sizeof(buf), false); // expected-error {{call to deleted function}} + to_chars(buf, buf + sizeof(buf), lv, 16); // expected-error {{call to deleted function}} +} diff --git a/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp b/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp new file mode 100644 index 000000000..50ca5b190 --- /dev/null +++ b/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// <charconv> + +// to_chars_result to_chars(char* first, char* last, Integral value, +// int base = 10) + +#include "charconv_test_helpers.h" + +template <typename T> +struct test_basics : to_chars_test_base<T> +{ + using to_chars_test_base<T>::test; + using to_chars_test_base<T>::test_value; + + void operator()() + { + test(0, "0"); + test(42, "42"); + test(32768, "32768"); + test(0, "0", 10); + test(42, "42", 10); + test(32768, "32768", 10); + test(0xf, "f", 16); + test(0xdeadbeaf, "deadbeaf", 16); + test(0755, "755", 8); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits<T>; + + test_value(1, b); + test_value(xl::lowest(), b); + test_value((xl::max)(), b); + test_value((xl::max)() / 2, b); + } + } +}; + +template <typename T> +struct test_signed : to_chars_test_base<T> +{ + using to_chars_test_base<T>::test; + using to_chars_test_base<T>::test_value; + + void operator()() + { + test(-1, "-1"); + test(-12, "-12"); + test(-1, "-1", 10); + test(-12, "-12", 10); + test(-21734634, "-21734634", 10); + test(-2647, "-101001010111", 2); + test(-0xcc1, "-cc1", 16); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits<T>; + + test_value(0, b); + test_value(xl::lowest(), b); + test_value((xl::max)(), b); + } + } +}; + +int +main() +{ + run<test_basics>(integrals); + run<test_signed>(all_signed); +} diff --git a/test/support/charconv_test_helpers.h b/test/support/charconv_test_helpers.h new file mode 100644 index 000000000..df1b00a67 --- /dev/null +++ b/test/support/charconv_test_helpers.h @@ -0,0 +1,232 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_CHARCONV_TEST_HELPERS_H +#define SUPPORT_CHARCONV_TEST_HELPERS_H + +#include <charconv> +#include <cassert> +#include <limits> +#include <string.h> +#include <stdlib.h> + +#include "test_macros.h" + +#if TEST_STD_VER <= 11 +#error This file requires C++14 +#endif + +using std::false_type; +using std::true_type; + +template <typename To, typename From> +constexpr auto +is_non_narrowing(From a) -> decltype(To{a}, true_type()) +{ + return {}; +} + +template <typename To> +constexpr auto +is_non_narrowing(...) -> false_type +{ + return {}; +} + +template <typename X, typename T> +constexpr bool +_fits_in(T, true_type /* non-narrowing*/, ...) +{ + return true; +} + +template <typename X, typename T, typename xl = std::numeric_limits<X>> +constexpr bool +_fits_in(T v, false_type, true_type /* T signed*/, true_type /* X signed */) +{ + return xl::lowest() <= v && v <= (xl::max)(); +} + +template <typename X, typename T, typename xl = std::numeric_limits<X>> +constexpr bool +_fits_in(T v, false_type, true_type /* T signed */, false_type /* X unsigned*/) +{ + return 0 <= v && std::make_unsigned_t<T>(v) <= (xl::max)(); +} + +template <typename X, typename T, typename xl = std::numeric_limits<X>> +constexpr bool +_fits_in(T v, false_type, false_type /* T unsigned */, ...) +{ + return v <= std::make_unsigned_t<X>((xl::max)()); +} + +template <typename X, typename T> +constexpr bool +fits_in(T v) +{ + return _fits_in<X>(v, is_non_narrowing<X>(v), std::is_signed<T>(), + std::is_signed<X>()); +} + +template <typename X> +struct to_chars_test_base +{ + template <typename T, size_t N, typename... Ts> + void test(T v, char const (&expect)[N], Ts... args) + { + using std::to_chars; + std::to_chars_result r; + + constexpr size_t len = N - 1; + static_assert(len > 0, "expected output won't be empty"); + + if (!fits_in<X>(v)) + return; + + r = to_chars(buf, buf + len - 1, X(v), args...); + assert(r.ptr == buf + len - 1); + assert(r.ec == std::errc::value_too_large); + + r = to_chars(buf, buf + sizeof(buf), X(v), args...); + assert(r.ptr == buf + len); + assert(r.ec == std::errc{}); + assert(memcmp(buf, expect, len) == 0); + } + + template <typename... Ts> + void test_value(X v, Ts... args) + { + using std::to_chars; + std::to_chars_result r; + + r = to_chars(buf, buf + sizeof(buf), v, args...); + assert(r.ec == std::errc{}); + *r.ptr = '\0'; + + auto a = fromchars(buf, r.ptr, args...); + assert(v == a); + + auto ep = r.ptr - 1; + r = to_chars(buf, ep, v, args...); + assert(r.ptr == ep); + assert(r.ec == std::errc::value_too_large); + } + +private: + static auto fromchars(char const* p, char const* ep, int base, true_type) + { + char* last; + auto r = strtoll(p, &last, base); + assert(last == ep); + + return r; + } + + static auto fromchars(char const* p, char const* ep, int base, false_type) + { + char* last; + auto r = strtoull(p, &last, base); + assert(last == ep); + + return r; + } + + static auto fromchars(char const* p, char const* ep, int base = 10) + { + return fromchars(p, ep, base, std::is_signed<X>()); + } + + char buf[100]; +}; + +template <typename X> +struct roundtrip_test_base +{ + template <typename T, typename... Ts> + void test(T v, Ts... args) + { + using std::from_chars; + using std::to_chars; + std::from_chars_result r2; + std::to_chars_result r; + X x = 0xc; + + if (fits_in<X>(v)) + { + r = to_chars(buf, buf + sizeof(buf), v, args...); + assert(r.ec == std::errc{}); + + r2 = from_chars(buf, r.ptr, x, args...); + assert(r2.ptr == r.ptr); + assert(x == X(v)); + } + else + { + r = to_chars(buf, buf + sizeof(buf), v, args...); + assert(r.ec == std::errc{}); + + r2 = from_chars(buf, r.ptr, x, args...); + + if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value) + { + assert(x == 0xc); + assert(r2.ptr == buf); + assert(r.ec == std::errc::invalid_argument); + } + else + { + assert(x == 0xc); + assert(r2.ptr == r.ptr); + assert(r2.ec == std::errc::result_out_of_range); + } + } + } + +private: + char buf[100]; +}; + +template <typename... T> +struct type_list +{ +}; + +template <typename L1, typename L2> +struct type_concat; + +template <typename... Xs, typename... Ys> +struct type_concat<type_list<Xs...>, type_list<Ys...>> +{ + using type = type_list<Xs..., Ys...>; +}; + +template <typename L1, typename L2> +using concat_t = typename type_concat<L1, L2>::type; + +template <typename L1, typename L2> +constexpr auto concat(L1, L2) -> concat_t<L1, L2> +{ + return {}; +} + +auto all_signed = type_list<char, signed char, short, int, long, long long>(); +auto all_unsigned = type_list<unsigned char, unsigned short, unsigned int, + unsigned long, unsigned long long>(); +auto integrals = concat(all_signed, all_unsigned); + +template <template <typename> class Fn, typename... Ts> +void +run(type_list<Ts...>) +{ + int ls[sizeof...(Ts)] = {(Fn<Ts>{}(), 0)...}; + (void)ls; +} + +#endif // SUPPORT_CHARCONV_TEST_HELPERS_H |