diff options
author | Eric Fiselier <eric@efcs.ca> | 2014-07-24 18:48:34 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2014-07-24 18:48:34 +0000 |
commit | 567bb79bf2f414bd93162383b368985580725b13 (patch) | |
tree | 57beb701f61e1642f39fa3ad4fed77c3ac79d169 /libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr | |
parent | d1854f9cb1ff0ab7ebd73a438b5757ef5f98005d (diff) | |
download | bcm5719-llvm-567bb79bf2f414bd93162383b368985580725b13.tar.gz bcm5719-llvm-567bb79bf2f414bd93162383b368985580725b13.zip |
D4451: Fix copy/move issues casude by __tuple_leafs's converting constructor
llvm-svn: 213888
Diffstat (limited to 'libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr')
-rw-r--r-- | libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp | 51 | ||||
-rw-r--r-- | libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp | 20 |
2 files changed, 71 insertions, 0 deletions
diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp index 04cb3d5f7a3..ca53cd3c519 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp @@ -17,6 +17,40 @@ #include <string> #include <cassert> + +template <class ...> +struct never { + enum { value = 0 }; +}; + +struct NoValueCtor +{ + NoValueCtor() : id(++count) {} + NoValueCtor(NoValueCtor const & other) : id(other.id) { ++count; } + + // The constexpr is required to make is_constructible instantiate this template. + // The explicit is needed to test-around a similar bug with is_convertible. + template <class T> + constexpr explicit NoValueCtor(T) + { static_assert(never<T>::value, "This should not be instantiated"); } + + static int count; + int id; +}; + +int NoValueCtor::count = 0; + + +struct NoValueCtorEmpty +{ + NoValueCtorEmpty() {} + NoValueCtorEmpty(NoValueCtorEmpty const &) {} + + template <class T> + constexpr explicit NoValueCtorEmpty(T) + { static_assert(never<T>::value, "This should not be instantiated"); } +}; + int main() { { @@ -56,6 +90,23 @@ int main() assert(std::get<1>(t) == nullptr); assert(std::get<2>(t) == "text"); } + // __tuple_leaf<T> uses is_constructible<T, U> to disable its explicit converting + // constructor overload __tuple_leaf(U &&). Evaluating is_constructible can cause a compile error. + // This overload is evaluated when __tuple_leafs copy or move ctor is called. + // This checks that is_constructible is not evaluated when U == __tuple_leaf. + { + std::tuple<int, NoValueCtor, int, int> t(1, NoValueCtor(), 2, 3); + assert(std::get<0>(t) == 1); + assert(std::get<1>(t).id == 1); + assert(std::get<2>(t) == 2); + assert(std::get<3>(t) == 3); + } + { + std::tuple<int, NoValueCtorEmpty, int, int> t(1, NoValueCtorEmpty(), 2, 3); + assert(std::get<0>(t) == 1); + assert(std::get<2>(t) == 2); + assert(std::get<3>(t) == 3); + } // extensions { std::tuple<int, char*, std::string> t(2); diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp index 41e4b660760..8dc7d21ec28 100644 --- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp +++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp @@ -18,6 +18,18 @@ #include "../MoveOnly.h" +struct ConstructsWithTupleLeaf +{ + ConstructsWithTupleLeaf() {} + + ConstructsWithTupleLeaf(ConstructsWithTupleLeaf const &) { assert(false); } + ConstructsWithTupleLeaf(ConstructsWithTupleLeaf &&) {} + + template <class T> + ConstructsWithTupleLeaf(T t) + { assert(false); } +}; + int main() { { @@ -46,4 +58,12 @@ int main() assert(std::get<1>(t) == 1); assert(std::get<2>(t) == 2); } + // A bug in tuple caused __tuple_leaf to use its explicit converting constructor + // as its move constructor. This tests that ConstructsWithTupleLeaf is not called + // (w/ __tuple_leaf) + { + typedef std::tuple<ConstructsWithTupleLeaf> d_t; + d_t d((ConstructsWithTupleLeaf())); + d_t d2(static_cast<d_t &&>(d)); + } } |