OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libstdc++-v3/] [testsuite/] [util/] [exception/] [safety.h] - Blame information for rev 742

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 742 jeremybenn
// -*- C++ -*-
2
 
3
// Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4
//
5
// This file is part of the GNU ISO C++ Library.  This library is free
6
// software; you can redistribute it and/or modify it under the terms
7
// of the GNU General Public License as published by the Free Software
8
// Foundation; either version 3, or (at your option) any later
9
// version.
10
 
11
// This library is distributed in the hope that it will be useful, but
12
// WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
// General Public License for more details.
15
 
16
// You should have received a copy of the GNU General Public License along
17
// with this library; see the file COPYING3.  If not see
18
// <http://www.gnu.org/licenses/>.
19
 
20
#ifndef _GLIBCXX_EXCEPTION_SAFETY_H
21
#define _GLIBCXX_EXCEPTION_SAFETY_H
22
 
23
#include <testsuite_container_traits.h>
24
#include <ext/throw_allocator.h>
25
 
26
// Container requirement testing.
27
namespace __gnu_test
28
{
29
  // Base class for exception testing, contains utilities.
30
  struct setup_base
31
  {
32
    typedef std::size_t                                 size_type;
33
    typedef std::uniform_int_distribution<size_type>    distribution_type;
34
    typedef std::mt19937                                engine_type;
35
 
36
    // Return randomly generated integer on range [0, __max_size].
37
    static size_type
38
    generate(size_type __max_size)
39
    {
40
      // Make the generator static...
41
      const engine_type engine;
42
      const distribution_type distribution;
43
      static auto generator = std::bind(distribution, engine,
44
                                        std::placeholders::_1);
45
 
46
      // ... but set the range for this particular invocation here.
47
      const typename distribution_type::param_type p(0, __max_size);
48
      size_type random = generator(p);
49
      if (random < distribution.min() || random > distribution.max())
50
        {
51
          std::string __s("setup_base::generate");
52
          __s += "\n";
53
          __s += "random number generated is: ";
54
          char buf[40];
55
          __builtin_sprintf(buf, "%lu", (unsigned long)random);
56
          __s += buf;
57
          __s += " on range [";
58
          __builtin_sprintf(buf, "%lu", (unsigned long)distribution.min());
59
          __s += buf;
60
          __s += ", ";
61
          __builtin_sprintf(buf, "%lu", (unsigned long)distribution.max());
62
          __s += buf;
63
          __s += "]\n";
64
          std::__throw_out_of_range(__s.c_str());
65
        }
66
      return random;
67
    }
68
 
69
    // Given an instantiating type, return a unique value.
70
    template<typename _Tp>
71
      struct generate_unique
72
      {
73
        typedef _Tp value_type;
74
 
75
        operator value_type()
76
        {
77
          static value_type __ret;
78
          ++__ret;
79
          return __ret;
80
        }
81
      };
82
 
83
    // Partial specialization for pair.
84
    template<typename _Tp1, typename _Tp2>
85
      struct generate_unique<std::pair<const _Tp1, _Tp2>>
86
      {
87
        typedef _Tp1 first_type;
88
        typedef _Tp2 second_type;
89
        typedef std::pair<const _Tp1, _Tp2> pair_type;
90
 
91
        operator pair_type()
92
        {
93
          static first_type _S_1;
94
          static second_type _S_2;
95
          ++_S_1;
96
          ++_S_2;
97
          return pair_type(_S_1, _S_2);
98
        }
99
      };
100
 
101
    // Partial specialization for throw_value
102
    template<typename _Cond>
103
      struct generate_unique<__gnu_cxx::throw_value_base<_Cond>>
104
      {
105
        typedef __gnu_cxx::throw_value_base<_Cond> value_type;
106
 
107
        operator value_type()
108
        {
109
          static size_t _S_i(0);
110
          return value_type(_S_i++);
111
        }
112
      };
113
 
114
 
115
    // Construct container of size n directly. _Tp == container type.
116
    template<typename _Tp>
117
      struct make_container_base
118
      {
119
        _Tp _M_container;
120
 
121
        make_container_base() = default;
122
        make_container_base(const size_type n): _M_container(n) { }
123
 
124
        operator _Tp&() { return _M_container; }
125
      };
126
 
127
    // Construct container of size n, via multiple insertions. For
128
    // associated and unordered types, unique value_type elements are
129
    // necessary.
130
    template<typename _Tp, bool = traits<_Tp>::is_mapped::value>
131
      struct make_insert_container_base
132
      : public make_container_base<_Tp>
133
      {
134
        using make_container_base<_Tp>::_M_container;
135
        typedef typename _Tp::value_type value_type;
136
 
137
        make_insert_container_base(const size_type n)
138
        {
139
          for (size_type i = 0; i < n; ++i)
140
            {
141
              value_type v = generate_unique<value_type>();
142
              _M_container.insert(v);
143
            }
144
          assert(_M_container.size() == n);
145
        }
146
      };
147
 
148
    template<typename _Tp>
149
      struct make_insert_container_base<_Tp, false>
150
      : public make_container_base<_Tp>
151
      {
152
        using make_container_base<_Tp>::_M_container;
153
        typedef typename _Tp::value_type value_type;
154
 
155
        make_insert_container_base(const size_type n)
156
        {
157
          for (size_type i = 0; i < n; ++i)
158
            {
159
              value_type v = generate_unique<value_type>();
160
              _M_container.insert(_M_container.end(), v);
161
            }
162
          assert(_M_container.size() == n);
163
        }
164
      };
165
 
166
    template<typename _Tp, bool = traits<_Tp>::has_size_type_constructor::value>
167
      struct make_container_n;
168
 
169
    // Specialization for non-associative types that have a constructor with
170
    // a size argument.
171
    template<typename _Tp>
172
      struct make_container_n<_Tp, true>
173
      : public make_container_base<_Tp>
174
      {
175
        make_container_n(const size_type n) : make_container_base<_Tp>(n) { }
176
      };
177
 
178
    template<typename _Tp>
179
      struct make_container_n<_Tp, false>
180
      : public make_insert_container_base<_Tp>
181
      {
182
        make_container_n(const size_type n)
183
        : make_insert_container_base<_Tp>(n) { }
184
      };
185
 
186
 
187
    // Randomly size and populate a given container reference.
188
    // NB: Responsibility for turning off exceptions lies with caller.
189
    template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value>
190
      struct populate
191
      {
192
        typedef _Tp                                     container_type;
193
        typedef typename container_type::allocator_type allocator_type;
194
        typedef typename container_type::value_type     value_type;
195
 
196
        populate(_Tp& __container)
197
        {
198
          const allocator_type a = __container.get_allocator();
199
 
200
          // Size test container.
201
          const size_type max_elements = 100;
202
          size_type n = generate(max_elements);
203
 
204
          // Construct new container.
205
          make_container_n<container_type> made(n);
206
          container_type& tmp = made;
207
          std::swap(tmp, __container);
208
        }
209
      };
210
 
211
    // Partial specialization, empty.
212
    template<typename _Tp>
213
      struct populate<_Tp, false>
214
      {
215
        populate(_Tp&) { }
216
      };
217
 
218
    // Compare two containers for equivalence.
219
    // Right now, that means size.
220
    // Returns true if equal, throws if not.
221
    template<typename _Tp>
222
      static bool
223
      compare(const _Tp& __control, const _Tp& __test)
224
      {
225
        // Make sure test container is in a consistent state, as
226
        // compared to the control container.
227
        // NB: Should be equivalent to __test != __control, but
228
        // computed without equivalence operators
229
        const size_type szt = std::distance(__test.begin(), __test.end());
230
        const size_type szc = std::distance(__control.begin(),
231
                                            __control.end());
232
        bool __equal_size = szt == szc;
233
 
234
        // Should test iterator validity before and after exception.
235
        bool __equal_it = std::equal(__test.begin(), __test.end(),
236
                                     __control.begin());
237
 
238
        if (!__equal_size || !__equal_it)
239
          throw std::logic_error("setup_base::compare containers not equal");
240
 
241
        return true;
242
      }
243
  };
244
 
245
 
246
  // Containing structure holding functors.
247
  struct functor_base : public setup_base
248
  {
249
    // Abstract the erase function.
250
    template<typename _Tp>
251
      struct erase_base
252
      {
253
        typedef typename _Tp::iterator                  iterator;
254
        typedef typename _Tp::const_iterator            const_iterator;
255
 
256
        iterator (_Tp::* _F_erase_point)(const_iterator);
257
        iterator (_Tp::* _F_erase_range)(const_iterator, const_iterator);
258
 
259
        erase_base()
260
        : _F_erase_point(&_Tp::erase), _F_erase_range(&_Tp::erase) { }
261
      };
262
 
263
    // Specializations, old C++03 signatures.
264
    template<typename _Tp1, typename _Tp2, typename _Tp3>
265
      struct erase_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
266
      {
267
        typedef std::basic_string<_Tp1, _Tp2, _Tp3>     container_type;
268
        typedef typename container_type::iterator       iterator;
269
 
270
        iterator (container_type::* _F_erase_point)(iterator);
271
        iterator (container_type::* _F_erase_range)(iterator, iterator);
272
 
273
        erase_base()
274
        : _F_erase_point(&container_type::erase),
275
          _F_erase_range(&container_type::erase) { }
276
      };
277
 
278
    template<typename _Tp1, typename _Tp2, typename _Tp3,
279
             template <typename, typename, typename> class _Tp4>
280
      struct erase_base<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
281
      {
282
        typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
283
                                                        container_type;
284
        typedef typename container_type::iterator       iterator;
285
 
286
        iterator (container_type::* _F_erase_point)(iterator);
287
        iterator (container_type::* _F_erase_range)(iterator, iterator);
288
 
289
        erase_base()
290
        : _F_erase_point(&container_type::erase),
291
          _F_erase_range(&container_type::erase) { }
292
      };
293
 
294
    template<typename _Tp1, typename _Tp2>
295
      struct erase_base<std::deque<_Tp1, _Tp2>>
296
      {
297
        typedef std::deque<_Tp1, _Tp2>                  container_type;
298
        typedef typename container_type::iterator       iterator;
299
 
300
        iterator (container_type::* _F_erase_point)(iterator);
301
        iterator (container_type::* _F_erase_range)(iterator, iterator);
302
 
303
        erase_base()
304
        : _F_erase_point(&container_type::erase),
305
          _F_erase_range(&container_type::erase) { }
306
      };
307
 
308
    template<typename _Tp1, typename _Tp2>
309
      struct erase_base<std::list<_Tp1, _Tp2>>
310
      {
311
        typedef std::list<_Tp1, _Tp2>                   container_type;
312
        typedef typename container_type::iterator       iterator;
313
 
314
        iterator (container_type::* _F_erase_point)(iterator);
315
        iterator (container_type::* _F_erase_range)(iterator, iterator);
316
 
317
        erase_base()
318
        : _F_erase_point(&container_type::erase),
319
          _F_erase_range(&container_type::erase) { }
320
      };
321
 
322
    template<typename _Tp1, typename _Tp2>
323
      struct erase_base<std::vector<_Tp1, _Tp2>>
324
      {
325
        typedef std::vector<_Tp1, _Tp2>                 container_type;
326
        typedef typename container_type::iterator       iterator;
327
 
328
        iterator (container_type::* _F_erase_point)(iterator);
329
        iterator (container_type::* _F_erase_range)(iterator, iterator);
330
 
331
        erase_base()
332
        : _F_erase_point(&container_type::erase),
333
          _F_erase_range(&container_type::erase) { }
334
      };
335
 
336
    // Specialization, as forward_list has erase_after.
337
    template<typename _Tp1, typename _Tp2>
338
      struct erase_base<std::forward_list<_Tp1, _Tp2>>
339
      {
340
        typedef std::forward_list<_Tp1, _Tp2>           container_type;
341
        typedef typename container_type::iterator       iterator;
342
        typedef typename container_type::const_iterator const_iterator;
343
 
344
        iterator (container_type::* _F_erase_point)(const_iterator);
345
        iterator (container_type::* _F_erase_range)(const_iterator,
346
                                                    const_iterator);
347
 
348
        erase_base()
349
        : _F_erase_point(&container_type::erase_after),
350
          _F_erase_range(&container_type::erase_after) { }
351
      };
352
 
353
    template<typename _Tp,
354
             bool = traits<_Tp>::has_erase::value,
355
             bool = traits<_Tp>::has_erase_after::value>
356
      struct erase_point;
357
 
358
    // Specialization for most containers.
359
    template<typename _Tp>
360
      struct erase_point<_Tp, true, false> : public erase_base<_Tp>
361
      {
362
        using erase_base<_Tp>::_F_erase_point;
363
 
364
        void
365
        operator()(_Tp& __container)
366
        {
367
          try
368
            {
369
              // NB: Should be equivalent to size() member function, but
370
              // computed with begin() and end().
371
              const size_type sz = std::distance(__container.begin(),
372
                                                 __container.end());
373
 
374
              // NB: Lowest common denominator: use forward iterator operations.
375
              auto i = __container.begin();
376
              std::advance(i, generate(sz));
377
 
378
              // Makes it easier to think of this as __container.erase(i)
379
              (__container.*_F_erase_point)(i);
380
            }
381
          catch(const __gnu_cxx::forced_error&)
382
            { throw; }
383
        }
384
      };
385
 
386
    // Specialization for forward_list.
387
    template<typename _Tp>
388
      struct erase_point<_Tp, false, true> : public erase_base<_Tp>
389
      {
390
        using erase_base<_Tp>::_F_erase_point;
391
 
392
        void
393
        operator()(_Tp& __container)
394
        {
395
          try
396
            {
397
              // NB: Should be equivalent to size() member function, but
398
              // computed with begin() and end().
399
              const size_type sz = std::distance(__container.begin(),
400
                                                 __container.end());
401
 
402
              // NB: Lowest common denominator: use forward iterator operations.
403
              auto i = __container.before_begin();
404
              std::advance(i, generate(sz));
405
 
406
              // Makes it easier to think of this as __container.erase(i)
407
              (__container.*_F_erase_point)(i);
408
            }
409
          catch(const __gnu_cxx::forced_error&)
410
            { throw; }
411
        }
412
      };
413
 
414
    // Specialization, empty.
415
    template<typename _Tp>
416
      struct erase_point<_Tp, false, false>
417
      {
418
        void
419
        operator()(_Tp&) { }
420
      };
421
 
422
 
423
    template<typename _Tp,
424
             bool = traits<_Tp>::has_erase::value,
425
             bool = traits<_Tp>::has_erase_after::value>
426
      struct erase_range;
427
 
428
    // Specialization for most containers.
429
    template<typename _Tp>
430
      struct erase_range<_Tp, true, false> : public erase_base<_Tp>
431
      {
432
        using erase_base<_Tp>::_F_erase_range;
433
 
434
        void
435
        operator()(_Tp& __container)
436
        {
437
          try
438
            {
439
              const size_type sz = std::distance(__container.begin(),
440
                                                 __container.end());
441
              size_type s1 = generate(sz);
442
              size_type s2 = generate(sz);
443
              auto i1 = __container.begin();
444
              auto i2 = __container.begin();
445
              std::advance(i1, std::min(s1, s2));
446
              std::advance(i2, std::max(s1, s2));
447
 
448
              // Makes it easier to think of this as __container.erase(i1, i2).
449
              (__container.*_F_erase_range)(i1, i2);
450
            }
451
          catch(const __gnu_cxx::forced_error&)
452
            { throw; }
453
        }
454
      };
455
 
456
    // Specialization for forward_list.
457
    template<typename _Tp>
458
      struct erase_range<_Tp, false, true> : public erase_base<_Tp>
459
      {
460
        using erase_base<_Tp>::_F_erase_range;
461
 
462
        void
463
        operator()(_Tp& __container)
464
        {
465
          try
466
            {
467
              const size_type sz = std::distance(__container.begin(),
468
                                                 __container.end());
469
              size_type s1 = generate(sz);
470
              size_type s2 = generate(sz);
471
              auto i1 = __container.before_begin();
472
              auto i2 = __container.before_begin();
473
              std::advance(i1, std::min(s1, s2));
474
              std::advance(i2, std::max(s1, s2));
475
 
476
              // Makes it easier to think of this as __container.erase(i1, i2).
477
              (__container.*_F_erase_range)(i1, i2);
478
            }
479
          catch(const __gnu_cxx::forced_error&)
480
            { throw; }
481
        }
482
      };
483
 
484
    // Specialization, empty.
485
    template<typename _Tp>
486
      struct erase_range<_Tp, false, false>
487
      {
488
        void
489
        operator()(_Tp&) { }
490
      };
491
 
492
 
493
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
494
      struct pop_front
495
      {
496
        void
497
        operator()(_Tp& __container)
498
        {
499
          try
500
            {
501
              __container.pop_front();
502
            }
503
          catch(const __gnu_cxx::forced_error&)
504
            { throw; }
505
        }
506
      };
507
 
508
    // Specialization, empty.
509
    template<typename _Tp>
510
      struct pop_front<_Tp, false>
511
      {
512
        void
513
        operator()(_Tp&) { }
514
      };
515
 
516
 
517
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
518
                                  && traits<_Tp>::is_reversible::value>
519
      struct pop_back
520
      {
521
        void
522
        operator()(_Tp& __container)
523
        {
524
          try
525
            {
526
              __container.pop_back();
527
            }
528
          catch(const __gnu_cxx::forced_error&)
529
            { throw; }
530
        }
531
      };
532
 
533
    // Specialization, empty.
534
    template<typename _Tp>
535
      struct pop_back<_Tp, false>
536
      {
537
        void
538
        operator()(_Tp&) { }
539
      };
540
 
541
 
542
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
543
      struct push_front
544
      {
545
        typedef _Tp                                     container_type;
546
        typedef typename container_type::value_type     value_type;
547
 
548
        void
549
        operator()(_Tp& __test)
550
        {
551
          try
552
            {
553
              const value_type cv = generate_unique<value_type>();
554
              __test.push_front(cv);
555
            }
556
          catch(const __gnu_cxx::forced_error&)
557
            { throw; }
558
        }
559
 
560
        // Assumes containers start out equivalent.
561
        void
562
        operator()(_Tp& __control, _Tp& __test)
563
        {
564
          try
565
            {
566
              const value_type cv = generate_unique<value_type>();
567
              __test.push_front(cv);
568
            }
569
          catch(const __gnu_cxx::forced_error&)
570
            { throw; }
571
        }
572
    };
573
 
574
    // Specialization, empty.
575
    template<typename _Tp>
576
      struct push_front<_Tp, false>
577
      {
578
        void
579
        operator()(_Tp&) { }
580
 
581
        void
582
        operator()(_Tp&, _Tp&) { }
583
      };
584
 
585
 
586
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
587
                                  && traits<_Tp>::is_reversible::value>
588
      struct push_back
589
      {
590
        typedef _Tp                                     container_type;
591
        typedef typename container_type::value_type     value_type;
592
 
593
        void
594
        operator()(_Tp& __test)
595
        {
596
          try
597
            {
598
              const value_type cv = generate_unique<value_type>();
599
              __test.push_back(cv);
600
            }
601
          catch(const __gnu_cxx::forced_error&)
602
            { throw; }
603
        }
604
 
605
        // Assumes containers start out equivalent.
606
        void
607
        operator()(_Tp& __control, _Tp& __test)
608
        {
609
          try
610
            {
611
              const value_type cv = generate_unique<value_type>();
612
              __test.push_back(cv);
613
            }
614
          catch(const __gnu_cxx::forced_error&)
615
            { throw; }
616
        }
617
    };
618
 
619
    // Specialization, empty.
620
    template<typename _Tp>
621
      struct push_back<_Tp, false>
622
      {
623
        void
624
        operator()(_Tp&) { }
625
 
626
        void
627
        operator()(_Tp&, _Tp&) { }
628
      };
629
 
630
 
631
    // Abstract the insert function into two parts:
632
    // 1, insert_base_functions == holds function pointer
633
    // 2, insert_base == links function pointer to class insert method
634
    template<typename _Tp>
635
      struct insert_base
636
      {
637
        typedef typename _Tp::iterator                  iterator;
638
        typedef typename _Tp::const_iterator            const_iterator;
639
        typedef typename _Tp::value_type                value_type;
640
 
641
        iterator (_Tp::* _F_insert_point)(const_iterator, const value_type&);
642
 
643
        insert_base() : _F_insert_point(&_Tp::insert) { }
644
      };
645
 
646
    // Specializations, old C++03 signatures.
647
    template<typename _Tp1, typename _Tp2>
648
      struct insert_base<std::deque<_Tp1, _Tp2>>
649
      {
650
        typedef std::deque<_Tp1, _Tp2>                  container_type;
651
        typedef typename container_type::iterator       iterator;
652
        typedef typename container_type::value_type     value_type;
653
 
654
        iterator (container_type::* _F_insert_point)(iterator,
655
                                                     const value_type&);
656
 
657
        insert_base() : _F_insert_point(&container_type::insert) { }
658
      };
659
 
660
    template<typename _Tp1, typename _Tp2>
661
      struct insert_base<std::list<_Tp1, _Tp2>>
662
      {
663
        typedef std::list<_Tp1, _Tp2>                   container_type;
664
        typedef typename container_type::iterator       iterator;
665
        typedef typename container_type::value_type     value_type;
666
 
667
        iterator (container_type::* _F_insert_point)(iterator,
668
                                                     const value_type&);
669
 
670
        insert_base() : _F_insert_point(&container_type::insert) { }
671
      };
672
 
673
    template<typename _Tp1, typename _Tp2>
674
      struct insert_base<std::vector<_Tp1, _Tp2>>
675
      {
676
        typedef std::vector<_Tp1, _Tp2>                 container_type;
677
        typedef typename container_type::iterator       iterator;
678
        typedef typename container_type::value_type     value_type;
679
 
680
        iterator (container_type::* _F_insert_point)(iterator,
681
                                                     const value_type&);
682
 
683
        insert_base() : _F_insert_point(&container_type::insert) { }
684
      };
685
 
686
    // Specialization, as string insertion has a different signature.
687
    template<typename _Tp1, typename _Tp2, typename _Tp3>
688
      struct insert_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
689
      {
690
        typedef std::basic_string<_Tp1, _Tp2, _Tp3>     container_type;
691
        typedef typename container_type::iterator       iterator;
692
        typedef typename container_type::value_type     value_type;
693
 
694
        iterator (container_type::* _F_insert_point)(iterator, value_type);
695
 
696
        insert_base() : _F_insert_point(&container_type::insert) { }
697
      };
698
 
699
    // Likewise for __versa_string.
700
    template<typename _Tp1, typename _Tp2, typename _Tp3,
701
             template <typename, typename, typename> class _Tp4>
702
      struct insert_base<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
703
      {
704
        typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
705
                                                        container_type;
706
        typedef typename container_type::iterator       iterator;
707
        typedef typename container_type::value_type     value_type;
708
 
709
        iterator (container_type::* _F_insert_point)(iterator, value_type);
710
 
711
        insert_base() : _F_insert_point(&container_type::insert) { }
712
      };
713
 
714
    // Specialization, as forward_list has insert_after.
715
    template<typename _Tp1, typename _Tp2>
716
      struct insert_base<std::forward_list<_Tp1, _Tp2>>
717
      {
718
        typedef std::forward_list<_Tp1, _Tp2> container_type;
719
        typedef typename container_type::iterator       iterator;
720
        typedef typename container_type::const_iterator const_iterator;
721
        typedef typename container_type::value_type     value_type;
722
 
723
        iterator (container_type::* _F_insert_point)(const_iterator,
724
                                                     const value_type&);
725
 
726
        insert_base() : _F_insert_point(&container_type::insert_after) { }
727
      };
728
 
729
    template<typename _Tp,
730
             bool = traits<_Tp>::has_insert::value,
731
             bool = traits<_Tp>::has_insert_after::value>
732
      struct insert_point;
733
 
734
    // Specialization for most containers.
735
    template<typename _Tp>
736
      struct insert_point<_Tp, true, false> : public insert_base<_Tp>
737
      {
738
        typedef _Tp                                     container_type;
739
        typedef typename container_type::value_type     value_type;
740
        using insert_base<_Tp>::_F_insert_point;
741
 
742
        void
743
        operator()(_Tp& __test)
744
        {
745
          try
746
            {
747
              const value_type cv = generate_unique<value_type>();
748
              const size_type sz = std::distance(__test.begin(), __test.end());
749
              size_type s = generate(sz);
750
              auto i = __test.begin();
751
              std::advance(i, s);
752
              (__test.*_F_insert_point)(i, cv);
753
            }
754
          catch(const __gnu_cxx::forced_error&)
755
            { throw; }
756
        }
757
 
758
        // Assumes containers start out equivalent.
759
        void
760
        operator()(_Tp& __control, _Tp& __test)
761
        {
762
          try
763
            {
764
              const value_type cv = generate_unique<value_type>();
765
              const size_type sz = std::distance(__test.begin(), __test.end());
766
              size_type s = generate(sz);
767
              auto i = __test.begin();
768
              std::advance(i, s);
769
              (__test.*_F_insert_point)(i, cv);
770
            }
771
          catch(const __gnu_cxx::forced_error&)
772
            { throw; }
773
        }
774
      };
775
 
776
    // Specialization for forward_list.
777
    template<typename _Tp>
778
      struct insert_point<_Tp, false, true> : public insert_base<_Tp>
779
      {
780
        typedef _Tp                                     container_type;
781
        typedef typename container_type::value_type     value_type;
782
        using insert_base<_Tp>::_F_insert_point;
783
 
784
        void
785
        operator()(_Tp& __test)
786
        {
787
          try
788
            {
789
              const value_type cv = generate_unique<value_type>();
790
              const size_type sz = std::distance(__test.begin(), __test.end());
791
              size_type s = generate(sz);
792
              auto i = __test.before_begin();
793
              std::advance(i, s);
794
              (__test.*_F_insert_point)(i, cv);
795
            }
796
          catch(const __gnu_cxx::forced_error&)
797
            { throw; }
798
        }
799
 
800
        // Assumes containers start out equivalent.
801
        void
802
        operator()(_Tp& __control, _Tp& __test)
803
        {
804
          try
805
            {
806
              const value_type cv = generate_unique<value_type>();
807
              const size_type sz = std::distance(__test.begin(), __test.end());
808
              size_type s = generate(sz);
809
              auto i = __test.before_begin();
810
              std::advance(i, s);
811
              (__test.*_F_insert_point)(i, cv);
812
            }
813
          catch(const __gnu_cxx::forced_error&)
814
            { throw; }
815
        }
816
      };
817
 
818
    // Specialization, empty.
819
    template<typename _Tp>
820
      struct insert_point<_Tp, false, false>
821
      {
822
        void
823
        operator()(_Tp&) { }
824
 
825
        void
826
        operator()(_Tp&, _Tp&) { }
827
      };
828
 
829
    template<typename _Tp,
830
             bool = traits<_Tp>::has_emplace::value>
831
      struct emplace;
832
 
833
    // Specialization for most containers.
834
    template<typename _Tp>
835
      struct emplace<_Tp, true>
836
      {
837
        typedef _Tp                                     container_type;
838
        typedef typename container_type::value_type     value_type;
839
        typedef typename container_type::size_type      size_type;
840
 
841
        void
842
        operator()(_Tp& __test)
843
        {
844
          try
845
            {
846
              const value_type cv = generate_unique<value_type>();
847
              __test.emplace(cv);
848
            }
849
          catch(const __gnu_cxx::forced_error&)
850
            { throw; }
851
        }
852
 
853
        // Assumes containers start out equivalent.
854
        void
855
        operator()(_Tp& __control, _Tp& __test)
856
        {
857
          try
858
            {
859
              const value_type cv = generate_unique<value_type>();
860
              __test.emplace(cv);
861
            }
862
          catch(const __gnu_cxx::forced_error&)
863
            { throw; }
864
        }
865
      };
866
 
867
    // Specialization, empty.
868
    template<typename _Tp>
869
      struct emplace<_Tp, false>
870
      {
871
        void
872
        operator()(_Tp&) { }
873
 
874
        void
875
        operator()(_Tp&, _Tp&) { }
876
      };
877
 
878
    template<typename _Tp,
879
             bool = traits<_Tp>::has_emplace::value>
880
      struct emplace_hint;
881
 
882
    // Specialization for most containers.
883
    template<typename _Tp>
884
      struct emplace_hint<_Tp, true>
885
      {
886
        typedef _Tp                                     container_type;
887
        typedef typename container_type::value_type     value_type;
888
 
889
        void
890
        operator()(_Tp& __test)
891
        {
892
          try
893
            {
894
              const value_type cv = generate_unique<value_type>();
895
              const size_type sz = std::distance(__test.begin(), __test.end());
896
              size_type s = generate(sz);
897
              auto i = __test.begin();
898
              std::advance(i, s);
899
              __test.emplace_hint(i, cv);
900
            }
901
          catch(const __gnu_cxx::forced_error&)
902
            { throw; }
903
        }
904
 
905
        // Assumes containers start out equivalent.
906
        void
907
        operator()(_Tp& __control, _Tp& __test)
908
        {
909
          try
910
            {
911
              const value_type cv = generate_unique<value_type>();
912
              const size_type sz = std::distance(__test.begin(), __test.end());
913
              size_type s = generate(sz);
914
              auto i = __test.begin();
915
              std::advance(i, s);
916
              __test.emplace_hint(i, cv);
917
            }
918
          catch(const __gnu_cxx::forced_error&)
919
            { throw; }
920
        }
921
      };
922
 
923
    // Specialization, empty.
924
    template<typename _Tp>
925
      struct emplace_hint<_Tp, false>
926
      {
927
        void
928
        operator()(_Tp&) { }
929
 
930
        void
931
        operator()(_Tp&, _Tp&) { }
932
      };
933
 
934
    template<typename _Tp, bool = traits<_Tp>::is_associative::value
935
                                  || traits<_Tp>::is_unordered::value>
936
      struct clear
937
      {
938
        void
939
        operator()(_Tp& __container)
940
        {
941
          try
942
            {
943
              __container.clear();
944
            }
945
          catch(const __gnu_cxx::forced_error&)
946
            { throw; }
947
        }
948
      };
949
 
950
    // Specialization, empty.
951
    template<typename _Tp>
952
      struct clear<_Tp, false>
953
      {
954
        void
955
        operator()(_Tp&) { }
956
      };
957
 
958
 
959
    template<typename _Tp, bool = traits<_Tp>::is_unordered::value>
960
      struct rehash
961
      {
962
        void
963
        operator()(_Tp& __test)
964
        {
965
          try
966
            {
967
              size_type s = generate(__test.bucket_count());
968
              __test.rehash(s);
969
            }
970
          catch(const __gnu_cxx::forced_error&)
971
            { throw; }
972
        }
973
 
974
        void
975
        operator()(_Tp& __control, _Tp& __test)
976
        {
977
          try
978
            {
979
              size_type s = generate(__test.bucket_count());
980
              __test.rehash(s);
981
            }
982
          catch(const __gnu_cxx::forced_error&)
983
            {
984
              // Also check hash status.
985
              bool fail(false);
986
              if (__control.load_factor() != __test.load_factor())
987
                fail = true;
988
              if (__control.max_load_factor() != __test.max_load_factor())
989
                fail = true;
990
              if (__control.bucket_count() != __test.bucket_count())
991
                fail = true;
992
              if (__control.max_bucket_count() != __test.max_bucket_count())
993
                fail = true;
994
 
995
              if (fail)
996
                {
997
                  char buf[40];
998
                  std::string __s("setup_base::rehash "
999
                                  "containers not equal");
1000
                  __s += "\n";
1001
                  __s += "\n";
1002
                  __s += "\t\t\tcontrol : test";
1003
                  __s += "\n";
1004
                  __s += "load_factor\t\t";
1005
                  __builtin_sprintf(buf, "%lu", __control.load_factor());
1006
                  __s += buf;
1007
                  __s += " : ";
1008
                  __builtin_sprintf(buf, "%lu", __test.load_factor());
1009
                  __s += buf;
1010
                  __s += "\n";
1011
 
1012
                  __s += "max_load_factor\t\t";
1013
                  __builtin_sprintf(buf, "%lu", __control.max_load_factor());
1014
                  __s += buf;
1015
                  __s += " : ";
1016
                  __builtin_sprintf(buf, "%lu", __test.max_load_factor());
1017
                  __s += buf;
1018
                  __s += "\n";
1019
 
1020
                  __s += "bucket_count\t\t";
1021
                  __builtin_sprintf(buf, "%lu", __control.bucket_count());
1022
                  __s += buf;
1023
                  __s += " : ";
1024
                  __builtin_sprintf(buf, "%lu", __test.bucket_count());
1025
                  __s += buf;
1026
                  __s += "\n";
1027
 
1028
                  __s += "max_bucket_count\t";
1029
                  __builtin_sprintf(buf, "%lu", __control.max_bucket_count());
1030
                  __s += buf;
1031
                  __s += " : ";
1032
                  __builtin_sprintf(buf, "%lu", __test.max_bucket_count());
1033
                  __s += buf;
1034
                  __s += "\n";
1035
 
1036
                  std::__throw_logic_error(__s.c_str());
1037
                }
1038
            }
1039
        }
1040
      };
1041
 
1042
    // Specialization, empty.
1043
    template<typename _Tp>
1044
      struct rehash<_Tp, false>
1045
      {
1046
        void
1047
        operator()(_Tp&) { }
1048
 
1049
        void
1050
        operator()(_Tp&, _Tp&) { }
1051
      };
1052
 
1053
 
1054
    template<typename _Tp>
1055
      struct swap
1056
      {
1057
        _Tp _M_other;
1058
 
1059
        void
1060
        operator()(_Tp& __container)
1061
        {
1062
          try
1063
            {
1064
              __container.swap(_M_other);
1065
            }
1066
          catch(const __gnu_cxx::forced_error&)
1067
            { throw; }
1068
        }
1069
      };
1070
 
1071
 
1072
    template<typename _Tp>
1073
      struct iterator_operations
1074
      {
1075
        typedef _Tp                                     container_type;
1076
        typedef typename container_type::iterator       iterator;
1077
 
1078
        void
1079
        operator()(_Tp& __container)
1080
        {
1081
          try
1082
            {
1083
              // Any will do.
1084
              iterator i = __container.begin();
1085
              iterator __attribute__((unused)) icopy(i);
1086
              iterator __attribute__((unused)) iassign = i;
1087
            }
1088
          catch(const __gnu_cxx::forced_error&)
1089
            { throw; }
1090
        }
1091
      };
1092
 
1093
 
1094
    template<typename _Tp>
1095
      struct const_iterator_operations
1096
      {
1097
        typedef _Tp                                     container_type;
1098
        typedef typename container_type::const_iterator const_iterator;
1099
 
1100
        void
1101
        operator()(_Tp& __container)
1102
        {
1103
          try
1104
            {
1105
              // Any will do.
1106
              const_iterator i = __container.begin();
1107
              const_iterator __attribute__((unused)) icopy(i);
1108
              const_iterator __attribute__((unused)) iassign = i;
1109
            }
1110
          catch(const __gnu_cxx::forced_error&)
1111
            { throw; }
1112
        }
1113
      };
1114
  };
1115
 
1116
  // Base class for exception tests.
1117
  template<typename _Tp>
1118
    struct test_base: public functor_base
1119
    {
1120
      typedef _Tp                                       container_type;
1121
 
1122
      typedef functor_base                              base_type;
1123
      typedef populate<container_type>                  populate;
1124
      typedef make_container_n<container_type>          make_container_n;
1125
 
1126
      typedef clear<container_type>                     clear;
1127
      typedef erase_point<container_type>               erase_point;
1128
      typedef erase_range<container_type>               erase_range;
1129
      typedef insert_point<container_type>              insert_point;
1130
      typedef emplace<container_type>                   emplace;
1131
      typedef emplace_hint<container_type>              emplace_hint;
1132
      typedef pop_front<container_type>                 pop_front;
1133
      typedef pop_back<container_type>                  pop_back;
1134
      typedef push_front<container_type>                push_front;
1135
      typedef push_back<container_type>                 push_back;
1136
      typedef rehash<container_type>                    rehash;
1137
      typedef swap<container_type>                      swap;
1138
      typedef iterator_operations<container_type>       iterator_ops;
1139
      typedef const_iterator_operations<container_type> const_iterator_ops;
1140
 
1141
      using base_type::compare;
1142
 
1143
      // Functor objects.
1144
      clear                     _M_clear;
1145
      erase_point               _M_erasep;
1146
      erase_range               _M_eraser;
1147
      insert_point              _M_insertp;
1148
      emplace                   _M_emplace;
1149
      emplace_hint              _M_emplaceh;
1150
      pop_front                 _M_popf;
1151
      pop_back                  _M_popb;
1152
      push_front                _M_pushf;
1153
      push_back                 _M_pushb;
1154
      rehash                    _M_rehash;
1155
      swap                      _M_swap;
1156
 
1157
      iterator_ops              _M_iops;
1158
      const_iterator_ops        _M_ciops;
1159
    };
1160
 
1161
 
1162
  // Run through all member functions for basic exception safety
1163
  // guarantee: no resource leaks when exceptions are thrown.
1164
  //
1165
  // Types of resources checked: memory.
1166
  //
1167
  // For each member function, use throw_value and throw_allocator as
1168
  // value_type and allocator_type to force potential exception safety
1169
  // errors.
1170
  //
1171
  // NB: Assumes
1172
  // _Tp::value_type is __gnu_cxx::throw_value_*
1173
  // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
1174
  // And that the _Cond template parameter for them both is
1175
  // __gnu_cxx::limit_condition.
1176
  template<typename _Tp>
1177
    struct basic_safety : public test_base<_Tp>
1178
    {
1179
      typedef _Tp                                       container_type;
1180
      typedef test_base<container_type>                 base_type;
1181
      typedef typename base_type::populate              populate;
1182
      typedef std::function<void(container_type&)>      function_type;
1183
      typedef __gnu_cxx::limit_condition                condition_type;
1184
 
1185
      using base_type::generate;
1186
 
1187
      container_type                                    _M_container;
1188
      std::vector<function_type>                        _M_functions;
1189
 
1190
      basic_safety() { run(); }
1191
 
1192
      void
1193
      run()
1194
      {
1195
        // Setup.
1196
        condition_type::never_adjustor off;
1197
 
1198
        // Construct containers.
1199
        populate p1(_M_container);
1200
        populate p2(base_type::_M_swap._M_other);
1201
 
1202
        // Construct list of member functions to exercise.
1203
        _M_functions.push_back(function_type(base_type::_M_iops));
1204
        _M_functions.push_back(function_type(base_type::_M_ciops));
1205
 
1206
        _M_functions.push_back(function_type(base_type::_M_erasep));
1207
        _M_functions.push_back(function_type(base_type::_M_eraser));
1208
        _M_functions.push_back(function_type(base_type::_M_insertp));
1209
        _M_functions.push_back(function_type(base_type::_M_emplace));
1210
        _M_functions.push_back(function_type(base_type::_M_emplaceh));
1211
        _M_functions.push_back(function_type(base_type::_M_popf));
1212
        _M_functions.push_back(function_type(base_type::_M_popb));
1213
        _M_functions.push_back(function_type(base_type::_M_pushf));
1214
        _M_functions.push_back(function_type(base_type::_M_pushb));
1215
        _M_functions.push_back(function_type(base_type::_M_rehash));
1216
        _M_functions.push_back(function_type(base_type::_M_swap));
1217
 
1218
        // Last.
1219
        _M_functions.push_back(function_type(base_type::_M_clear));
1220
 
1221
        // Run tests.
1222
        for (auto i = _M_functions.begin(); i != _M_functions.end(); ++i)
1223
          {
1224
            function_type& f = *i;
1225
            run_steps_to_limit(f);
1226
          }
1227
      }
1228
 
1229
      template<typename _Funct>
1230
        void
1231
        run_steps_to_limit(const _Funct& __f)
1232
        {
1233
          size_t i(1);
1234
          bool exit(false);
1235
          auto a = _M_container.get_allocator();
1236
 
1237
          do
1238
            {
1239
              // Use the current step as an allocator label.
1240
              a.set_label(i);
1241
 
1242
              try
1243
                {
1244
                  condition_type::limit_adjustor limit(i);
1245
                  __f(_M_container);
1246
 
1247
                  // If we get here, done.
1248
                  exit = true;
1249
                }
1250
              catch(const __gnu_cxx::forced_error&)
1251
                {
1252
                  // Check this step for allocations.
1253
                  // NB: Will throw std::logic_error if allocations.
1254
                  a.check_allocated(i);
1255
 
1256
                  // Check memory allocated with operator new.
1257
 
1258
                  ++i;
1259
                }
1260
            }
1261
          while (!exit);
1262
 
1263
          // Log count info.
1264
          std::cout << __f.target_type().name() << std::endl;
1265
          std::cout << "end count " << i << std::endl;
1266
        }
1267
  };
1268
 
1269
 
1270
  // Run through all member functions with a no throw requirement, sudden death.
1271
  // all: member functions erase, pop_back, pop_front, swap
1272
  //      iterator copy ctor, assignment operator
1273
  // unordered and associative: clear
1274
  // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
1275
  template<typename _Tp>
1276
    struct generation_prohibited : public test_base<_Tp>
1277
    {
1278
      typedef _Tp                                       container_type;
1279
      typedef test_base<container_type>                 base_type;
1280
      typedef typename base_type::populate              populate;
1281
      typedef __gnu_cxx::random_condition               condition_type;
1282
 
1283
      container_type                                    _M_container;
1284
 
1285
      generation_prohibited()  { run(); }
1286
 
1287
      void
1288
      run()
1289
      {
1290
        // Furthermore, assumes that the test functor will throw
1291
        // forced_exception via throw_allocator, that all errors are
1292
        // propagated and in error. Sudden death!
1293
 
1294
        // Setup.
1295
        {
1296
          condition_type::never_adjustor off;
1297
          populate p1(_M_container);
1298
          populate p2(base_type::_M_swap._M_other);
1299
        }
1300
 
1301
        // Run tests.
1302
        {
1303
          condition_type::always_adjustor on;
1304
 
1305
          // NB: Vector and deque are special, erase can throw if the copy
1306
          // constructor or assignment operator of value_type throws.
1307
          if (!traits<container_type>::has_throwing_erase::value)
1308
            {
1309
              this->_M_erasep(_M_container);
1310
              this->_M_eraser(_M_container);
1311
            }
1312
 
1313
          this->_M_popf(_M_container);
1314
          this->_M_popb(_M_container);
1315
 
1316
          this->_M_iops(_M_container);
1317
          this->_M_ciops(_M_container);
1318
 
1319
          this->_M_swap(_M_container);
1320
 
1321
          // Last.
1322
          this->_M_clear(_M_container);
1323
        }
1324
      }
1325
    };
1326
 
1327
 
1328
  // Test strong exception guarantee.
1329
  // Run through all member functions with a roll-back, consistent
1330
  // coherent requirement.
1331
  // all: member functions insert of a single element, push_back, push_front
1332
  // unordered: rehash
1333
  template<typename _Tp>
1334
    struct propagation_consistent : public test_base<_Tp>
1335
    {
1336
      typedef _Tp                                       container_type;
1337
      typedef test_base<container_type>                 base_type;
1338
      typedef typename base_type::populate              populate;
1339
      typedef std::function<void(container_type&)>      function_type;
1340
      typedef __gnu_cxx::limit_condition                condition_type;
1341
 
1342
      using base_type::compare;
1343
 
1344
      container_type                                    _M_container_test;
1345
      container_type                                    _M_container_control;
1346
      std::vector<function_type>                        _M_functions;
1347
 
1348
      propagation_consistent() { run(); }
1349
 
1350
      void
1351
      sync()
1352
      { _M_container_test = _M_container_control; }
1353
 
1354
      // Run test.
1355
      void
1356
      run()
1357
      {
1358
        // Setup.
1359
        condition_type::never_adjustor off;
1360
 
1361
        // Construct containers.
1362
        populate p(_M_container_control);
1363
        sync();
1364
 
1365
        // Construct list of member functions to exercise.
1366
        _M_functions.push_back(function_type(base_type::_M_pushf));
1367
        _M_functions.push_back(function_type(base_type::_M_pushb));
1368
        _M_functions.push_back(function_type(base_type::_M_insertp));
1369
        _M_functions.push_back(function_type(base_type::_M_rehash));
1370
 
1371
        // Run tests.
1372
        for (auto i = _M_functions.begin(); i != _M_functions.end(); ++i)
1373
          {
1374
            function_type& f = *i;
1375
            run_steps_to_limit(f);
1376
          }
1377
      }
1378
 
1379
      template<typename _Funct>
1380
        void
1381
        run_steps_to_limit(const _Funct& __f)
1382
        {
1383
          size_t i(1);
1384
          bool exit(false);
1385
 
1386
          do
1387
            {
1388
              sync();
1389
 
1390
              try
1391
                {
1392
                  condition_type::limit_adjustor limit(i);
1393
                  __f(_M_container_test);
1394
 
1395
                  // If we get here, done.
1396
                  exit = true;
1397
                }
1398
              catch(const __gnu_cxx::forced_error&)
1399
                {
1400
                  compare(_M_container_control, _M_container_test);
1401
                  ++i;
1402
                }
1403
            }
1404
          while (!exit);
1405
 
1406
          // Log count info.
1407
          std::cout << __f.target_type().name() << std::endl;
1408
          std::cout << "end count " << i << std::endl;
1409
        }
1410
    };
1411
 
1412
} // namespace __gnu_test
1413
 
1414
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.