1  // Copyright (C) 2010-2023 Free Software Foundation, Inc.
       2  //
       3  // This file is part of the GNU ISO C++ Library.  This library is free
       4  // software; you can redistribute it and/or modify it under the
       5  // terms of the GNU General Public License as published by the
       6  // Free Software Foundation; either version 3, or (at your option)
       7  // any later version.
       8  //
       9  // This library is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      13  //
      14  // You should have received a copy of the GNU General Public License along
      15  // with this library; see the file COPYING3.  If not see
      16  // <http://www.gnu.org/licenses/>.
      17  //
      18  
      19  #include <vector>
      20  #include <deque>
      21  #include <list>
      22  #ifndef _GLIBCXX_DEBUG
      23  #  include <debug/vector>
      24  #  include <debug/deque>
      25  #  include <debug/list>
      26  #endif
      27  #include <testsuite_hooks.h>
      28  
      29  namespace __gnu_test
      30  {
      31    template<typename _Tp>
      32      struct CopyableValueType
      33      {
      34        typedef _Tp value_type;
      35      };
      36  
      37    template<typename _Tp1, typename _Tp2>
      38      struct CopyableValueType<std::pair<const _Tp1, _Tp2> >
      39      {
      40        typedef std::pair<_Tp1, _Tp2> value_type;
      41      };
      42  
      43    template<typename _Tp>
      44      struct generate_unique
      45      {
      46        typedef _Tp value_type;
      47  
      48        value_type build()
      49        {
      50  	static value_type _S_;
      51  	++_S_;
      52  	return _S_;
      53        }
      54      };
      55  
      56    template<>
      57      struct generate_unique<bool>
      58      {
      59        typedef bool value_type;
      60  
      61        value_type build()
      62        {
      63  	static value_type _S_;
      64  	_S_ = !_S_;
      65  	return _S_;
      66        }
      67      };
      68  
      69    template<typename _Tp1, typename _Tp2>
      70      struct generate_unique<std::pair<_Tp1, _Tp2> >
      71      {
      72        typedef _Tp1 first_type;
      73        typedef _Tp2 second_type;
      74        typedef std::pair<_Tp1, _Tp2> pair_type;
      75  
      76        pair_type build()
      77        {
      78  	static first_type _S_1;
      79  	static second_type _S_2;
      80  	++_S_1;
      81  	++_S_2;
      82  	return pair_type(_S_1, _S_2);
      83        }
      84      };
      85  
      86    // Check that invalid range of pointers is detected
      87    template<typename _Tp>
      88      void
      89      check_assign1()
      90      {
      91        typedef _Tp cont_type;
      92        typedef typename cont_type::value_type cont_val_type;
      93        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
      94        typedef std::vector<val_type> vector_type;
      95  
      96        generate_unique<val_type> gu;
      97  
      98        vector_type v;
      99        for (int i = 0; i != 5; ++i)
     100          v.push_back(gu.build());
     101        VERIFY(v.size() == 5);
     102  
     103        const val_type* first = &v.front() + 1;
     104        const val_type* last = first + 2;
     105  
     106        cont_type c1;
     107        c1.assign(first, last);
     108        VERIFY(c1.size() == 2);
     109  
     110        cont_type c2;
     111        c2.assign(last, first); // Expected failure
     112      }
     113  
     114    // Check that invalid range of debug random iterators is detected
     115    template<typename _Tp>
     116      void
     117      check_assign2()
     118      {
     119        typedef _Tp cont_type;
     120        typedef typename cont_type::value_type cont_val_type;
     121        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     122        typedef std::vector<val_type> vector_type;
     123  
     124        generate_unique<val_type> gu;
     125  
     126        vector_type v;
     127        for (int i = 0; i != 5; ++i)
     128          v.push_back(gu.build());
     129        VERIFY(v.size() == 5);
     130  
     131        typename vector_type::iterator first = v.begin() + 1;
     132        typename vector_type::iterator last = first + 2;
     133        cont_type c1;
     134        c1.assign(first, last);
     135        VERIFY(c1.size() == 2);
     136  
     137        cont_type c2;
     138        c2.assign(last, first); // Expected failure
     139      }
     140  
     141    // Check that invalid range of debug not random iterators is detected
     142    template<typename _Tp>
     143      void
     144      check_assign3()
     145      {
     146        typedef _Tp cont_type;
     147        typedef typename cont_type::value_type cont_val_type;
     148        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     149        typedef std::list<val_type> list_type;
     150  
     151        generate_unique<val_type> gu;
     152  
     153        list_type l;
     154        for (int i = 0; i != 5; ++i)
     155          l.push_back(gu.build());
     156        VERIFY(l.size() == 5);
     157  
     158        typename list_type::iterator first = l.begin(); ++first;
     159        typename list_type::iterator last = first; ++last; ++last;
     160        cont_type c1;
     161        c1.assign(first, last);
     162        VERIFY(c1.size() == 2);
     163  
     164        cont_type c2;
     165        c2.assign(last, first); // Expected failure
     166      }
     167  
     168    // Check that invalid range of pointers is detected
     169    template<typename _Tp>
     170      void
     171      check_construct1()
     172      {
     173        typedef _Tp cont_type;
     174        typedef typename cont_type::value_type cont_val_type;
     175        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     176        typedef std::vector<val_type> vector_type;
     177  
     178        generate_unique<val_type> gu;
     179  
     180        vector_type v;
     181        for (int i = 0; i != 5; ++i)
     182          v.push_back(gu.build());
     183        VERIFY(v.size() == 5);
     184  
     185        val_type *first = &v.front() + 1;
     186        val_type *last = first + 2;
     187  
     188        cont_type c(last, first); // Expected failure
     189      }
     190  
     191    // Check that invalid range of debug random iterators is detected
     192    template<typename _Tp>
     193      void
     194      check_construct2()
     195      {
     196        typedef _Tp cont_type;
     197        typedef typename cont_type::value_type cont_val_type;
     198        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     199        typedef std::vector<val_type> vector_type;
     200  
     201        generate_unique<val_type> gu;
     202  
     203        vector_type v;
     204        for (int i = 0; i != 5; ++i)
     205          v.push_back(gu.build());
     206        VERIFY(v.size() == 5);
     207  
     208        typename vector_type::iterator first = v.begin() + 1;
     209        typename vector_type::iterator last = first + 2;
     210  
     211        cont_type c(last, first); // Expected failure
     212      }
     213  
     214    // Check that invalid range of debug not random iterators is detected
     215    template<typename _Tp>
     216      void
     217      check_construct3()
     218      {
     219        typedef _Tp cont_type;
     220        typedef typename cont_type::value_type cont_val_type;
     221        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     222        typedef std::list<val_type> list_type;
     223  
     224        generate_unique<val_type> gu;
     225  
     226        list_type l;
     227        for (int i = 0; i != 5; ++i)
     228          l.push_back(gu.build());
     229        VERIFY(l.size() == 5);
     230  
     231        typename list_type::iterator first = l.begin(); ++first;
     232        typename list_type::iterator last = first; ++last; ++last;
     233  
     234        cont_type c(last, first); // Expected failure
     235      }
     236  
     237    template <typename _Cont>
     238      struct InsertRangeHelper
     239      {
     240        template <typename _It>
     241          static void
     242          Insert(_Cont& cont, _It first, _It last)
     243  	{ cont.insert(first, last); }
     244      };
     245  
     246    template <typename _Cont>
     247      struct InsertRangeHelperAux
     248      {
     249        template <typename _It>
     250          static void
     251          Insert(_Cont& cont, _It first, _It last)
     252  	{ cont.insert(cont.begin(), first, last); }
     253      };
     254  
     255    template <typename _Tp1, typename _Tp2>
     256      struct InsertRangeHelper<std::vector<_Tp1, _Tp2> >
     257      : InsertRangeHelperAux<std::vector<_Tp1, _Tp2> >
     258      { };
     259  
     260    template <typename _Tp1, typename _Tp2>
     261      struct InsertRangeHelper<std::deque<_Tp1, _Tp2> >
     262      : InsertRangeHelperAux<std::deque<_Tp1, _Tp2> >
     263      { };
     264  
     265    template <typename _Tp1, typename _Tp2>
     266      struct InsertRangeHelper<std::list<_Tp1, _Tp2> >
     267      : InsertRangeHelperAux<std::list<_Tp1, _Tp2> >
     268      { };
     269  
     270  #ifndef _GLIBCXX_DEBUG
     271    template <typename _Tp1, typename _Tp2>
     272      struct InsertRangeHelper<__gnu_debug::vector<_Tp1, _Tp2> >
     273      : InsertRangeHelperAux<__gnu_debug::vector<_Tp1, _Tp2> >
     274      { };
     275  
     276    template <typename _Tp1, typename _Tp2>
     277      struct InsertRangeHelper<__gnu_debug::deque<_Tp1, _Tp2> >
     278      : InsertRangeHelperAux<__gnu_debug::deque<_Tp1, _Tp2> >
     279      { };
     280  
     281    template <typename _Tp1, typename _Tp2>
     282      struct InsertRangeHelper<__gnu_debug::list<_Tp1, _Tp2> >
     283      : InsertRangeHelperAux<__gnu_debug::list<_Tp1, _Tp2> >
     284      { };
     285  #endif
     286  
     287    template<typename _Tp>
     288      void
     289      check_insert1()
     290      {
     291        typedef _Tp cont_type;
     292        typedef typename cont_type::value_type cont_val_type;
     293        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     294        typedef std::vector<val_type> vector_type;
     295  
     296        generate_unique<val_type> gu;
     297  
     298        vector_type v;
     299        for (int i = 0; i != 5; ++i)
     300          v.push_back(gu.build());
     301        VERIFY(v.size() == 5);
     302  
     303        const val_type* first = &v.front() + 1;
     304        const val_type* last = first + 2;
     305  
     306        cont_type c1;
     307        InsertRangeHelper<cont_type>::Insert(c1, first, last);
     308        VERIFY(c1.size() == 2);
     309  
     310        cont_type c2;
     311        InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
     312      }
     313  
     314    template<typename _Tp>
     315      void
     316      check_insert2()
     317      {
     318        typedef _Tp cont_type;
     319        typedef typename cont_type::value_type cont_val_type;
     320        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     321        typedef std::vector<val_type> vector_type;
     322  
     323        generate_unique<val_type> gu;
     324  
     325        vector_type v;
     326        for (int i = 0; i != 5; ++i)
     327          v.push_back(gu.build());
     328        VERIFY(v.size() == 5);
     329  
     330        typename vector_type::iterator first = v.begin() + 1;
     331        typename vector_type::iterator last = first + 2;
     332  
     333        cont_type c1;
     334        InsertRangeHelper<cont_type>::Insert(c1, first, last);
     335        VERIFY(c1.size() == 2);
     336  
     337        cont_type c2;
     338        InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
     339      }
     340  
     341    template<typename _Tp>
     342      void
     343      check_insert3()
     344      {
     345        typedef _Tp cont_type;
     346        typedef typename cont_type::value_type cont_val_type;
     347        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     348        typedef std::list<val_type> list_type;
     349  
     350        generate_unique<val_type> gu;
     351  
     352        list_type l;
     353        for (int i = 0; i != 5; ++i)
     354          l.push_back(gu.build());
     355        VERIFY(l.size() == 5);
     356  
     357        typename list_type::iterator first = l.begin(); ++first;
     358        typename list_type::iterator last = first; ++last; ++last;
     359  
     360        cont_type c1;
     361        InsertRangeHelper<cont_type>::Insert(c1, first, last);
     362        VERIFY(c1.size() == 2);
     363  
     364        cont_type c2;
     365        InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
     366      }
     367  
     368    template<typename _Tp>
     369      void
     370      check_insert4()
     371      {
     372        typedef _Tp cont_type;
     373        typedef typename cont_type::value_type cont_val_type;
     374        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     375        typedef std::list<val_type> list_type;
     376  
     377        generate_unique<val_type> gu;
     378  
     379        list_type l;
     380        for (int i = 0; i != 5; ++i)
     381          l.push_back(gu.build());
     382        VERIFY(l.size() == 5);
     383  
     384        typename list_type::iterator first = l.begin(); ++first;
     385        typename list_type::iterator last = first; ++last; ++last;
     386  
     387        cont_type c1;
     388        InsertRangeHelper<cont_type>::Insert(c1, l.begin(), l.end());
     389        VERIFY(c1.size() == 5);
     390  
     391        c1.insert(c1.begin(), c1.begin(), c1.end()); // Expected failure.
     392      }
     393  
     394    template<typename _Tp>
     395      void use_invalid_iterator()
     396      {
     397        typedef _Tp cont_type;
     398        typedef typename cont_type::value_type cont_val_type;
     399        typedef typename CopyableValueType<cont_val_type>::value_type val_type;
     400        generate_unique<val_type> gu;
     401  
     402        cont_type c;
     403        for (size_t i = 0; i != 5; ++i)
     404  	c.insert(gu.build());
     405  
     406        typename cont_type::iterator it = c.begin();
     407        cont_val_type val = *it;
     408        c.clear();
     409        VERIFY( *it == val );
     410      }
     411  }
     412