1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef NASTY_CONTAINERS_H
11#define NASTY_CONTAINERS_H
12
13#include <cassert>
14#include <vector>
15#include <list>
16
17#include "test_macros.h"
18
19template <class T>
20class nasty_vector
21{
22public:
23    typedef typename std::vector<T>                           nested_container;
24    typedef typename nested_container::value_type             value_type;
25    typedef typename nested_container::reference              reference;
26    typedef typename nested_container::const_reference        const_reference;
27    typedef typename nested_container::iterator               iterator;
28    typedef typename nested_container::const_iterator         const_iterator;
29
30    typedef typename nested_container::size_type              size_type;
31    typedef typename nested_container::difference_type        difference_type;
32    typedef typename nested_container::pointer                pointer;
33    typedef typename nested_container::const_pointer          const_pointer;
34
35    typedef typename nested_container::reverse_iterator       reverse_iterator;
36    typedef typename nested_container::const_reverse_iterator const_reverse_iterator;
37
38    nasty_vector() : v_() {}
39    explicit nasty_vector(size_type n) : v_(n) {}
40    nasty_vector(size_type n, const value_type& value) : v_(n, value) {}
41    template <class InputIterator> nasty_vector(InputIterator first, InputIterator last) : v_(first, last) {}
42#if TEST_STD_VER >= 11
43    nasty_vector(std::initializer_list<value_type> il) : v_(il) {}
44#endif
45    ~nasty_vector() {}
46
47    template <class InputIterator>
48        void assign(InputIterator first, InputIterator last) { v_.assign(first, last); }
49    void assign(size_type n, const value_type& u) { v_.assign(n, u); }
50#if TEST_STD_VER >= 11
51    void assign(std::initializer_list<value_type> il)  { v_.assign(il); }
52#endif
53
54    iterator               begin() TEST_NOEXCEPT         { return v_.begin(); }
55    const_iterator         begin()   const TEST_NOEXCEPT { return v_.begin(); }
56    iterator               end() TEST_NOEXCEPT           { return v_.end(); }
57    const_iterator         end()     const TEST_NOEXCEPT { return v_.end(); }
58
59    reverse_iterator       rbegin() TEST_NOEXCEPT        { return v_.rbegin(); }
60    const_reverse_iterator rbegin()  const TEST_NOEXCEPT { return v_.rbegin(); }
61    reverse_iterator       rend() TEST_NOEXCEPT          { return v_.rend(); }
62    const_reverse_iterator rend()    const TEST_NOEXCEPT { return v_.rend(); }
63
64    const_iterator         cbegin()  const TEST_NOEXCEPT { return v_.cbegin(); }
65    const_iterator         cend()    const TEST_NOEXCEPT { return v_.cend(); }
66    const_reverse_iterator crbegin() const TEST_NOEXCEPT { return v_.crbegin(); }
67    const_reverse_iterator crend()   const TEST_NOEXCEPT { return v_.crend(); }
68
69    size_type size() const TEST_NOEXCEPT      { return v_.size(); }
70    size_type max_size() const TEST_NOEXCEPT  { return v_.max_size(); }
71    size_type capacity() const TEST_NOEXCEPT  { return v_.capacity(); }
72    bool empty() const TEST_NOEXCEPT          { return v_.empty(); }
73    void reserve(size_type n)             { v_.reserve(n); };
74    void shrink_to_fit() TEST_NOEXCEPT        { v_.shrink_to_fit(); }
75
76    reference       operator[](size_type n)       { return v_[n]; }
77    const_reference operator[](size_type n) const { return v_[n]; }
78    reference       at(size_type n)               { return v_.at(n); }
79    const_reference at(size_type n) const         { return v_.at(n); }
80
81    reference       front()       { return v_.front(); }
82    const_reference front() const { return v_.front(); }
83    reference       back()        { return v_.back(); }
84    const_reference back() const  { return v_.back(); }
85
86    value_type*       data() TEST_NOEXCEPT       { return v_.data(); }
87    const value_type* data() const TEST_NOEXCEPT { return v_.data(); }
88
89    void push_back(const value_type& x)     { v_.push_back(x); }
90#if TEST_STD_VER >= 11
91    void push_back(value_type&& x)          { v_.push_back(std::forward<value_type&&>(x)); }
92    template <class... Args>
93        void emplace_back(Args&&... args)   { v_.emplace_back(std::forward<Args>(args)...); }
94#endif
95    void pop_back()                         { v_.pop_back(); }
96
97#if TEST_STD_VER >= 11
98    template <class... Args> iterator emplace(const_iterator pos, Args&&... args)
99    { return v_.emplace(pos, std::forward<Args>(args)...); }
100#endif
101
102    iterator insert(const_iterator pos, const value_type& x) { return v_.insert(pos, x); }
103#if TEST_STD_VER >= 11
104    iterator insert(const_iterator pos, value_type&& x)      { return v_.insert(pos, std::forward<value_type>(x)); }
105#endif
106    iterator insert(const_iterator pos, size_type n, const value_type& x) { return v_.insert(pos, n, x); }
107    template <class InputIterator>
108        iterator insert(const_iterator pos, InputIterator first, InputIterator last)
109    { return v_.insert(pos, first, last); }
110
111#if TEST_STD_VER >= 11
112    iterator insert(const_iterator pos, std::initializer_list<value_type> il) { return v_.insert(pos, il); }
113#endif
114
115    iterator erase(const_iterator pos)                        { return v_.erase(pos); }
116    iterator erase(const_iterator first, const_iterator last) { return v_.erase(first, last); }
117
118    void clear() TEST_NOEXCEPT { v_.clear(); }
119
120    void resize(size_type sz)                      { v_.resize(sz); }
121    void resize(size_type sz, const value_type& c) { v_.resize(sz, c); }
122
123    void swap(nasty_vector &nv)
124#if TEST_STD_VER > 14
125    noexcept(std::is_nothrow_swappable<nested_container>::value)
126#elif defined(_LIBCPP_VERSION)
127    TEST_NOEXCEPT_COND(std::__is_nothrow_swappable<nested_container>::value)
128#endif
129    { v_.swap(nv.v_); }
130
131    nasty_vector *operator &()             { assert(false); return nullptr; }  // nasty
132    const nasty_vector *operator &() const { assert(false); return nullptr; }  // nasty
133
134    nested_container v_;
135};
136
137template <class T>
138bool operator==(const nasty_vector<T>& x, const nasty_vector<T>& y) { return x.v_ == y.v_; }
139
140template <class T>
141class nasty_list
142{
143public:
144
145    typedef typename std::list<T>                             nested_container;
146    typedef typename nested_container::value_type             value_type;
147    typedef typename nested_container::reference              reference;
148    typedef typename nested_container::const_reference        const_reference;
149    typedef typename nested_container::iterator               iterator;
150    typedef typename nested_container::const_iterator         const_iterator;
151
152    typedef typename nested_container::size_type              size_type;
153    typedef typename nested_container::difference_type        difference_type;
154    typedef typename nested_container::pointer                pointer;
155    typedef typename nested_container::const_pointer          const_pointer;
156
157    typedef typename nested_container::reverse_iterator       reverse_iterator;
158    typedef typename nested_container::const_reverse_iterator const_reverse_iterator;
159
160    nasty_list() : l_() {}
161    explicit nasty_list(size_type n)  : l_(n) {}
162    nasty_list(size_type n, const value_type& value)  : l_(n,value) {}
163    template <class Iter>
164        nasty_list(Iter first, Iter last)  : l_(first, last) {}
165#if TEST_STD_VER >= 11
166    nasty_list(std::initializer_list<value_type> il) : l_(il) {}
167#endif
168
169    ~nasty_list() {}
170
171#if TEST_STD_VER >= 11
172    nasty_list& operator=(std::initializer_list<value_type> il) { l_ = il; return *this; }
173#endif
174    template <class Iter>
175        void assign(Iter first, Iter last) { l_.assign(first, last); }
176    void assign(size_type n, const value_type& t) { l_.assign(n, t); }
177#if TEST_STD_VER >= 11
178    void assign(std::initializer_list<value_type> il) { l_.assign(il); }
179#endif
180
181
182    iterator               begin() TEST_NOEXCEPT         { return l_.begin(); }
183    const_iterator         begin()   const TEST_NOEXCEPT { return l_.begin(); }
184    iterator               end() TEST_NOEXCEPT           { return l_.end(); }
185    const_iterator         end()     const TEST_NOEXCEPT { return l_.end(); }
186
187    reverse_iterator       rbegin() TEST_NOEXCEPT        { return l_.rbegin(); }
188    const_reverse_iterator rbegin()  const TEST_NOEXCEPT { return l_.rbegin(); }
189    reverse_iterator       rend() TEST_NOEXCEPT          { return l_.rend(); }
190    const_reverse_iterator rend()    const TEST_NOEXCEPT { return l_.rend(); }
191
192    const_iterator         cbegin()  const TEST_NOEXCEPT { return l_.cbegin(); }
193    const_iterator         cend()    const TEST_NOEXCEPT { return l_.cend(); }
194    const_reverse_iterator crbegin() const TEST_NOEXCEPT { return l_.crbegin(); }
195    const_reverse_iterator crend()   const TEST_NOEXCEPT { return l_.crend(); }
196
197    reference       front()       { return l_.front(); }
198    const_reference front() const { return l_.front(); }
199    reference       back()        { return l_.back(); }
200    const_reference back() const  { return l_.back(); }
201
202    size_type size() const TEST_NOEXCEPT      { return l_.size(); }
203    size_type max_size() const TEST_NOEXCEPT  { return l_.max_size(); }
204    bool empty() const TEST_NOEXCEPT          { return l_.empty(); }
205
206    void push_front(const value_type& x)    { l_.push_front(x); }
207    void push_back(const value_type& x)     { l_.push_back(x); }
208#if TEST_STD_VER >= 11
209    void push_back(value_type&& x)          { l_.push_back(std::forward<value_type&&>(x)); }
210    void push_front(value_type&& x)         { l_.push_back(std::forward<value_type&&>(x)); }
211    template <class... Args>
212        void emplace_back(Args&&... args)   { l_.emplace_back(std::forward<Args>(args)...); }
213    template <class... Args>
214        void emplace_front(Args&&... args)  { l_.emplace_front(std::forward<Args>(args)...); }
215#endif
216    void pop_front()                        { l_.pop_front(); }
217    void pop_back()                         { l_.pop_back(); }
218
219#if TEST_STD_VER >= 11
220    template <class... Args> iterator emplace(const_iterator pos, Args&&... args)
221    { return l_.emplace(pos, std::forward<Args>(args)...); }
222#endif
223
224    iterator insert(const_iterator pos, const value_type& x) { return l_.insert(pos, x); }
225#if TEST_STD_VER >= 11
226    iterator insert(const_iterator pos, value_type&& x)      { return l_.insert(pos, std::forward<value_type>(x)); }
227#endif
228    iterator insert(const_iterator pos, size_type n, const value_type& x) { return l_.insert(pos, n, x); }
229    template <class InputIterator>
230        iterator insert(const_iterator pos, InputIterator first, InputIterator last)
231    { return l_.insert(pos, first, last); }
232
233#if TEST_STD_VER >= 11
234    iterator insert(const_iterator pos, std::initializer_list<value_type> il) { return l_.insert(pos, il); }
235#endif
236
237    iterator erase(const_iterator pos)                      { return l_.erase(pos); }
238    iterator erase(const_iterator pos, const_iterator last) { return l_.erase(pos, last); }
239
240    void resize(size_type)                      { l_.resize(); }
241    void resize(size_type, const value_type& c) { l_.resize(c); }
242
243    void swap(nasty_list &nl)
244#if TEST_STD_VER > 14
245    noexcept(std::is_nothrow_swappable<nested_container>::value)
246#elif defined(_LIBCPP_VERSION)
247    TEST_NOEXCEPT_COND(std::__is_nothrow_swappable<nested_container>::value)
248#endif
249    { l_.swap(nl.l_); }
250
251    void clear() TEST_NOEXCEPT { l_.clear(); }
252
253//     void splice(const_iterator position, list& x);
254//     void splice(const_iterator position, list&& x);
255//     void splice(const_iterator position, list& x, const_iterator i);
256//     void splice(const_iterator position, list&& x, const_iterator i);
257//     void splice(const_iterator position, list& x, const_iterator first,
258//                                                   const_iterator last);
259//     void splice(const_iterator position, list&& x, const_iterator first,
260//                                                   const_iterator last);
261//
262//     void remove(const value_type& value);
263//     template <class Pred> void remove_if(Pred pred);
264//     void unique();
265//     template <class BinaryPredicate>
266//         void unique(BinaryPredicate binary_pred);
267//     void merge(list& x);
268//     void merge(list&& x);
269//     template <class Compare>
270//         void merge(list& x, Compare comp);
271//     template <class Compare>
272//         void merge(list&& x, Compare comp);
273//     void sort();
274//     template <class Compare>
275//         void sort(Compare comp);
276//     void reverse() noexcept;
277
278    nasty_list *operator &()             { assert(false); return nullptr; }  // nasty
279    const nasty_list *operator &() const { assert(false); return nullptr; }  // nasty
280
281    nested_container l_;
282};
283
284template <class T>
285bool operator==(const nasty_list<T>& x, const nasty_list<T>& y) { return x.l_ == y.l_; }
286
287// Not really a mutex, but can play one in tests
288class nasty_mutex
289{
290public:
291     nasty_mutex() TEST_NOEXCEPT {}
292     ~nasty_mutex() {}
293
294    nasty_mutex *operator& ()   { assert(false); return nullptr; }
295    template <typename T>
296    void operator, (const T &) { assert(false); }
297
298private:
299    nasty_mutex(const nasty_mutex&)            { assert(false); }
300    nasty_mutex& operator=(const nasty_mutex&) { assert(false); return *this; }
301
302public:
303    void lock()               {}
304    bool try_lock() TEST_NOEXCEPT { return true; }
305    void unlock() TEST_NOEXCEPT   {}
306
307    // Shared ownership
308    void lock_shared()     {}
309    bool try_lock_shared() { return true; }
310    void unlock_shared()   {}
311};
312
313#endif
314