Author: ericwf Date: Tue Dec 27 23:53:01 2016 New Revision: 290655 URL: http://llvm.org/viewvc/llvm-project?rev=290655&view=rev Log: Add tests for unordered container tests and std::string
Added: libcxx/trunk/test/libcxx/debug/containers/ libcxx/trunk/test/libcxx/debug/containers/db_string.pass.cpp libcxx/trunk/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp libcxx/trunk/test/support/debug_mode_helper.h Modified: libcxx/trunk/include/__hash_table libcxx/trunk/include/string libcxx/trunk/include/unordered_map libcxx/trunk/test/libcxx/test/config.py Modified: libcxx/trunk/include/__hash_table URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__hash_table?rev=290655&r1=290654&r2=290655&view=diff ============================================================================== --- libcxx/trunk/include/__hash_table (original) +++ libcxx/trunk/include/__hash_table Tue Dec 27 23:53:01 2016 @@ -1181,7 +1181,7 @@ public: void swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 - _NOEXCEPT_( + _NOEXCEPT_DEBUG_( __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || __is_nothrow_swappable<__pointer_allocator>::value) @@ -1189,7 +1189,7 @@ public: || __is_nothrow_swappable<__node_allocator>::value) ); #else - _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value); + _NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value); #endif _LIBCPP_INLINE_VISIBILITY @@ -2408,15 +2408,15 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc> --size(); #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) + for (__i_node** __dp = __c->end_; __dp != __c->beg_; ) { - --__p; - iterator* __i = static_cast<iterator*>((*__p)->__i_); + --__dp; + iterator* __i = static_cast<iterator*>((*__dp)->__i_); if (__i->__node_ == __cn) { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); + (*__dp)->__c_ = nullptr; + if (--__c->end_ != __dp) + memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*)); } } __get_db()->unlock(); @@ -2524,7 +2524,7 @@ template <class _Tp, class _Hash, class void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 - _NOEXCEPT_( + _NOEXCEPT_DEBUG_( __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || __is_nothrow_swappable<__pointer_allocator>::value) @@ -2532,9 +2532,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc> || __is_nothrow_swappable<__node_allocator>::value) ) #else - _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value) + _NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value) #endif { + _LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value || + this->__node_alloc() == __u.__node_alloc(), + "list::swap: Either propagate_on_container_swap must be true" + " or the allocators must compare equal"); { __node_pointer_pointer __npp = __bucket_list_.release(); __bucket_list_.reset(__u.__bucket_list_.release()); Modified: libcxx/trunk/include/string URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=290655&r1=290654&r2=290655&view=diff ============================================================================== --- libcxx/trunk/include/string (original) +++ libcxx/trunk/include/string Tue Dec 27 23:53:01 2016 @@ -1105,9 +1105,9 @@ public: _LIBCPP_INLINE_VISIBILITY void swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 - _NOEXCEPT; + _NOEXCEPT_DEBUG; #else - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + _NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value); #endif @@ -2996,9 +2996,9 @@ inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 - _NOEXCEPT + _NOEXCEPT_DEBUG #else - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || + _NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value) #endif { @@ -3009,6 +3009,10 @@ basic_string<_CharT, _Traits, _Allocator __get_db()->__invalidate_all(&__str); __get_db()->swap(this, &__str); #endif + _LIBCPP_ASSERT( + __alloc_traits::propagate_on_container_swap::value || + __alloc_traits::is_always_equal::value || + __alloc() == __str.__alloc(), "swapping non-equal allocators"); _VSTD::swap(__r_.first(), __str.__r_.first()); __swap_allocator(__alloc(), __str.__alloc()); } Modified: libcxx/trunk/include/unordered_map URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/unordered_map?rev=290655&r1=290654&r2=290655&view=diff ============================================================================== --- libcxx/trunk/include/unordered_map (original) +++ libcxx/trunk/include/unordered_map Tue Dec 27 23:53:01 2016 @@ -1099,7 +1099,7 @@ public: _LIBCPP_INLINE_VISIBILITY void swap(unordered_map& __u) _NOEXCEPT_(__is_nothrow_swappable<__table>::value) - {__table_.swap(__u.__table_);} + { __table_.swap(__u.__table_);} _LIBCPP_INLINE_VISIBILITY hasher hash_function() const Added: libcxx/trunk/test/libcxx/debug/containers/db_string.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/debug/containers/db_string.pass.cpp?rev=290655&view=auto ============================================================================== --- libcxx/trunk/test/libcxx/debug/containers/db_string.pass.cpp (added) +++ libcxx/trunk/test/libcxx/debug/containers/db_string.pass.cpp Tue Dec 27 23:53:01 2016 @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++14 +// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr + +// test container debugging + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS +#include <string> +#include <vector> + +#include "test_macros.h" +#include "debug_mode_helper.h" + +using namespace IteratorDebugChecks; + +typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> StringType; + +template <class Container = StringType, ContainerType CT = CT_String> +struct StringContainerChecks : BasicContainerChecks<Container, CT> { + using Base = BasicContainerChecks<Container, CT_String>; + using value_type = typename Container::value_type; + using allocator_type = typename Container::allocator_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + + using Base::makeContainer; + using Base::makeValueType; + +public: + static void run() { + Base::run_iterator_tests(); + // FIXME: get these passing + // Base::run_allocator_aware_tests(); + try { + for (int N : {3, 128}) { + FrontOnEmptyContainer(N); + BackOnEmptyContainer(N); + PopBack(N); + } + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + +private: + static void BackOnEmptyContainer(int N) { + CHECKPOINT("testing back on empty"); + Container C = makeContainer(N); + Container const& CC = C; + iterator it = --C.end(); + (void)C.back(); + (void)CC.back(); + C.pop_back(); + CHECK_DEBUG_THROWS( C.erase(it) ); + C.clear(); + CHECK_DEBUG_THROWS( C.back() ); + CHECK_DEBUG_THROWS( CC.back() ); + } + + static void FrontOnEmptyContainer(int N) { + CHECKPOINT("testing front on empty"); + Container C = makeContainer(N); + Container const& CC = C; + (void)C.front(); + (void)CC.front(); + C.clear(); + CHECK_DEBUG_THROWS( C.front() ); + CHECK_DEBUG_THROWS( CC.front() ); + } + + static void PopBack(int N) { + CHECKPOINT("testing pop_back() invalidation"); + Container C1 = makeContainer(N); + iterator it1 = C1.end(); + --it1; + C1.pop_back(); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + C1.erase(C1.begin(), C1.end()); + assert(C1.size() == 0); + CHECK_DEBUG_THROWS( C1.pop_back() ); + } +}; + +int main() +{ + StringContainerChecks<>::run(); +} Added: libcxx/trunk/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp?rev=290655&view=auto ============================================================================== --- libcxx/trunk/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp (added) +++ libcxx/trunk/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp Tue Dec 27 23:53:01 2016 @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++14 +// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr + +// test container debugging + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <cassert> +#include "debug_mode_helper.h" + +using namespace IteratorDebugChecks; + +template <class Container, ContainerType CT> +struct UnorderedContainerChecks : BasicContainerChecks<Container, CT> { + using Base = BasicContainerChecks<Container, CT>; + using value_type = typename Container::value_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using traits = std::iterator_traits<iterator>; + using category = typename traits::iterator_category; + + using Base::makeContainer; +public: + static void run() { + Base::run(); + try { + // FIXME + } catch (...) { + assert(false && "uncaught debug exception"); + } + } +private: + +}; + +int main() +{ + using SetAlloc = test_allocator<int>; + using MapAlloc = test_allocator<std::pair<const int, int>>; + { + UnorderedContainerChecks< + std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, MapAlloc>, + CT_UnorderedMap>::run(); + UnorderedContainerChecks< + std::unordered_set<int, std::hash<int>, std::equal_to<int>, SetAlloc>, + CT_UnorderedSet>::run(); + UnorderedContainerChecks< + std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, MapAlloc>, + CT_UnorderedMultiMap>::run(); + UnorderedContainerChecks< + std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, SetAlloc>, + CT_UnorderedMultiSet>::run(); + } +} Modified: libcxx/trunk/test/libcxx/test/config.py URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/test/config.py?rev=290655&r1=290654&r2=290655&view=diff ============================================================================== --- libcxx/trunk/test/libcxx/test/config.py (original) +++ libcxx/trunk/test/libcxx/test/config.py Tue Dec 27 23:53:01 2016 @@ -335,6 +335,9 @@ class Configuration(object): if self.get_lit_bool('has_libatomic', False): self.config.available_features.add('libatomic') + if '__cpp_if_constexpr' not in self.cxx.dumpMacros(): + self.config.available_features.add('libcpp-no-if-constexpr') + def configure_compile_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) if not no_default_flags: Added: libcxx/trunk/test/support/debug_mode_helper.h URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/debug_mode_helper.h?rev=290655&view=auto ============================================================================== --- libcxx/trunk/test/support/debug_mode_helper.h (added) +++ libcxx/trunk/test/support/debug_mode_helper.h Tue Dec 27 23:53:01 2016 @@ -0,0 +1,382 @@ +//===----------------------------------------------------------------------===// +// +// 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 TEST_SUPPORT_DEBUG_MODE_HELPER_H +#define TEST_SUPPORT_DEBUG_MODE_HELPER_H + +#ifndef _LIBCPP_DEBUG +#error _LIBCPP_DEBUG must be defined before including this header +#endif +#ifndef _LIBCPP_DEBUG_USE_EXCEPTIONS +#error _LIBCPP_DEBUG_USE_EXCEPTIONS must be defined before including this header +#endif + +#include <ciso646> +#ifndef _LIBCPP_VERSION +#error This header may only be used for libc++ tests" +#endif + +#include <__debug> +#include <utility> +#include <cstddef> +#include <cstdlib> +#include <cassert> + +#include "test_macros.h" +#include "assert_checkpoint.h" +#include "test_allocator.h" + +// These test make use of 'if constexpr'. +#if TEST_STD_VER <= 14 +#error This header may only be used in C++17 and greater +#endif +#ifdef TEST_HAS_NO_EXCEPTIONS +#error These tests require exceptions +#endif + +#ifndef __cpp_if_constexpr +#error These tests require if constexpr +#endif + +/// Assert that the specified expression throws a libc++ debug exception. +#define CHECK_DEBUG_THROWS(...) assert((CheckDebugThrows( [&]() { __VA_ARGS__; } ))) + +template <class Func> +inline bool CheckDebugThrows(Func&& func) { + try { + func(); + } catch (std::__libcpp_debug_exception const&) { + return true; + } + return false; +} + +namespace IteratorDebugChecks { + +enum ContainerType { + CT_None, + CT_String, + CT_Vector, + CT_VectorBool, + CT_List, + CT_Deque, + CT_ForwardList, + CT_Map, + CT_Set, + CT_MultiMap, + CT_MultiSet, + CT_UnorderedMap, + CT_UnorderedSet, + CT_UnorderedMultiMap, + CT_UnorderedMultiSet +}; + +constexpr bool isSequential(ContainerType CT) { + return CT_Vector >= CT && CT_ForwardList <= CT; +} + +constexpr bool isAssociative(ContainerType CT) { + return CT_Map >= CT && CT_MultiSet <= CT; +} + +constexpr bool isUnordered(ContainerType CT) { + return CT_UnorderedMap >= CT && CT_UnorderedMultiSet <= CT; +} + +constexpr bool isSet(ContainerType CT) { + return CT == CT_Set + || CT == CT_MultiSet + || CT == CT_UnorderedSet + || CT == CT_UnorderedMultiSet; +} + +constexpr bool isMap(ContainerType CT) { + return CT == CT_Map + || CT == CT_MultiMap + || CT == CT_UnorderedMap + || CT == CT_UnorderedMultiMap; +} + +constexpr bool isMulti(ContainerType CT) { + return CT == CT_MultiMap + || CT == CT_MultiSet + || CT == CT_UnorderedMultiMap + || CT == CT_UnorderedMultiSet; +} + +template <class Container, class ValueType = typename Container::value_type> +struct ContainerDebugHelper { + static_assert(std::is_constructible<ValueType, int>::value, + "must be constructible from int"); + + static ValueType makeValueType(int val = 0, int = 0) { + return ValueType(val); + } +}; + +template <class Container> +struct ContainerDebugHelper<Container, char> { + static char makeValueType(int = 0, int = 0) { + return 'A'; + } +}; + +template <class Container, class Key, class Value> +struct ContainerDebugHelper<Container, std::pair<const Key, Value> > { + using ValueType = std::pair<const Key, Value>; + static_assert(std::is_constructible<Key, int>::value, + "must be constructible from int"); + static_assert(std::is_constructible<Value, int>::value, + "must be constructible from int"); + + static ValueType makeValueType(int key = 0, int val = 0) { + return ValueType(key, val); + } +}; + +template <class Container, ContainerType CT, + class Helper = ContainerDebugHelper<Container> > +struct BasicContainerChecks { + using value_type = typename Container::value_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using allocator_type = typename Container::allocator_type; + using traits = std::iterator_traits<iterator>; + using category = typename traits::iterator_category; + + static_assert(std::is_same<test_allocator<value_type>, allocator_type>::value, + "the container must use a test allocator"); + + static constexpr bool IsBiDir = + std::is_convertible<category, std::bidirectional_iterator_tag>::value; + +public: + static void run() { + run_iterator_tests(); + run_container_tests(); + run_allocator_aware_tests(); + } + + static void run_iterator_tests() { + try { + TestNullIterators<iterator>(); + TestNullIterators<const_iterator>(); + if constexpr (IsBiDir) { DecrementBegin(); } + IncrementEnd(); + DerefEndIterator(); + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + + static void run_container_tests() { + try { + CopyInvalidatesIterators(); + MoveInvalidatesIterators(); + if constexpr (CT != CT_ForwardList) { + EraseIter(); + EraseIterIter(); + } + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + + static void run_allocator_aware_tests() { + try { + SwapNonEqualAllocators(); + if constexpr (CT != CT_ForwardList) { + SwapInvalidatesIterators(); // FIXME: This should work + } + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + + static Container makeContainer(int size, allocator_type A = allocator_type()) { + Container C(A); + if constexpr (CT == CT_ForwardList) { + for (int i = 0; i < size; ++i) + C.insert_after(C.before_begin(), Helper::makeValueType(i)); + } else { + for (int i = 0; i < size; ++i) + C.insert(C.end(), Helper::makeValueType(i)); + assert(C.size() == static_cast<std::size_t>(size)); + } + return C; + } + + static value_type makeValueType(int value) { + return Helper::makeValueType(value); + } + +private: + // Iterator tests + template <class Iter> + static void TestNullIterators() { + CHECKPOINT("testing null iterator"); + Iter it; + CHECK_DEBUG_THROWS( ++it ); + CHECK_DEBUG_THROWS( it++ ); + CHECK_DEBUG_THROWS( *it ); + if constexpr (CT != CT_VectorBool) { + CHECK_DEBUG_THROWS( it.operator->() ); + } + if constexpr (IsBiDir) { + CHECK_DEBUG_THROWS( --it ); + CHECK_DEBUG_THROWS( it-- ); + } + } + + static void DecrementBegin() { + CHECKPOINT("testing decrement on begin"); + Container C = makeContainer(1); + iterator i = C.end(); + const_iterator ci = C.cend(); + --i; + --ci; + assert(i == C.begin()); + CHECK_DEBUG_THROWS( --i ); + CHECK_DEBUG_THROWS( i-- ); + CHECK_DEBUG_THROWS( --ci ); + CHECK_DEBUG_THROWS( ci-- ); + } + + static void IncrementEnd() { + CHECKPOINT("testing increment on end"); + Container C = makeContainer(1); + iterator i = C.begin(); + const_iterator ci = C.begin(); + ++i; + ++ci; + assert(i == C.end()); + CHECK_DEBUG_THROWS( ++i ); + CHECK_DEBUG_THROWS( i++ ); + CHECK_DEBUG_THROWS( ++ci ); + CHECK_DEBUG_THROWS( ci++ ); + } + + static void DerefEndIterator() { + CHECKPOINT("testing deref end iterator"); + Container C = makeContainer(1); + iterator i = C.begin(); + const_iterator ci = C.cbegin(); + (void)*i; (void)*ci; + if constexpr (CT != CT_VectorBool) { + i.operator->(); + ci.operator->(); + } + ++i; ++ci; + assert(i == C.end()); + CHECK_DEBUG_THROWS( *i ); + CHECK_DEBUG_THROWS( *ci ); + if constexpr (CT != CT_VectorBool) { + CHECK_DEBUG_THROWS( i.operator->() ); + CHECK_DEBUG_THROWS( ci.operator->() ); + } + } + + // Container tests + static void CopyInvalidatesIterators() { + CHECKPOINT("copy invalidates iterators"); + Container C1 = makeContainer(3); + iterator i = C1.begin(); + Container C2 = C1; + if constexpr (CT == CT_ForwardList) { + iterator i_next = i; + ++i_next; + (void)*i_next; + CHECK_DEBUG_THROWS( C2.erase_after(i) ); + C1.erase_after(i); + CHECK_DEBUG_THROWS( *i_next ); + } else { + CHECK_DEBUG_THROWS( C2.erase(i) ); + (void)*i; + C1.erase(i); + CHECK_DEBUG_THROWS( *i ); + } + } + + static void MoveInvalidatesIterators() { + CHECKPOINT("copy move invalidates iterators"); + Container C1 = makeContainer(3); + iterator i = C1.begin(); + Container C2 = std::move(C1); + (void) *i; + if constexpr (CT == CT_ForwardList) { + CHECK_DEBUG_THROWS( C1.erase_after(i) ); + C2.erase_after(i); + } else { + CHECK_DEBUG_THROWS( C1.erase(i) ); + C2.erase(i); + CHECK_DEBUG_THROWS(*i); + } + } + + static void EraseIter() { + CHECKPOINT("testing erase invalidation"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + iterator it1_next = it1; + ++it1_next; + Container C2 = C1; + CHECK_DEBUG_THROWS( C2.erase(it1) ); // wrong container + CHECK_DEBUG_THROWS( C2.erase(C2.end()) ); // erase with end + C1.erase(it1_next); + CHECK_DEBUG_THROWS( C1.erase(it1_next) ); // invalidated iterator + C1.erase(it1); + CHECK_DEBUG_THROWS( C1.erase(it1) ); // invalidated iterator + } + + static void EraseIterIter() { + CHECKPOINT("testing erase iter iter invalidation"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + iterator it1_next = it1; + ++it1_next; + Container C2 = C1; + iterator it2 = C2.begin(); + iterator it2_next = it2; + ++it2_next; + CHECK_DEBUG_THROWS( C2.erase(it1, it1_next) ); // begin from wrong container + CHECK_DEBUG_THROWS( C2.erase(it1, it2_next) ); // end from wrong container + CHECK_DEBUG_THROWS( C2.erase(it2, it1_next) ); // both from wrong container + C2.erase(it2, it2_next); + } + + // Allocator aware tests + static void SwapInvalidatesIterators() { + CHECKPOINT("testing swap invalidates iterators"); + Container C1 = makeContainer(3); + Container C2 = makeContainer(3); + iterator it1 = C1.begin(); + iterator it2 = C2.begin(); + swap(C1, C2); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + C1.erase(it2); + //C2.erase(it1); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + } + + static void SwapNonEqualAllocators() { + CHECKPOINT("testing swap with non-equal allocators"); + Container C1 = makeContainer(3, allocator_type(1)); + Container C2 = makeContainer(1, allocator_type(2)); + Container C3 = makeContainer(2, allocator_type(2)); + swap(C2, C3); + CHECK_DEBUG_THROWS( swap(C1, C2) ); + } + +private: + BasicContainerChecks() = delete; +}; + +} // namespace IteratorDebugChecks + +#endif // TEST_SUPPORT_DEBUG_MODE_HELPER_H _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits