This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Basic exception guarantee testcases (redux)


On November 25, 2002 01:49 pm, Benjamin Kosnik wrote:
> Please send me a complete patch, with the new and old bits integrated,
> and I'll do this today.

ChangeLog

2002-11-25  Stephen M. Webb <stephen@bregmasoft.com>

  * testsuite/testsuite_allocator.h: New file.
  * testsuite/testsuite_allocator.cc: New file.
  * testsuite/Makefile.am: Added testsuite_allocator to test library.
  * testsuite/testsuite_hooks.h: Added more detailed tracker objects
    gnu_copy_constructor, gnu_assignment_operator, and gnu_destructor.
  * testsuite/testsuite_hooks.cc: Added new static objects definitions.
  * testsuite/23_containers/vector_capacity.cc: Added reserve() tests.
  * testsuite/23_containers/vector_ctor.cc: Added a plethora of tests.
  * testsuite/23_containers/deque_ctor.cc: Added a slew of new tests.

Index: testsuite/testsuite_hooks.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/testsuite_hooks.h,v
retrieving revision 1.10
diff -c -3 -p -r1.10 testsuite_hooks.h
*** testsuite/testsuite_hooks.h	2 Aug 2002 16:04:16 -0000	1.10
--- testsuite/testsuite_hooks.h	25 Nov 2002 19:14:21 -0000
*************** struct gnu_counting_struct
*** 100,156 ****
  
  #define assert_count(n)   VERIFY(gnu_counting_struct::count == n)
  
  
  class gnu_copy_tracker
  {
    public:
!     // Cannot be explicit.  Conversion ctor used by list_modifiers.cc's
!     // test03(), "range fill at beginning".
!     gnu_copy_tracker (int anId, bool throwOnDemand = false)
!     : itsId(anId), willThrow(throwOnDemand)
!     {}
! 
!     gnu_copy_tracker (const gnu_copy_tracker& rhs)
!     : itsId(rhs.id()), willThrow(rhs.willThrow)
      {
-       ++itsCopyCount;
-       if (willThrow) 
- 	__throw_exception_again "copy tracker exception";
      }
  
!     gnu_copy_tracker& operator=(const gnu_copy_tracker& rhs)
      {
!       itsId = rhs.id();
!       // willThrow must obviously already be false to get this far
      }
  
!     ~gnu_copy_tracker() { ++itsDtorCount; }
  
      int
      id() const
!     { return itsId; }
  
    private:
!           int   itsId;
!     const bool  willThrow;
  
    public:
      static void
      reset()
!     { itsCopyCount = 0; itsDtorCount = 0; }
  
      static int
      copyCount() 
!     { return itsCopyCount; }
  
      static int
      dtorCount() 
!     { return itsDtorCount; }
  
    private:
!     static int itsCopyCount;
!     static int itsDtorCount;
  };
  
  struct gnu_char
  {
--- 100,273 ----
  
  #define assert_count(n)   VERIFY(gnu_counting_struct::count == n)
  
+ // A (static) class for counting copy constructors and possibly throwing an
+ // exception on a desired count.
+ class gnu_copy_constructor
+ {
+ public:
+   static unsigned int
+   count()
+   { return count_; }
+ 
+   static void
+   mark_call()
+   {
+     count_++;
+     if (count_ == throw_on_)
+     {
+       __throw_exception_again "copy constructor exception";
+     }
+   }
+ 
+   static void
+   reset()
+   {
+     count_ = 0;
+     throw_on_ = 0;
+   }
+ 
+   static void
+   throw_on(unsigned int count)
+   { throw_on_ = count; }
+ 
+ private:
+   static unsigned int count_;
+   static unsigned int throw_on_;
+ };
+ 
+ // A (static) class for counting assignment operator calls and possibly
+ // throwing an exception on a desired count.
+ class gnu_assignment_operator
+ {
+ public:
+   static unsigned int
+   count()
+   { return count_; }
+ 
+   static void
+   mark_call()
+   {
+     count_++;
+     if (count_ == throw_on_)
+     {
+       __throw_exception_again "assignment operator exception";
+     }
+   }
+ 
+   static void
+   reset()
+   {
+     count_ = 0;
+     throw_on_ = 0;
+   }
+ 
+   static void
+   throw_on(unsigned int count)
+   { throw_on_ = count; }
+ 
+ private:
+   static unsigned int count_;
+   static unsigned int throw_on_;
+ };
  
+ // A (static) class for tracking calls to an object's destructor.
+ class gnu_destructor
+ {
+ public:
+   static unsigned int
+   count()
+   { return count_; }
+ 
+   static void
+   mark_call()
+   { count_++; }
+ 
+   static void
+   reset()
+   { count_ = 0; }
+ 
+ private:
+   static unsigned int count_;
+ };
+ 
+ // An class of objects that can be used for validating various behaviours 
and
+ // guarantees of containers and algorithms defined in the standard library.
  class gnu_copy_tracker
  {
    public:
!     // Creates a copy-tracking object with the given ID number.
!     // If "throw_on_copy" is set, an exception will be thrown if
!     // an attempt is made to copy this object.
!     gnu_copy_tracker(int id = next_id_--, bool throw_on_copy = false)
!     : id_(id)
!     , throw_on_copy_(throw_on_copy)
      {
      }
  
!     // Copy-constructs the object, marking a call to the copy
!     // constructor and forcing an exception if indicated.
!     gnu_copy_tracker(const gnu_copy_tracker& rhs)
!     : id_(rhs.id()), throw_on_copy_(rhs.throw_on_copy_)
      {
!       int kkk = throw_on_copy_;
!       if (throw_on_copy_)
!       {
!         gnu_copy_constructor::throw_on(gnu_copy_constructor::count() + 1);
!       }
!       gnu_copy_constructor::mark_call();
      }
  
!     // Assigns the value of another object to this one, tracking the number 
of
!     // times this member function has been called and if the other object is
!     // supposed to throw an exception when it is copied, well, make it so.
!     gnu_copy_tracker&
!     operator=(const gnu_copy_tracker& rhs)
!     { 
!       id_            = rhs.id();
!       if (rhs.throw_on_copy_)
!       {
!         gnu_assignment_operator::throw_on(gnu_assignment_operator::count() 
+ 1);
!       }
!       gnu_assignment_operator::mark_call();
!     }
! 
!     ~gnu_copy_tracker()
!     { gnu_destructor::mark_call(); }
  
      int
      id() const
!     { return id_; }
  
    private:
!           int   id_;
!     const bool  throw_on_copy_;
  
    public:
      static void
      reset()
!     {
!       gnu_copy_constructor::reset();
!       gnu_assignment_operator::reset();
!       gnu_destructor::reset();
!     }
  
+     // for backwards-compatibility
      static int
      copyCount() 
!     { return gnu_copy_constructor::count(); }
  
+     // for backwards-compatibility
      static int
      dtorCount() 
!     { return gnu_destructor::count(); }
  
    private:
!     static int next_id_;
  };
+ 
+ inline bool
+ operator==(const gnu_copy_tracker& lhs, const gnu_copy_tracker& rhs)
+ { return lhs.id() == rhs.id(); }
  
  struct gnu_char
  {
Index: testsuite/testsuite_hooks.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/testsuite_hooks.cc,v
retrieving revision 1.4
diff -c -3 -p -r1.4 testsuite_hooks.cc
*** testsuite/testsuite_hooks.cc	24 Oct 2002 23:27:27 -0000	1.4
--- testsuite/testsuite_hooks.cc	25 Nov 2002 19:14:21 -0000
*************** __set_testsuite_memlimit(float) { }
*** 78,83 ****
  
  gnu_counting_struct::size_type  gnu_counting_struct::count = 0;
  
! int gnu_copy_tracker::itsCopyCount = 0;
! int gnu_copy_tracker::itsDtorCount = 0;
  
--- 78,87 ----
  
  gnu_counting_struct::size_type  gnu_counting_struct::count = 0;
  
! unsigned int gnu_copy_constructor::count_ = 0;
! unsigned int gnu_copy_constructor::throw_on_ = 0;
! unsigned int gnu_assignment_operator::count_ = 0;
! unsigned int gnu_assignment_operator::throw_on_ = 0;
! unsigned int gnu_destructor::count_ = 0;
!          int gnu_copy_tracker::next_id_ = 0;
  
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/Makefile.am,v
retrieving revision 1.11
diff -c -3 -p -r1.11 Makefile.am
*** testsuite/Makefile.am	1 Sep 2002 18:09:18 -0000	1.11
--- testsuite/Makefile.am	25 Nov 2002 19:14:21 -0000
*************** INCLUDES = \
*** 51,57 ****
  
  ## Build support library.
  noinst_LIBRARIES = libv3test.a
! libv3test_a_SOURCES = testsuite_hooks.cc
  
  ## Build support utilities.
  ## Only build this as native, as need to find startup files and libc to 
link.
--- 51,57 ----
  
  ## Build support library.
  noinst_LIBRARIES = libv3test.a
! libv3test_a_SOURCES = testsuite_hooks.cc testsuite_allocator.cc
  
  ## Build support utilities.
  ## Only build this as native, as need to find startup files and libc to 
link.
Index: testsuite/23_containers/vector_capacity.cc
===================================================================
RCS file: 
/cvs/gcc/gcc/libstdc++-v3/testsuite/23_containers/vector_capacity.cc,v
retrieving revision 1.5
diff -c -3 -p -r1.5 vector_capacity.cc
*** testsuite/23_containers/vector_capacity.cc	16 Nov 2002 17:16:31 -0000	1.5
--- testsuite/23_containers/vector_capacity.cc	25 Nov 2002 19:14:21 -0000
***************
*** 23,28 ****
--- 23,29 ----
  
  #include <vector>
  #include <stdexcept>
+ #include <testsuite_allocator.h>
  #include <testsuite_hooks.h>
  
  template<typename T>
*************** void test03()
*** 119,128 ****
--- 120,190 ----
    VERIFY( test );
  }
  
+ // Verifies basic functionality of reserve() with forced reallocation.
+ void
+ test_reserve()
+ {
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(3);
+     const X::size_type old_size     = a.size();
+     const X::size_type old_capacity = a.capacity();
+     const X::size_type new_capacity = old_capacity + 10;
+     T::reset();
+     
+     a.reserve(new_capacity);
+ 
+     // [23.2.4.1 (2)]
+     VERIFY(new_capacity <= a.capacity());
+     // [23.2.4.1 (3)]
+     VERIFY(old_size == a.size());
+     VERIFY(gnu_copy_constructor::count() <= old_size);
+     VERIFY(gnu_destructor::count() <= old_size);
+   }
+   // check for memory leaks
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ }
+ 
+ // Verifies that reserve() with reallocation offers the strong exception 
guarantee.
+ void
+ test_reserve_exception_guarantee()
+ {
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     const X::size_type old_size     = a.size();
+     const X::size_type old_capacity = a.capacity();
+     const X::size_type new_capacity = old_capacity + 10;
+     T::reset();
+     gnu_copy_constructor::throw_on(3);
+     
+     try
+     {
+       a.reserve(new_capacity);
+       VERIFY(("no exception thrown", false));
+     }
+     catch (...)
+     {
+     }
+ 
+     VERIFY(old_capacity == a.capacity());
+     VERIFY(gnu_copy_constructor::count() == gnu_destructor::count()+1);
+   }
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ }
+ 
  int main()
  {
    test01();
    test02();
    test03();
+   test_reserve();
+   test_reserve_exception_guarantee();
    return 0;
  }
Index: testsuite/23_containers/vector_ctor.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/23_containers/vector_ctor.cc,v
retrieving revision 1.8
diff -c -3 -p -r1.8 vector_ctor.cc
*** testsuite/23_containers/vector_ctor.cc	1 May 2002 02:17:35 -0000	1.8
--- testsuite/23_containers/vector_ctor.cc	25 Nov 2002 19:14:22 -0000
***************
*** 22,27 ****
--- 22,28 ----
  
  #include <vector>
  #include <string>
+ #include <testsuite_allocator.h>
  #include <testsuite_hooks.h>
  
  template<typename T>
*************** void test04()
*** 94,105 ****
--- 95,641 ----
  #endif
  }
  
+ 
+ // @fn test_default_ctor_exception_gurantee
+ // This test verifies that if one of the vector's contained objects throws
+ // an exception from its constructor while the vector is being constructed 
and
+ // filled with default values, all memory is returned to the allocator 
whence
+ // it came.
+ void
+ test_default_ctor_exception_gurantee()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_copy_tracker::reset();
+   gnu_copy_constructor::throw_on(3);
+   gnu_allocator_tracker::resetCounts();
+ 
+   // run test
+   try
+   {
+     X a(7);
+     VERIFY(("no exception thrown", false));
+   }
+   catch (...)
+   {
+   }
+ 
+   // assert postconditions
+   VERIFY(("memory leak detected:",
+           gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal()));
+ 
+   // teardown
+ }
+ 
+ // @fn test_copy_ctor_exception_gurantee
+ // This test verifies that if one of the vector's contained objects throws
+ // an exception from its constructor while the vector is being copy
+ // constructed, all memory is returned to the allocator whence it came.
+ void
+ test_copy_ctor_exception_gurantee()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     gnu_copy_tracker::reset();
+     gnu_copy_constructor::throw_on(3);
+ 
+     // run test
+     try
+     {
+       X u(a);
+       VERIFY(("no exception thrown", false));
+     }
+     catch (...)
+     {
+     }
+   }
+ 
+   // assert postconditions
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ // operator=()
+ //
+ // case 1: lhs.size() > rhs.size()
+ // case 2: lhs.size() < rhs.size() < lhs.capacity()
+ // case 3: lhs.capacity() < rhs.size()
+ //
+ void
+ test_assignment_operator_1()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X r(9);
+   X a(r.size() - 2);
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // preconditions
+   VERIFY(r.size() > a.size());
+ 
+   // run test
+   r = a;
+ 
+   // assert postconditions
+   VERIFY(r == a);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_assignment_operator_2()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X r(1);
+   r.reserve(17);
+   X a(r.size() + 7);
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // preconditions
+   VERIFY(r.size() < a.size());
+   VERIFY(a.size() < r.capacity());
+ 
+   // run test
+   r = a;
+ 
+   // assert postconditions
+   VERIFY(r == a);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_assignment_operator_3()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X r(1);
+     X a(r.capacity() + 7);
+     gnu_copy_tracker::reset();
+ 
+     // preconditions
+     VERIFY(r.capacity() < a.size());
+ 
+     // run test
+     r = a;
+ 
+     // assert postconditions
+     VERIFY(r == a);
+   }
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_assignment_operator_3_exception_guarantee()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X r(1);
+     X a(r.capacity() + 7);
+     gnu_copy_tracker::reset();
+     gnu_copy_constructor::throw_on(3);
+ 
+     // preconditions
+     VERIFY(r.capacity() < a.size());
+ 
+     // run test
+     try
+     {
+       r = a;
+       VERIFY(("no exception thrown", false));
+     }
+     catch (...)
+     {
+     }
+   }
+ 
+   // assert postconditions
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ // fill assign()
+ //
+ // case 1: [23.2.4.1 (3)] n <= size()
+ // case 2: [23.2.4.1 (3)] size() < n <= capacity()
+ // case 3: [23.2.4.1 (3)] n > capacity()
+ // case 4: [23.2.4.1 (3)] n > capacity(), exception guarantees
+ // case 5: [23.1.1 (9)] fill assign disguised as a range assign
+ //
+ void
+ test_fill_assign_1()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X a(7);
+   X::size_type old_size = a.size();
+   X::size_type new_size = old_size - 2;
+   const T t;
+ 
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // run test
+   a.assign(new_size, t);
+ 
+   // assert postconditions
+   VERIFY(a.size() == new_size);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_fill_assign_2()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X a(7);
+   a.reserve(11);
+   X::size_type old_size     = a.size();
+   X::size_type old_capacity = a.capacity();
+   X::size_type new_size     = old_size + 2;
+   const T t;
+ 
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // assert preconditions
+   VERIFY(old_size < new_size);
+   VERIFY(new_size <= old_capacity);
+ 
+   // run test
+   a.assign(new_size, t);
+ 
+   // assert postconditions
+   VERIFY(a.size() == new_size);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_fill_assign_3()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     X::size_type old_size     = a.size();
+     X::size_type old_capacity = a.capacity();
+     X::size_type new_size     = old_capacity + 4;
+     const T t;
+ 
+     gnu_copy_tracker::reset();
+ 
+     // assert preconditions
+     VERIFY(new_size > old_capacity);
+ 
+     // run test
+     a.assign(new_size, t);
+ 
+     // assert postconditions
+     VERIFY(a.size() == new_size);
+   }
+ 
+   VERIFY(gnu_allocator_tracker::allocationTotal() > 0);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_fill_assign_3_exception_guarantee()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     X::size_type old_size     = a.size();
+     X::size_type old_capacity = a.capacity();
+     X::size_type new_size     = old_capacity + 4;
+     const T t;
+ 
+     gnu_copy_tracker::reset();
+     gnu_copy_constructor::throw_on(3);
+ 
+     // assert preconditions
+     VERIFY(new_size > old_capacity);
+ 
+     // run test
+     try
+     {
+       a.assign(new_size, t);
+       VERIFY(("no exception thrown", false));
+     }
+     catch (...)
+     {
+     }
+ 
+     // assert postconditions
+     VERIFY(a.size() == old_size);
+     VERIFY(a.capacity() == old_capacity);
+   }
+ 
+   VERIFY(gnu_allocator_tracker::allocationTotal() > 0);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_fill_assign_4()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X a(7);
+   X::size_type old_size  = a.size();
+   X::size_type new_size  = old_size - 2;
+   X::size_type new_value = 117;
+ 
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // run test
+   a.assign(new_size, new_value);
+ 
+   // assert postconditions
+   VERIFY(a.size() == new_size);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ // range assign()
+ //
+ // case 1: [23.2.4.1 (2)] input iterator
+ // case 2: [23.2.4.1 (2)] forward iterator, distance(first, last) <= size()
+ // case 3: [23.2.4.1 (2)] forward iterator, size() < distance(first, last) 
<= capacity()
+ // case 4: [23.2.4.1 (2)] forward iterator, distance(first, last) > 
capacity()
+ // case 5: [23.2.4.1 (2)] forward iterator, distance(first, last) > 
capacity(), exception guarantees
+ void
+ test_range_assign_1()
+ {
+   // @TODO
+ }
+ 
+ void
+ test_range_assign_2()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X a(7);
+   X b(3);
+   X::size_type old_size = a.size();
+ 
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // assert preconditions
+   VERIFY(b.size() < a.capacity());
+ 
+   // run test
+   a.assign(b.begin(), b.end());
+ 
+   // assert postconditions
+   VERIFY(a.size() == b.size());
+   VERIFY(a == b);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_range_assign_3()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   X a(7);
+   a.reserve(a.size() + 7);
+   X b(a.size() + 3);
+   X::size_type old_size = a.size();
+ 
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ 
+   // assert preconditions
+   VERIFY(a.size() < b.size());
+   VERIFY(b.size() < a.capacity());
+ 
+   // run test
+   a.assign(b.begin(), b.end());
+ 
+   // assert postconditions
+   VERIFY(a.size() == b.size());
+   VERIFY(a == b);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 0);
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_range_assign_4()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     X b(a.capacity() + 7);
+     X::size_type old_size = a.size();
+ 
+     gnu_copy_tracker::reset();
+ 
+     // assert preconditions
+     VERIFY(b.size() > a.capacity());
+ 
+     // run test
+     a.assign(b.begin(), b.end());
+ 
+     // assert postconditions
+     VERIFY(a.size() == b.size());
+     VERIFY(a == b);
+   }
+   VERIFY(gnu_allocator_tracker::allocationTotal() > 0);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ void
+ test_range_assign_4_exception_guarantee()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::vector<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     X b(a.capacity() + 7);
+     X::size_type old_size = a.size();
+ 
+     gnu_copy_tracker::reset();
+     gnu_copy_constructor::throw_on(3);
+ 
+     // assert preconditions
+     VERIFY(b.size() > a.capacity());
+ 
+     // run test
+     try
+     {
+       a.assign(b.begin(), b.end());
+       VERIFY(("no exception thrown", false));
+     }
+     catch (...)
+     {
+     }
+   }
+ 
+   // assert postconditions
+   VERIFY(gnu_allocator_tracker::allocationTotal() > 0);
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+   gnu_copy_tracker::reset();
+   gnu_allocator_tracker::resetCounts();
+ }
+ 
+ 
  int main()
  {
    test01();
    test02(); 
    test03();
    test04();
+   test_default_ctor_exception_gurantee();
+   test_copy_ctor_exception_gurantee();
+   test_assignment_operator_1();
+   test_assignment_operator_2();
+   test_assignment_operator_3();
+   test_assignment_operator_3_exception_guarantee();
+   test_fill_assign_1();
+   test_fill_assign_2();
+   test_fill_assign_3();
+   test_fill_assign_3_exception_guarantee();
+   test_fill_assign_4();
+   test_range_assign_1();
+   test_range_assign_2();
+   test_range_assign_3();
+   test_range_assign_4();
+   test_range_assign_4_exception_guarantee();
  
    return 0;
  }
