summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/algorithm20
-rw-r--r--libcxx/include/type_traits42
-rw-r--r--libcxx/test/libcxx/type_traits/convert_to_integral.pass.cpp89
-rw-r--r--libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp5
-rw-r--r--libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp21
-rw-r--r--libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp5
-rw-r--r--libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp4
-rw-r--r--libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp6
-rw-r--r--libcxx/test/support/user_defined_integral.hpp44
9 files changed, 219 insertions, 17 deletions
diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm
index 68173f472c8..475ba66ad38 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -1672,7 +1672,8 @@ search_n(_ForwardIterator __first, _ForwardIterator __last,
_Size __count, const _Tp& __value_, _BinaryPredicate __pred)
{
return _VSTD::__search_n<typename add_lvalue_reference<_BinaryPredicate>::type>
- (__first, __last, __count, __value_, __pred, typename iterator_traits<_ForwardIterator>::iterator_category());
+ (__first, __last, __convert_to_integral(__count), __value_, __pred,
+ typename iterator_traits<_ForwardIterator>::iterator_category());
}
template <class _ForwardIterator, class _Size, class _Tp>
@@ -1681,7 +1682,8 @@ _ForwardIterator
search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value_)
{
typedef typename iterator_traits<_ForwardIterator>::value_type __v;
- return _VSTD::search_n(__first, __last, __count, __value_, __equal_to<__v, _Tp>());
+ return _VSTD::search_n(__first, __last, __convert_to_integral(__count),
+ __value_, __equal_to<__v, _Tp>());
}
// copy
@@ -1839,8 +1841,10 @@ typename enable_if
!__is_random_access_iterator<_InputIterator>::value,
_OutputIterator
>::type
-copy_n(_InputIterator __first, _Size __n, _OutputIterator __result)
+copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
{
+ typedef decltype(__convert_to_integral(__orig_n)) _IntegralSize;
+ _IntegralSize __n = __orig_n;
if (__n > 0)
{
*__result = *__first;
@@ -1862,8 +1866,10 @@ typename enable_if
__is_random_access_iterator<_InputIterator>::value,
_OutputIterator
>::type
-copy_n(_InputIterator __first, _Size __n, _OutputIterator __result)
+copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
{
+ typedef decltype(__convert_to_integral(__orig_n)) _IntegralSize;
+ _IntegralSize __n = __orig_n;
return _VSTD::copy(__first, __first + __n, __result);
}
@@ -2055,7 +2061,7 @@ inline _LIBCPP_INLINE_VISIBILITY
_OutputIterator
fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_)
{
- return _VSTD::__fill_n(__first, __n, __value_);
+ return _VSTD::__fill_n(__first, __convert_to_integral(__n), __value_);
}
// fill
@@ -2101,8 +2107,10 @@ generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen)
template <class _OutputIterator, class _Size, class _Generator>
inline _LIBCPP_INLINE_VISIBILITY
_OutputIterator
-generate_n(_OutputIterator __first, _Size __n, _Generator __gen)
+generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen)
{
+ typedef decltype(__convert_to_integral(__orig_n)) _IntegralSize;
+ _IntegralSize __n = __orig_n;
for (; __n > 0; ++__first, (void) --__n)
*__first = __gen();
return __first;
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 914e8593b2f..c44cae63908 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -3646,6 +3646,48 @@ struct underlying_type
#endif // _LIBCPP_UNDERLYING_TYPE
+
+template <class _Tp, bool = std::is_enum<_Tp>::value>
+struct __sfinae_underlying_type
+{
+ typedef typename underlying_type<_Tp>::type type;
+ typedef decltype(((type)1) + 0) __promoted_type;
+};
+
+template <class _Tp>
+struct __sfinae_underlying_type<_Tp, false> {};
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+int __convert_to_integral(int __val) { return __val; }
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+unsigned __convert_to_integral(unsigned __val) { return __val; }
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+long __convert_to_integral(long __val) { return __val; }
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+unsigned long __convert_to_integral(unsigned long __val) { return __val; }
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+long long __convert_to_integral(long long __val) { return __val; }
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+unsigned long long __convert_to_integral(unsigned long long __val) {return __val; }
+
+#ifndef _LIBCPP_HAS_NO_INT128
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+__int128_t __convert_to_integral(__int128_t __val) { return __val; }
+
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+__uint128_t __convert_to_integral(__uint128_t __val) { return __val; }
+#endif
+
+template <class _Tp>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+typename __sfinae_underlying_type<_Tp>::__promoted_type
+__convert_to_integral(_Tp __val) { return __val; }
+
#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE
template <class _Tp>
diff --git a/libcxx/test/libcxx/type_traits/convert_to_integral.pass.cpp b/libcxx/test/libcxx/type_traits/convert_to_integral.pass.cpp
new file mode 100644
index 00000000000..ccdc7675ad6
--- /dev/null
+++ b/libcxx/test/libcxx/type_traits/convert_to_integral.pass.cpp
@@ -0,0 +1,89 @@
+
+#include <limits>
+#include <type_traits>
+#include <cstdint>
+#include <cassert>
+
+#include "user_defined_integral.hpp"
+
+template <class T>
+struct EnumType
+{
+ enum type : T {E_zero, E_one};
+};
+
+
+template <class From, class To>
+void check_integral_types()
+{
+ typedef std::numeric_limits<From> Limits;
+ const From max = Limits::max();
+ const From min = Limits::min();
+ {
+ auto ret = std::__convert_to_integral((From)max);
+ assert(ret == max);
+ ret = std::__convert_to_integral((From)min);
+ assert(ret == min);
+ static_assert(std::is_same<decltype(ret), To>::value, "");
+ }
+ {
+ UserDefinedIntegral<From> f(max);
+ auto ret = std::__convert_to_integral(f);
+ assert(ret == max);
+ f.value = min;
+ ret = std::__convert_to_integral(f);
+ assert(ret == min);
+ static_assert(std::is_same<decltype(ret), To>::value, "");
+ }
+ {
+ typedef typename EnumType<From>::type Enum;
+ Enum e(static_cast<Enum>(max));
+ auto ret = std::__convert_to_integral(e);
+ assert(ret == max);
+ e = static_cast<Enum>(min);
+ ret = std::__convert_to_integral(min);
+ assert(ret == min);
+ static_assert(std::is_same<decltype(ret), To>::value, "");
+ }
+}
+
+
+template <class From, class To>
+void check_enum_types()
+{
+ auto ret = std::__convert_to_integral((From)1);
+ assert(ret == 1);
+ static_assert(std::is_same<decltype(ret), To>::value, "");
+}
+
+
+enum enum1 {};
+enum enum2 {
+ value = std::numeric_limits<unsigned long>::max()
+};
+
+int main()
+{
+ check_integral_types<bool, int>();
+ check_integral_types<char, int>();
+ check_integral_types<signed char, int>();
+ check_integral_types<unsigned char, int>();
+ check_integral_types<wchar_t, int>();
+ check_integral_types<char16_t, int>();
+ check_integral_types<char32_t, uint32_t>();
+ check_integral_types<short, int>();
+ check_integral_types<unsigned short, int>();
+ check_integral_types<int, int>();
+ check_integral_types<unsigned, unsigned>();
+ check_integral_types<long, long>();
+ check_integral_types<unsigned long, unsigned long>();
+ check_integral_types<long long, long long>();
+ check_integral_types<unsigned long long, unsigned long long>();
+#ifndef _LIBCPP_HAS_NO_INT128
+ check_integral_types<__int128_t, __int128_t>();
+ check_integral_types<__uint128_t, __uint128_t>();
+#endif
+ // TODO(ericwf): Not standard
+ check_enum_types<enum1, unsigned>();
+ check_enum_types<enum2, unsigned long>();
+}
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
index f594a0bf618..1dba8847c7e 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp
@@ -17,6 +17,9 @@
#include <cassert>
#include "test_iterators.h"
+#include "user_defined_integral.hpp"
+
+typedef UserDefinedIntegral<unsigned> UDI;
template <class InIter, class OutIter>
void
@@ -28,7 +31,7 @@ test()
ia[i] = i;
int ib[N] = {0};
- OutIter r = std::copy_n(InIter(ia), N/2, OutIter(ib));
+ OutIter r = std::copy_n(InIter(ia), UDI(N/2), OutIter(ib));
assert(base(r) == ib+N/2);
for (unsigned i = 0; i < N/2; ++i)
assert(ia[i] == ib[i]);
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
index bffcf1b63cb..6617cd0916f 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp
@@ -18,6 +18,9 @@
#include <cassert>
#include "test_iterators.h"
+#include "user_defined_integral.hpp"
+
+typedef UserDefinedIntegral<unsigned> UDI;
template <class Iter>
void
@@ -25,7 +28,7 @@ test_char()
{
const unsigned n = 4;
char ca[n] = {0};
- assert(std::fill_n(Iter(ca), n, char(1)) == std::next(Iter(ca), n));
+ assert(std::fill_n(Iter(ca), UDI(n), char(1)) == std::next(Iter(ca), n));
assert(ca[0] == 1);
assert(ca[1] == 1);
assert(ca[2] == 1);
@@ -38,7 +41,7 @@ test_int()
{
const unsigned n = 4;
int ia[n] = {0};
- assert(std::fill_n(Iter(ia), n, 1) == std::next(Iter(ia), n));
+ assert(std::fill_n(Iter(ia), UDI(n), 1) == std::next(Iter(ia), n));
assert(ia[0] == 1);
assert(ia[1] == 1);
assert(ia[2] == 1);
@@ -50,7 +53,7 @@ test_int_array()
{
const unsigned n = 4;
int ia[n] = {0};
- assert(std::fill_n(ia, n, static_cast<char>(1)) == std::next(ia, n));
+ assert(std::fill_n(ia, UDI(n), static_cast<char>(1)) == std::next(ia, n));
assert(ia[0] == 1);
assert(ia[1] == 1);
assert(ia[2] == 1);
@@ -69,7 +72,7 @@ test_int_array_struct_source()
{
const unsigned n = 4;
int ia[n] = {0};
- assert(std::fill_n(ia, n, source()) == std::next(ia, n));
+ assert(std::fill_n(ia, UDI(n), source()) == std::next(ia, n));
assert(ia[0] == 0);
assert(ia[1] == 1);
assert(ia[2] == 2);
@@ -87,7 +90,7 @@ test_struct_array()
{
const unsigned n = 4;
test1 test1a[n] = {0};
- assert(std::fill_n(test1a, n, static_cast<char>(10)) == std::next(test1a, n));
+ assert(std::fill_n(test1a, UDI(n), static_cast<char>(10)) == std::next(test1a, n));
assert(test1a[0].c == 11);
assert(test1a[1].c == 11);
assert(test1a[2].c == 11);
@@ -110,7 +113,7 @@ void
test5()
{
A a[3];
- assert(std::fill_n(&a[0], 3, A('a')) == a+3);
+ assert(std::fill_n(&a[0], UDI(3), A('a')) == a+3);
assert(a[0] == A('a'));
assert(a[1] == A('a'));
assert(a[2] == A('a'));
@@ -124,11 +127,11 @@ struct Storage
unsigned char b;
};
};
-
+
void test6()
{
Storage foo[5];
- std::fill_n(&foo[0], 5, Storage());
+ std::fill_n(&foo[0], UDI(5), Storage());
}
@@ -143,7 +146,7 @@ int main()
test_int<bidirectional_iterator<int*> >();
test_int<random_access_iterator<int*> >();
test_int<int*>();
-
+
test_int_array();
test_int_array_struct_source();
test_struct_array();
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp
index 249419169a1..a9ccaf4cd95 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp
@@ -19,6 +19,9 @@
#include <cassert>
#include "test_iterators.h"
+#include "user_defined_integral.hpp"
+
+typedef UserDefinedIntegral<unsigned> UDI;
struct gen_test
{
@@ -31,7 +34,7 @@ test()
{
const unsigned n = 4;
int ia[n] = {0};
- assert(std::generate_n(Iter(ia), n, gen_test()) == Iter(ia+n));
+ assert(std::generate_n(Iter(ia), UDI(n), gen_test()) == Iter(ia+n));
assert(ia[0] == 2);
assert(ia[1] == 2);
assert(ia[2] == 2);
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp
index b834da210d3..f7f8ee09279 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp
@@ -18,6 +18,7 @@
#include <cassert>
#include "test_iterators.h"
+#include "user_defined_integral.hpp"
template <class Iter>
void
@@ -63,6 +64,9 @@ test()
assert(std::search_n(Iter(ic), Iter(ic+sc), 2, 0) == Iter(ic));
assert(std::search_n(Iter(ic), Iter(ic+sc), 3, 0) == Iter(ic));
assert(std::search_n(Iter(ic), Iter(ic+sc), 4, 0) == Iter(ic+sc));
+
+ // Check that we properly convert the size argument to an integral.
+ std::search_n(Iter(ic), Iter(ic+sc), UserDefinedIntegral<unsigned>(0), 0);
}
int main()
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
index 6004b0e0a81..8bc6f4d26bd 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
@@ -18,6 +18,7 @@
#include <cassert>
#include "test_iterators.h"
+#include "user_defined_integral.hpp"
struct count_equal
{
@@ -29,6 +30,7 @@ struct count_equal
unsigned count_equal::count = 0;
+
template <class Iter>
void
test()
@@ -138,6 +140,10 @@ test()
assert(std::search_n(Iter(ic), Iter(ic+sc), 4, 0, count_equal()) == Iter(ic+sc));
assert(count_equal::count <= sc);
count_equal::count = 0;
+
+ // Check that we properly convert the size argument to an integral.
+ std::search_n(Iter(ic), Iter(ic+sc), UserDefinedIntegral<unsigned>(4), 0, count_equal());
+ count_equal::count = 0;
}
int main()
diff --git a/libcxx/test/support/user_defined_integral.hpp b/libcxx/test/support/user_defined_integral.hpp
new file mode 100644
index 00000000000..3b0f7a19fcf
--- /dev/null
+++ b/libcxx/test/support/user_defined_integral.hpp
@@ -0,0 +1,44 @@
+#ifndef SUPPORT_USER_DEFINED_INTEGRAL_HPP
+#define SUPPORT_USER_DEFINED_INTEGRAL_HPP
+
+template <class T>
+struct UserDefinedIntegral
+{
+ UserDefinedIntegral() : value(0) {}
+ UserDefinedIntegral(T v) : value(v) {}
+ operator T() const { return value; }
+ T value;
+};
+
+// Poison the arithmetic and comparison operations
+template <class T, class U>
+void operator+(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator-(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator*(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator/(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator==(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator!=(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator<(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator>(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator<=(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+template <class T, class U>
+void operator>=(UserDefinedIntegral<T>, UserDefinedIntegral<U>);
+
+#endif // SUPPORT_USER_DEFINED_INTEGRAL_HPP
OpenPOWER on IntegriCloud