diff options
| author | Eric Fiselier <eric@efcs.ca> | 2017-10-17 13:03:17 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2017-10-17 13:03:17 +0000 |
| commit | 1c0cedccb62480d61bc4c0c31c871f9096b4873a (patch) | |
| tree | 7f0273afe6543f92aa56aa048e3c9ed812386c9b /libcxx/test/support | |
| parent | 228340315d655373219db0d61bd48e390b9f5735 (diff) | |
| download | bcm5719-llvm-1c0cedccb62480d61bc4c0c31c871f9096b4873a.tar.gz bcm5719-llvm-1c0cedccb62480d61bc4c0c31c871f9096b4873a.zip | |
[libc++] Fix PR34898 - vector iterator constructors and assign method perform push_back instead of emplace_back.
Summary:
The constructors `vector(Iter, Iter, Alloc = Alloc{})` and `assign(Iter, Iter)` don't correctly perform EmplaceConstruction from the result of dereferencing the iterator. This results in them performing an additional and unneeded copy.
This patch addresses the issue by correctly using `emplace_back` in C++11 and newer.
There are also some bugs in our `insert` implementation, but those will be handled separately.
@mclow.lists We should probably merge this into 5.1, agreed?
Reviewers: mclow.lists, dlj, EricWF
Reviewed By: mclow.lists, EricWF
Subscribers: cfe-commits, mclow.lists
Differential Revision: https://reviews.llvm.org/D38757
llvm-svn: 315994
Diffstat (limited to 'libcxx/test/support')
| -rw-r--r-- | libcxx/test/support/container_test_types.h | 28 | ||||
| -rw-r--r-- | libcxx/test/support/emplace_constructible.h | 74 |
2 files changed, 100 insertions, 2 deletions
diff --git a/libcxx/test/support/container_test_types.h b/libcxx/test/support/container_test_types.h index 08e88f09146..b8422ec4602 100644 --- a/libcxx/test/support/container_test_types.h +++ b/libcxx/test/support/container_test_types.h @@ -234,6 +234,19 @@ inline ConstructController* getConstructController() { return &c; } +template <class ...Args> +struct ExpectConstructGuard { + ExpectConstructGuard(int N) { + auto CC = getConstructController(); + assert(!CC->unchecked()); + CC->expect<Args...>(N); + } + + ~ExpectConstructGuard() { + assert(!getConstructController()->unchecked()); + } +}; + //===----------------------------------------------------------------------===// // ContainerTestAllocator //===----------------------------------------------------------------------===// @@ -417,7 +430,12 @@ namespace std { return arg.data; } }; - + template <class T, class Alloc> + class vector; + template <class T, class Alloc> + class deque; + template <class T, class Alloc> + class list; template <class _Key, class _Value, class _Less, class _Alloc> class map; template <class _Key, class _Value, class _Less, class _Alloc> @@ -444,6 +462,13 @@ _LIBCPP_END_NAMESPACE_STD // TCT - Test container type namespace TCT { +template <class T = CopyInsertable<1>> +using vector = std::vector<T, ContainerTestAllocator<T, T> >; +template <class T = CopyInsertable<1>> +using deque = std::deque<T, ContainerTestAllocator<T, T> >; +template <class T = CopyInsertable<1>> +using list = std::list<T, ContainerTestAllocator<T, T> >; + template <class Key = CopyInsertable<1>, class Value = CopyInsertable<2>, class ValueTp = std::pair<const Key, Value> > using unordered_map = @@ -488,5 +513,4 @@ using multiset = } // end namespace TCT - #endif // SUPPORT_CONTAINER_TEST_TYPES_H diff --git a/libcxx/test/support/emplace_constructible.h b/libcxx/test/support/emplace_constructible.h new file mode 100644 index 00000000000..f2bc0ec6a36 --- /dev/null +++ b/libcxx/test/support/emplace_constructible.h @@ -0,0 +1,74 @@ +#ifndef TEST_SUPPORT_EMPLACE_CONSTRUCTIBLE_H +#define TEST_SUPPORT_EMPLACE_CONSTRUCTIBLE_H + +#include "test_macros.h" + +#if TEST_STD_VER >= 11 +template <class T> +struct EmplaceConstructible { + T value; + explicit EmplaceConstructible(T value) : value(value) {} + EmplaceConstructible(EmplaceConstructible const&) = delete; +}; + +template <class T> +struct EmplaceConstructibleAndMoveInsertable { + int copied = 0; + T value; + explicit EmplaceConstructibleAndMoveInsertable(T value) : value(value) {} + + EmplaceConstructibleAndMoveInsertable( + EmplaceConstructibleAndMoveInsertable&& Other) + : copied(Other.copied + 1), value(std::move(Other.value)) {} +}; + +template <class T> +struct EmplaceConstructibleAndMoveable { + int copied = 0; + int assigned = 0; + T value; + explicit EmplaceConstructibleAndMoveable(T value) noexcept : value(value) {} + + EmplaceConstructibleAndMoveable(EmplaceConstructibleAndMoveable&& Other) + noexcept : copied(Other.copied + 1), + value(std::move(Other.value)) {} + + EmplaceConstructibleAndMoveable& + operator=(EmplaceConstructibleAndMoveable&& Other) noexcept { + copied = Other.copied; + assigned = Other.assigned + 1; + value = std::move(Other.value); + return *this; + } +}; + +template <class T> +struct EmplaceConstructibleMoveableAndAssignable { + int copied = 0; + int assigned = 0; + T value; + explicit EmplaceConstructibleMoveableAndAssignable(T value) noexcept + : value(value) {} + + EmplaceConstructibleMoveableAndAssignable( + EmplaceConstructibleMoveableAndAssignable&& Other) noexcept + : copied(Other.copied + 1), + value(std::move(Other.value)) {} + + EmplaceConstructibleMoveableAndAssignable& + operator=(EmplaceConstructibleMoveableAndAssignable&& Other) noexcept { + copied = Other.copied; + assigned = Other.assigned + 1; + value = std::move(Other.value); + return *this; + } + + EmplaceConstructibleMoveableAndAssignable& operator=(T xvalue) { + value = std::move(xvalue); + ++assigned; + return *this; + } +}; +#endif + +#endif // TEST_SUPPORT_EMPLACE_CONSTRUCTIBLE_H |