Index: testsuite/23_containers/deque_ctor.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/23_containers/deque_ctor.cc,v
retrieving revision 1.1
diff -c -3 -p -r1.1 deque_ctor.cc
*** testsuite/23_containers/deque_ctor.cc	27 Dec 2001 21:51:28 -0000	1.1
--- testsuite/23_containers/deque_ctor.cc	25 Nov 2002 19:57:18 -0000
***************
*** 21,32 ****
  // 23.2.1.1 deque constructors, copy, and assignment
  
  #include <deque>
  #include <testsuite_hooks.h>
  
  typedef std::deque<gnu_counting_struct>   gdeque;
  
  
! // basic alloc/dealloc sanity check
  void
  test01()
  {
--- 21,36 ----
  // 23.2.1.1 deque constructors, copy, and assignment
  
  #include <deque>
+ #include <iterator>
+ #include <sstream>
+ #include <testsuite_allocator.h>
  #include <testsuite_hooks.h>
  
  typedef std::deque<gnu_counting_struct>   gdeque;
  
+ bool test = true;
  
! // see http://gcc.gnu.org/ml/libstdc++/2001-11/msg00139.html
  void
  test01()
  {
*************** test01()
*** 38,46 ****
    assert_count (0);
  }
  
  int main()
  {
    test01();
  
!   return 0;
  }
--- 42,531 ----
    assert_count (0);
  }
  
