EricWF updated this revision to Diff 82832.
EricWF added a comment.
Use the correct patch file this time.
https://reviews.llvm.org/D28222
Files:
include/__tuple
test/libcxx/test/config.py
test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp
test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp
test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp
Index: test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// XFAIL: libcpp-no-structured-bindings
+
+#include <tuple>
+#include <array>
+#include <type_traits>
+#include <cassert>
+
+struct S { int x; };
+
+void test_decomp_user_type() {
+ {
+ S s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &s.x);
+ }
+ {
+ S const s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &s.x);
+ }
+}
+
+void test_decomp_tuple() {
+ typedef std::tuple<int> T;
+ {
+ T s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+ {
+ T const s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+}
+
+
+void test_decomp_pair() {
+ typedef std::pair<int, double> T;
+ {
+ T s{99, 42.1};
+ auto [m1, m2] = s;
+ auto& [r1, r2] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+ {
+ T const s{99, 42.1};
+ auto [m1, m2] = s;
+ auto& [r1, r2] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+}
+
+void test_decomp_array() {
+ typedef std::array<int, 3> T;
+ {
+ T s{{99, 42, -1}};
+ auto [m1, m2, m3] = s;
+ auto& [r1, r2, r3] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+ {
+ T const s{{99, 42, -1}};
+ auto [m1, m2, m3] = s;
+ auto& [r1, r2, r3] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+}
+
+int main() {
+ test_decomp_user_type();
+ test_decomp_tuple();
+ test_decomp_pair();
+ test_decomp_array();
+}
Index: test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// UNSUPPORTED: c++98, c++03
+
+#include <tuple>
+#include <array>
+#include <type_traits>
+
+template <class T, size_t Size = sizeof(std::tuple_size<T>)>
+constexpr bool is_complete(int) { static_assert(Size > 0, ""); return true; }
+template <class> constexpr bool is_complete(long) { return false; }
+template <class T> constexpr bool is_complete() { return is_complete<T>(0); }
+
+struct Dummy1 {};
+struct Dummy2 {};
+
+template <>
+class std::tuple_size<Dummy1> : public std::integral_constant<size_t, 0> {};
+
+template <class T>
+void test_complete() {
+ static_assert(is_complete<T>(), "");
+ static_assert(is_complete<const T>(), "");
+ static_assert(is_complete<volatile T>(), "");
+ static_assert(is_complete<const volatile T>(), "");
+}
+
+template <class T>
+void test_incomplete() {
+ static_assert(!is_complete<T>(), "");
+ static_assert(!is_complete<const T>(), "");
+ static_assert(!is_complete<volatile T>(), "");
+ static_assert(!is_complete<const volatile T>(), "");
+}
+
+
+int main()
+{
+ test_complete<std::tuple<> >();
+ test_complete<std::tuple<int&> >();
+ test_complete<std::tuple<int&&, int&, void*>>();
+ test_complete<std::pair<int, long> >();
+ test_complete<std::array<int, 5> >();
+ test_complete<Dummy1>();
+
+ test_incomplete<void>();
+ test_incomplete<int>();
+ test_incomplete<std::tuple<int>&>();
+ test_incomplete<Dummy2>();
+}
Index: test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// UNSUPPORTED: c++98, c++03
+
+#include <tuple>
+#include <array>
+#include <type_traits>
+
+template <class T, size_t Size = sizeof(std::tuple_size<T>)>
+constexpr bool is_complete(int) { static_assert(Size > 0, ""); return true; }
+template <class> constexpr bool is_complete(long) { return false; }
+template <class T> constexpr bool is_complete() { return is_complete<T>(0); }
+
+struct Dummy1 {};
+struct Dummy2 {};
+struct Dummy3 {};
+
+template <>
+class std::tuple_size<Dummy1> {
+public:
+ static size_t value;
+};
+
+template <>
+class std::tuple_size<Dummy2> {
+public:
+ static void value() {}
+};
+
+template <>
+class std::tuple_size<Dummy3> {};
+
+template <class T>
+void test_complete() {
+ static_assert(is_complete<T>(), "");
+ static_assert(is_complete<const T>(), "");
+ static_assert(is_complete<volatile T>(), "");
+ static_assert(is_complete<const volatile T>(), "");
+}
+
+template <class T>
+void test_incomplete() {
+ static_assert(!is_complete<T>(), "");
+ static_assert(!is_complete<const T>(), "");
+ static_assert(!is_complete<volatile T>(), "");
+ static_assert(!is_complete<const volatile T>(), "");
+}
+
+int main()
+{
+ // Test that tuple_size<const T> is not incomplete when tuple_size<T>::value
+ // is well-formed but not a constant expression.
+ {
+ // expected-error@__tuple:* 1 {{is not a constant expression}}
+ (void)std::tuple_size<const Dummy1>::value; // expected-note {{here}}
+ }
+ // Test that tuple_size<const T> is not incomplete when tuple_size<T>::value
+ // is well-formed but not convertible to size_t.
+ {
+ // expected-error@__tuple:* 1 {{value of type 'void ()' is not implicitly convertible to 'unsigned long'}}
+ (void)std::tuple_size<const Dummy2>::value; // expected-note {{here}}
+ }
+ // Test that tuple_size<const T> is incomplete when tuple_size<T>::value is
+ // ill-formed.
+ // FIXME: it would be better if tuple_size<const Dummy3> were a complete type
+ // which generated diagnostics when used.
+ {
+ (void)std::tuple_size<const Dummy3>::value;
+ // expected-error@-1 {{implicit instantiation of undefined template}}
+ }
+}
Index: test/libcxx/test/config.py
===================================================================
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -335,9 +335,13 @@
if self.get_lit_bool('has_libatomic', False):
self.config.available_features.add('libatomic')
- if '__cpp_if_constexpr' not in self.cxx.dumpMacros():
+ macros = self.cxx.dumpMacros()
+ if '__cpp_if_constexpr' not in macros:
self.config.available_features.add('libcpp-no-if-constexpr')
+ if '__cpp_structured_bindings' not in macros:
+ self.config.available_features.add('libcpp-no-structured-bindings')
+
def configure_compile_flags(self):
no_default_flags = self.get_lit_bool('no_default_flags', False)
if not no_default_flags:
Index: include/__tuple
===================================================================
--- include/__tuple
+++ include/__tuple
@@ -24,30 +24,26 @@
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size;
-struct __empty_tuple_size_base {};
-
-template <class _Tp, class = void>
-struct __tuple_size_base_type {
- typedef __empty_tuple_size_base type;
-};
-
-template <class _Tp>
-struct __tuple_size_base_type<_Tp, typename __void_t<decltype(tuple_size<_Tp>::value)>::type>
-{
- typedef integral_constant<size_t, tuple_size<_Tp>::value> type;
-};
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Tp, class>
+using __enable_if_tuple_size_imp = _Tp;
template <class _Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp>
- : public __tuple_size_base_type<_Tp>::type {};
+class _LIBCPP_TYPE_VIS_ONLY tuple_size<__enable_if_tuple_size_imp<const _Tp, decltype(tuple_size<typename remove_cv<_Tp>::type>::value)>>
+ : public integral_constant<size_t, tuple_size<_Tp>::value> {};
template <class _Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp>
- : public __tuple_size_base_type<_Tp>::type {};
+class _LIBCPP_TYPE_VIS_ONLY tuple_size<__enable_if_tuple_size_imp<volatile _Tp, decltype(tuple_size<typename remove_cv<_Tp>::type>::value)>>
+ : public integral_constant<size_t, tuple_size<_Tp>::value> {};
template <class _Tp>
-class _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp>
- : public __tuple_size_base_type<_Tp>::type {};
+class _LIBCPP_TYPE_VIS_ONLY tuple_size<__enable_if_tuple_size_imp<const volatile _Tp, decltype(tuple_size<typename remove_cv<_Tp>::type>::value)>>
+ : public integral_constant<size_t, tuple_size<_Tp>::value> {};
+#else
+template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp> : tuple_size<_Tp> {};
+template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp> : tuple_size<_Tp> {};
+template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp> : tuple_size<_Tp> {};
+#endif
template <size_t _Ip, class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_element;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits