db_sequence_container_iterators.pass.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // UNSUPPORTED: c++98, c++03, c++11, c++14
  9. // UNSUPPORTED: windows
  10. // UNSUPPORTED: libcpp-no-if-constexpr
  11. // MODULES_DEFINES: _LIBCPP_DEBUG=1
  12. // Can't test the system lib because this test enables debug mode
  13. // UNSUPPORTED: with_system_cxx_lib
  14. // test container debugging
  15. #define _LIBCPP_DEBUG 1
  16. #include <forward_list>
  17. #include <list>
  18. #include <vector>
  19. #include <deque>
  20. #include "container_debug_tests.hpp"
  21. #include "test_macros.h"
  22. #include "debug_mode_helper.h"
  23. using namespace IteratorDebugChecks;
  24. template <class Container, ContainerType CT>
  25. struct SequenceContainerChecks : BasicContainerChecks<Container, CT> {
  26. using Base = BasicContainerChecks<Container, CT>;
  27. using value_type = typename Container::value_type;
  28. using allocator_type = typename Container::allocator_type;
  29. using iterator = typename Container::iterator;
  30. using const_iterator = typename Container::const_iterator;
  31. using Base::makeContainer;
  32. using Base::makeValueType;
  33. public:
  34. static void run() {
  35. Base::run();
  36. SanityTest();
  37. FrontOnEmptyContainer();
  38. if constexpr(CT != CT_ForwardList) {
  39. AssignInvalidates();
  40. BackOnEmptyContainer();
  41. InsertIterValue();
  42. InsertIterSizeValue();
  43. InsertIterIterIter();
  44. EmplaceIterValue();
  45. EraseIterIter();
  46. }
  47. else {
  48. SpliceFirstElemAfter();
  49. }
  50. if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) {
  51. PopBack();
  52. }
  53. if constexpr (CT == CT_List || CT == CT_Deque) {
  54. PopFront(); // FIXME: Run with forward list as well
  55. }
  56. if constexpr (CT == CT_List || CT == CT_ForwardList) {
  57. RemoveFirstElem();
  58. }
  59. if constexpr (CT == CT_List) {
  60. SpliceFirstElem();
  61. SpliceSameContainer();
  62. }
  63. }
  64. private:
  65. static void SanityTest() {
  66. CHECKPOINT("sanity test");
  67. Container C = {1, 1, 1, 1};
  68. ::DoNotOptimize(&C);
  69. }
  70. static void RemoveFirstElem() {
  71. // See llvm.org/PR35564
  72. CHECKPOINT("remove(<first-elem>)");
  73. {
  74. Container C = makeContainer(1);
  75. auto FirstVal = *(C.begin());
  76. C.remove(FirstVal);
  77. assert(C.empty());
  78. }
  79. {
  80. Container C = {1, 1, 1, 1};
  81. auto FirstVal = *(C.begin());
  82. C.remove(FirstVal);
  83. assert(C.empty());
  84. }
  85. }
  86. static void SpliceFirstElem() {
  87. // See llvm.org/PR35564
  88. CHECKPOINT("splice(<first-elem>)");
  89. {
  90. Container C = makeContainer(1);
  91. Container C2;
  92. C2.splice(C2.end(), C, C.begin(), ++C.begin());
  93. }
  94. {
  95. Container C = makeContainer(1);
  96. Container C2;
  97. C2.splice(C2.end(), C, C.begin());
  98. }
  99. }
  100. static void SpliceSameContainer() {
  101. CHECKPOINT("splice(<same-container>)");
  102. Container C = {1, 1};
  103. C.splice(C.end(), C, C.begin());
  104. }
  105. static void SpliceFirstElemAfter() {
  106. // See llvm.org/PR35564
  107. CHECKPOINT("splice(<first-elem>)");
  108. {
  109. Container C = makeContainer(1);
  110. Container C2;
  111. C2.splice_after(C2.begin(), C, C.begin(), ++C.begin());
  112. }
  113. {
  114. Container C = makeContainer(1);
  115. Container C2;
  116. C2.splice_after(C2.begin(), C, C.begin());
  117. }
  118. }
  119. static void AssignInvalidates() {
  120. CHECKPOINT("assign(Size, Value)");
  121. Container C(allocator_type{});
  122. iterator it1, it2, it3;
  123. auto reset = [&]() {
  124. C = makeContainer(3);
  125. it1 = C.begin();
  126. it2 = ++C.begin();
  127. it3 = C.end();
  128. };
  129. auto check = [&]() {
  130. EXPECT_DEATH( C.erase(it1) );
  131. EXPECT_DEATH( C.erase(it2) );
  132. EXPECT_DEATH( C.erase(it3, C.end()) );
  133. };
  134. reset();
  135. C.assign(2, makeValueType(4));
  136. check();
  137. reset();
  138. CHECKPOINT("assign(Iter, Iter)");
  139. std::vector<value_type> V = {
  140. makeValueType(1),
  141. makeValueType(2),
  142. makeValueType(3)
  143. };
  144. C.assign(V.begin(), V.end());
  145. check();
  146. reset();
  147. CHECKPOINT("assign(initializer_list)");
  148. C.assign({makeValueType(1), makeValueType(2), makeValueType(3)});
  149. check();
  150. }
  151. static void BackOnEmptyContainer() {
  152. CHECKPOINT("testing back on empty");
  153. Container C = makeContainer(1);
  154. Container const& CC = C;
  155. (void)C.back();
  156. (void)CC.back();
  157. C.clear();
  158. EXPECT_DEATH( C.back() );
  159. EXPECT_DEATH( CC.back() );
  160. }
  161. static void FrontOnEmptyContainer() {
  162. CHECKPOINT("testing front on empty");
  163. Container C = makeContainer(1);
  164. Container const& CC = C;
  165. (void)C.front();
  166. (void)CC.front();
  167. C.clear();
  168. EXPECT_DEATH( C.front() );
  169. EXPECT_DEATH( CC.front() );
  170. }
  171. static void EraseIterIter() {
  172. CHECKPOINT("testing erase iter iter invalidation");
  173. Container C1 = makeContainer(3);
  174. iterator it1 = C1.begin();
  175. iterator it1_next = ++C1.begin();
  176. iterator it1_after_next = ++C1.begin();
  177. ++it1_after_next;
  178. iterator it1_back = --C1.end();
  179. assert(it1_next != it1_back);
  180. if (CT == CT_Vector) {
  181. EXPECT_DEATH( C1.erase(it1_next, it1) ); // bad range
  182. }
  183. C1.erase(it1, it1_after_next);
  184. EXPECT_DEATH( C1.erase(it1) );
  185. EXPECT_DEATH( C1.erase(it1_next) );
  186. if (CT == CT_List) {
  187. C1.erase(it1_back);
  188. } else {
  189. EXPECT_DEATH( C1.erase(it1_back) );
  190. }
  191. }
  192. static void PopBack() {
  193. CHECKPOINT("testing pop_back() invalidation");
  194. Container C1 = makeContainer(2);
  195. iterator it1 = C1.end();
  196. --it1;
  197. C1.pop_back();
  198. EXPECT_DEATH( C1.erase(it1) );
  199. C1.erase(C1.begin());
  200. assert(C1.size() == 0);
  201. EXPECT_DEATH( C1.pop_back() );
  202. }
  203. static void PopFront() {
  204. CHECKPOINT("testing pop_front() invalidation");
  205. Container C1 = makeContainer(2);
  206. iterator it1 = C1.begin();
  207. C1.pop_front();
  208. EXPECT_DEATH( C1.erase(it1) );
  209. C1.erase(C1.begin());
  210. assert(C1.size() == 0);
  211. EXPECT_DEATH( C1.pop_front() );
  212. }
  213. static void InsertIterValue() {
  214. CHECKPOINT("testing insert(iter, value)");
  215. Container C1 = makeContainer(2);
  216. iterator it1 = C1.begin();
  217. iterator it1_next = it1;
  218. ++it1_next;
  219. Container C2 = C1;
  220. const value_type value = makeValueType(3);
  221. value_type rvalue = makeValueType(3);
  222. EXPECT_DEATH( C2.insert(it1, value) ); // wrong container
  223. EXPECT_DEATH( C2.insert(it1, std::move(rvalue)) ); // wrong container
  224. C1.insert(it1_next, value);
  225. if (CT == CT_List) {
  226. C1.insert(it1_next, value);
  227. C1.insert(it1, value);
  228. C1.insert(it1_next, std::move(rvalue));
  229. C1.insert(it1, std::move(rvalue));
  230. } else {
  231. EXPECT_DEATH( C1.insert(it1_next, value) ); // invalidated iterator
  232. EXPECT_DEATH( C1.insert(it1, value) ); // invalidated iterator
  233. EXPECT_DEATH( C1.insert(it1_next, std::move(rvalue)) ); // invalidated iterator
  234. EXPECT_DEATH( C1.insert(it1, std::move(rvalue)) ); // invalidated iterator
  235. }
  236. }
  237. static void EmplaceIterValue() {
  238. CHECKPOINT("testing emplace(iter, value)");
  239. Container C1 = makeContainer(2);
  240. iterator it1 = C1.begin();
  241. iterator it1_next = it1;
  242. ++it1_next;
  243. Container C2 = C1;
  244. const value_type value = makeValueType(3);
  245. EXPECT_DEATH( C2.emplace(it1, value) ); // wrong container
  246. EXPECT_DEATH( C2.emplace(it1, makeValueType(4)) ); // wrong container
  247. C1.emplace(it1_next, value);
  248. if (CT == CT_List) {
  249. C1.emplace(it1_next, value);
  250. C1.emplace(it1, value);
  251. } else {
  252. EXPECT_DEATH( C1.emplace(it1_next, value) ); // invalidated iterator
  253. EXPECT_DEATH( C1.emplace(it1, value) ); // invalidated iterator
  254. }
  255. }
  256. static void InsertIterSizeValue() {
  257. CHECKPOINT("testing insert(iter, size, value)");
  258. Container C1 = makeContainer(2);
  259. iterator it1 = C1.begin();
  260. iterator it1_next = it1;
  261. ++it1_next;
  262. Container C2 = C1;
  263. const value_type value = makeValueType(3);
  264. EXPECT_DEATH( C2.insert(it1, 1, value) ); // wrong container
  265. C1.insert(it1_next, 2, value);
  266. if (CT == CT_List) {
  267. C1.insert(it1_next, 3, value);
  268. C1.insert(it1, 1, value);
  269. } else {
  270. EXPECT_DEATH( C1.insert(it1_next, 1, value) ); // invalidated iterator
  271. EXPECT_DEATH( C1.insert(it1, 1, value) ); // invalidated iterator
  272. }
  273. }
  274. static void InsertIterIterIter() {
  275. CHECKPOINT("testing insert(iter, iter, iter)");
  276. Container C1 = makeContainer(2);
  277. iterator it1 = C1.begin();
  278. iterator it1_next = it1;
  279. ++it1_next;
  280. Container C2 = C1;
  281. std::vector<value_type> V = {
  282. makeValueType(1),
  283. makeValueType(2),
  284. makeValueType(3)
  285. };
  286. EXPECT_DEATH( C2.insert(it1, V.begin(), V.end()) ); // wrong container
  287. C1.insert(it1_next, V.begin(), V.end());
  288. if (CT == CT_List) {
  289. C1.insert(it1_next, V.begin(), V.end());
  290. C1.insert(it1, V.begin(), V.end());
  291. } else {
  292. EXPECT_DEATH( C1.insert(it1_next, V.begin(), V.end()) ); // invalidated iterator
  293. EXPECT_DEATH( C1.insert(it1, V.begin(), V.end()) ); // invalidated iterator
  294. }
  295. }
  296. };
  297. int main(int, char**)
  298. {
  299. using Alloc = test_allocator<int>;
  300. {
  301. SequenceContainerChecks<std::list<int, Alloc>, CT_List>::run();
  302. SequenceContainerChecks<std::vector<int, Alloc>, CT_Vector>::run();
  303. }
  304. // FIXME these containers don't support iterator debugging
  305. if ((false)) {
  306. SequenceContainerChecks<
  307. std::vector<bool, test_allocator<bool>>, CT_VectorBool>::run();
  308. SequenceContainerChecks<
  309. std::forward_list<int, Alloc>, CT_ForwardList>::run();
  310. SequenceContainerChecks<
  311. std::deque<int, Alloc>, CT_Deque>::run();
  312. }
  313. return 0;
  314. }