+ 
+ // 23.2.1     required types
+ //
+ // A missing required type will cause a compile failure.
+ //
+ void
+ requiredTypesCheck()
+ {
+   typedef int             T;
+   typedef std::deque<T>   X;
+ 
+   typedef X::reference              reference;
+   typedef X::const_reference        const_reference;
+   typedef X::iterator               iterator;
+   typedef X::const_iterator         const_iterator;
+   typedef X::size_type              size_type;
+   typedef X::difference_type        difference_type;
+   typedef X::value_type             value_type;
+   typedef X::allocator_type         allocator_type;
+   typedef X::pointer                pointer;
+   typedef X::const_pointer          const_pointer;
+   typedef X::reverse_iterator       reverse_iterator;
+   typedef X::const_reverse_iterator const_reverse_iterator;
+ }
+ 
+ 
+ // @fn defaultConstructorCheck
+ // Explicitly checks the default deque constructor and destructor for both
+ // trivial and non-trivial types.  In addition, the size() and empty()
+ // member functions are explicitly checked here since it should be their
+ // first use. Checking those functions means checking the begin() and
+ // end() and their const brethren functions as well.
+ //
+ // @verbatim
+ // 23.2.1.1   default ctor/dtor
+ //  effects:
+ //    23.2.1.1        constructs an empty deque using the specified 
allocator
+ //  postconditions:
+ //    23.1 table 65   u.size() == 0
+ //  throws:
+ //  complexity:
+ //    23.1 table 65   constant
+ //
+ // 23.2.1.2   bool empty() const
+ //  semantics:
+ //    23.1 table 65   a.size() == 0
+ //    23.1 (7)        a.begin() == a.end()
+ //  throws:
+ //  complexity:
+ //    23.1 table 65   constant
+ //
+ // 23.2.1.2   size_type size() const
+ //  semantics:
+ //    23.1 table 65   a.end() - a.begin()
+ //  throws:
+ //  complexity:
+ //    23.1 table 65(A) should be constant
+ //
+ // 23.2.1     iterator begin()
+ //            const_iterator begin() const
+ //            iterator end() 
+ //            const_iterator end() const
+ //  throws:
+ //    23.1 (10) pt. 4 does not throw
+ //  complexity:
+ //    23.1 table 65   constant
+ // @endverbatim
+ void
+ defaultConstructorCheckPOD()
+ {
+   // setup
+   typedef int             T;
+   typedef std::deque<T>   X;
+ 
+   // run test
+   X u;
+ 
+   // assert postconditions
+   VERIFY(u.empty());
+   VERIFY(0 == u.size());
+   VERIFY(u.begin() == u.end());
+   VERIFY(0 == std::distance(u.begin(), u.end()));
+ 
+   // teardown
+ }
+ 
+ 
+ void
+ defaultConstructorCheck()
+ {
+   // setup
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>     X;
+ 
+   gnu_copy_tracker::reset();
+ 
+   // run test
+   const X u;
+ 
+   // assert postconditions
+   VERIFY(u.empty());
+   VERIFY(0 == u.size());
+   VERIFY(u.begin() == u.end());
+   VERIFY(0 == std::distance(u.begin(), u.end()));
+ 
+   // teardown
+ }
+ 
+ 
+ // @fn copyConstructorCheck()
+ // Explicitly checks the deque copy constructor.  Continues verificaton of
+ // ancillary member functions documented under defaultConstructorCheck().
+ //
+ // This check also tests the push_back() member function.
+ //
+ // @verbatim
+ // 23.2.1     copy constructor
+ //  effects:
+ //  postconditions:
+ //    22.1.1 table 65 a == X(a)
+ //                    u == a
+ //  throws:
+ //  complexity:
+ //    22.1.1 table 65 linear
+ // @endverbatim
+ void
+ copyConstructorCheck()
+ {
+   // setup
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>     X;
+ 
+   const int copyBaseSize = 17;  // arbitrary
+ 
+   X a;
+   for (int i = 0; i < copyBaseSize; ++i)
+     a.push_back(i);
+   gnu_copy_tracker::reset();
+ 
+   // assert preconditions
+   VERIFY(!a.empty());
+   VERIFY(copyBaseSize == a.size());
+   VERIFY(a.begin() != a.end());
+   VERIFY(copyBaseSize == std::distance(a.begin(), a.end()));
+ 
+   // run test
+   X u = a;
+ 
+   // assert postconditions
+   VERIFY(u == a);
+   VERIFY(copyBaseSize == gnu_copy_constructor::count());
+ 
+   // teardown
+ }
+ 
+ 
+ // @fn fillConstructorCheck()
+ // This test explicitly verifies the basic fill constructor.  Like the 
default
+ // constructor, later tests depend on the fill constructor working 
correctly.
+ // That means this explicit test should preceed the later tests so the error
+ // message given on assertion failure can be more helpful n tracking the
+ // problem.
+ // 
+ // 23.2.1.1   fill constructor
+ //  complexity:
+ //    23.2.1.1        linear in N
+ void
+ fillConstructorCheck()
+ {
+   // setup
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>   X;
+ 
+   const X::size_type  n(23);  
+   const X::value_type t(111);
+ 
+   gnu_copy_tracker::reset();
+ 
+   // run test
+   X a(n, t);
+ 
+   // assert postconditions
+   VERIFY(n == a.size());
+   VERIFY(n == gnu_copy_constructor::count());
+ 
+   // teardown
+ }
+ 
+ 
+ // @fn fillConstructorCheck2()
+ // Explicit check for fill constructors masqueraded as range constructors as
+ // elucidated in clause 23.1.1 paragraph 9 of the standard.
+ //
+ // 23.1.1 (9) fill constructor looking like a range constructor
+ void
+ fillConstructorCheck2()
+ {
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>   X;
+ 
+   const int f = 23;  
+   const int l = 111;
+ 
+   gnu_copy_tracker::reset();
+ 
+   X a(f, l);
+ 
+   VERIFY(f == a.size());
+   VERIFY(f == gnu_copy_constructor::count());
+ }
+ 
+ 
+ // @fn rangeConstructorCheckForwardIterator()
+ // This test copies from one deque to another to force the copy
+ // constructor for T to be used because the compiler will kindly
+ // elide copies if the default constructor can be used with
+ // type conversions.  Trust me.
+ //
+ // 23.2.1.1   range constructor, forward iterators
+ void
+ rangeConstructorCheckForwardIterator()
+ {
+   // setup
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>   X;
+ 
+   const X::size_type  n(726); 
+   const X::value_type t(307);
+   X source(n, t);
+   X::iterator i = source.begin();
+   X::iterator j = source.end();
+   X::size_type rangeSize = std::distance(i, j);
+ 
+   gnu_copy_tracker::reset();
+ 
+   // test
+   X a(i, j);
+ 
+   // assert postconditions
+   VERIFY(rangeSize == a.size());
+   VERIFY(gnu_copy_constructor::count() <= rangeSize);
+ }
+ 
+ 
+ // @fn rangeConstructorCheckInputIterator()
+ // An explicit check for range construction on an input iterator
+ // range, which the standard expounds upon as having a different
+ // complexity than forward iterators.
+ //
+ // 23.2.1.1   range constructor, input iterators
+ void
+ rangeConstructorCheckInputIterator()
+ {
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>     X;
+ 
+   std::istringstream ibuf("1234567890123456789");
+   const X::size_type rangeSize = ibuf.str().size();  
+   std::istream_iterator<char>  i(ibuf);
+   std::istream_iterator<char>  j;
+ 
+   gnu_copy_tracker::reset();
+ 
+   X a(i, j);
+ 
+   VERIFY(rangeSize == a.size());
+   VERIFY(gnu_copy_constructor::count() <= (2 * rangeSize));
+ }
+ 
+ 
+ // 23.2.1     copy assignment
+ void
+ copyAssignmentCheck()
+ {
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>     X;
+ 
+   const X::size_type  n(18);  
+   const X::value_type t(1023);
+   X a(n, t);
+   X r;
+ 
+   gnu_copy_tracker::reset();
+ 
+   r = a;
+ 
+   VERIFY(r == a);
+   VERIFY(n == gnu_copy_constructor::count());
+ }
+ 
+ 
+ // 23.2.1.1   fill assignment
+ //
+ // The complexity check must check dtors+copyAssign and copyCtor+copyAssign
+ // because that's the way the SGI implementation works.  Dunno if it's true
+ // standard compliant (which specifies fill assignment in terms of erase and
+ // insert only), but it should work as (most) users expect and is more 
efficient.
+ void
+ fillAssignmentCheck()
+ {
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>   X;
+ 
+   const X::size_type  starting_size(10);  
+   const X::value_type starting_value(66);
+   const X::size_type  n(23);  
+   const X::value_type t(111);
+ 
+   X a(starting_size, starting_value);
+   gnu_copy_tracker::reset();
+ 
+   // preconditions
+   VERIFY(starting_size == a.size());
+ 
+   // test
+   a.assign(n, t);
+ 
+   // postconditions
+   VERIFY(n == a.size());
+   VERIFY(n == (gnu_copy_constructor::count() + 
gnu_assignment_operator::count()));
+   VERIFY(starting_size == (gnu_destructor::count() + 
gnu_assignment_operator::count()));
+ }
+ 
+ 
+ // @verbatim
+ // 23.2.1     range assignment
+ // 23.2.1.1   deque constructors, copy, and assignment
+ //  effects:
+ //    Constructs a deque equal to the range [first, last), using the 
specified allocator.
+ //
+ //      template<typename InputIterator>
+ //        assign(InputIterator first, InputIterator last);
+ //      
+ //    is equivalent to
+ //
+ //      erase(begin(), end());
+ //      insert(begin(), first, last);
+ //
+ //  postconditions:
+ //  throws:
+ //  complexity:
+ //    forward iterators: N calls to the copy constructor, 0 reallocations
+ //    input iterators:   2N calls to the copy constructor, log(N) 
reallocations
+ // @endverbatim
+ void
+ rangeAssignmentCheck()
+ {
+   typedef gnu_copy_tracker  T;
+   typedef std::deque<T>   X;
+ 
+   const X::size_type  source_size(726); 
+   const X::value_type source_value(307);
+   const X::size_type  starting_size(10);  
+   const X::value_type starting_value(66);
+ 
+   X source(source_size, source_value);
+   X::iterator i = source.begin();
+   X::iterator j = source.end();
+   X::size_type rangeSize = std::distance(i, j);
+ 
+   X a(starting_size, starting_value);
+   VERIFY(starting_size == a.size());
+ 
+   gnu_copy_tracker::reset();
+ 
+   a.assign(i, j);
+ 
+   VERIFY(source == a);
+   VERIFY(rangeSize == (gnu_copy_constructor::count() + 
gnu_assignment_operator::count()));
+   VERIFY(starting_size == (gnu_destructor::count() + 
gnu_assignment_operator::count()));
+ }
+ 
+ 
+ // 23.1 (10)  range assignment
+ // 23.2.1.3   with exception
+ void
+ rangeAssignmentCheckWithException()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::deque<T>    X;
+ 
+   // test
+   // What does "no effects" mean?
+ }
+ 
+ 
+ // 23.1.1 (9) fill assignment looking like a range assignment
+ void
+ fillAssignmentCheck2()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::deque<T>    X;
+ 
+   // test
+   // What does "no effects" mean?
+ }
+ 
+ // Verify that the default deque constructor offers the basic exception
+ // guarantee.
+ void
+ test_default_ctor_exception_safety()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::deque<T, gnu_new_allocator<T> > X;
+ 
+   T::reset();
+   gnu_copy_constructor::throw_on(3);
+   gnu_allocator_tracker::resetCounts();
+ 
+   // test
+   try
+   {
+     X a(7);
+     VERIFY(("no exception thrown", false));
+   }
+   catch (...)
+   {
+   }
+ 
+   // assert postconditions
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+ }
+ 
+ // Verify that the copy constructor offers the basic exception guarantee.
+ void
+ test_copy_ctor_exception_safety()
+ {
+   // setup
+   typedef gnu_copy_tracker T;
+   typedef std::deque<T, gnu_new_allocator<T> > X;
+ 
+   gnu_allocator_tracker::resetCounts();
+   {
+     X a(7);
+     T::reset();
+     gnu_copy_constructor::throw_on(3);
+ 
+ 
+     // test
+     try
+     {
+       X u(a);
+       VERIFY(("no exception thrown", false));
+     }
+     catch (...)
+     {
+     }
+   }
+ 
+   // assert postconditions
+   VERIFY(gnu_allocator_tracker::allocationTotal() == 
gnu_allocator_tracker::deallocationTotal());
+ 
+   // teardown
+ }
+ 
+ 
  int main()
  {
+   // basic functionality and standard conformance checks
+   requiredTypesCheck();
+   defaultConstructorCheckPOD();
+   defaultConstructorCheck();
+   test_default_ctor_exception_safety();
+   copyConstructorCheck();
+   test_copy_ctor_exception_safety();
+   fillConstructorCheck();
+   fillConstructorCheck2();
+   rangeConstructorCheckInputIterator();
+   rangeConstructorCheckForwardIterator();
+   copyAssignmentCheck();
+   fillAssignmentCheck();
+   fillAssignmentCheck2();
+   rangeAssignmentCheck();
+   rangeAssignmentCheckWithException();
+ 
+   // specific bug fix checks
    test01();
  
!   return !test;
  }


