summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/libcxx/double_include.sh.cpp1
-rw-r--r--test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp30
-rw-r--r--test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp181
-rw-r--r--test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp30
-rw-r--r--test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp80
-rw-r--r--test/support/charconv_test_helpers.h232
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