-- 
Stephen M. Webb
// Testing allocator for the C++ library testsuite.
//
// Copyright (C) 2002 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

// This file provides an test instrumentation allocator that can be used to
// verify allocation functionality of standard library containers.
// 2002.11.25 smw

#ifndef _GLIBCPP_TESTSUITE_ALLOCATOR_H
#define _GLIBCPP_TESTSUITE_ALLOCATOR_H

#include <cstddef>
#include <limits>

  class gnu_allocator_tracker
  {
  public:
    typedef std::size_t    size_type; 

    static void*
    allocate(size_type blocksize)
    {
      allocationTotal_ += blocksize;
      return ::operator new(blocksize);
    }

    static void
    construct()
    { constructCount_++; }

    static void
    destroy()
    { destructCount_++; }

    static void
    deallocate(void* p, size_type blocksize)
    {
      ::operator delete(p);
      deallocationTotal_ += blocksize;
    }

    static size_type
    allocationTotal() 
    { return allocationTotal_; }

    static size_type
    deallocationTotal()
    { return deallocationTotal_; }

    static int
    constructCount() 
    { return constructCount_; }

    static int
    destructCount() 
    { return destructCount_; }
    
    static void
    resetCounts()
    {
      allocationTotal_ = 0;
      deallocationTotal_ = 0;
      constructCount_ = 0;
      destructCount_ = 0;
    }

  private:
    static size_type  allocationTotal_;
    static size_type  deallocationTotal_;
    static int        constructCount_;
    static int        destructCount_;
  };

  // A simple basic allocator that just forwards to the gnu_allocator_tracker
  // to fulfill memory requests.  This class is templated on the target object
  // type, but gnu_allocator_tracker isn't.
  template <class T>
    class gnu_new_allocator
    {
    public:
      typedef T              value_type;
      typedef T*             pointer;
      typedef const T*       const_pointer;
      typedef T&             reference;
      typedef const T&       const_reference;
      typedef std::size_t    size_type; 
      typedef std::ptrdiff_t difference_type; 

      template <class U> struct rebind { typedef gnu_new_allocator<U> other; };

      pointer
      address(reference value) const
      { return &value; }

      const_pointer
      address(const_reference value) const
      { return &value; }

      gnu_new_allocator() throw()
      { }

      gnu_new_allocator(const gnu_new_allocator&) throw()
      { }

      template <class U>
        gnu_new_allocator(const gnu_new_allocator<U>&) throw()
        { }

      ~gnu_new_allocator() throw()
      { }

      size_type
      max_size() const throw()
      { return std::numeric_limits<std::size_t>::max() / sizeof(T); }

      pointer
      allocate(size_type num, const void* = 0)
      { return static_cast<pointer>(gnu_allocator_tracker::allocate(num * sizeof(T))); }

      void
      construct(pointer p, const T& value)
      {
        new (p) T(value);
        gnu_allocator_tracker::construct();
      }

      void
      destroy(pointer p)
      {
        p->~T();
        gnu_allocator_tracker::destroy();
      }

      void
      deallocate(pointer p, size_type num)
      { gnu_allocator_tracker::deallocate(p, num * sizeof(T)); }
    };

  template <class T1, class T2>
    bool
    operator==(const gnu_new_allocator<T1>&, const gnu_new_allocator<T2>&) throw()
    { return true; }

  template <class T1, class T2>
    bool
    operator!=(const gnu_new_allocator<T1>&, const gnu_new_allocator<T2>&) throw()
    { return false; }

#endif // _GLIBCPP_TESTSUITE_ALLOCATOR_H

//
// Copyright (C) 2002 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

#include <testsuite_allocator.h>

gnu_allocator_tracker::size_type gnu_allocator_tracker::allocationTotal_   = 0;
gnu_allocator_tracker::size_type gnu_allocator_tracker::deallocationTotal_ = 0;
int                              gnu_allocator_tracker::constructCount_    = 0;
int                              gnu_allocator_tracker::destructCount_     = 0;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]