+2004-10-14  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * include/ext/mt_allocator.h (__mt_alloc::deallocate): Check for
+       null pointer.
+       * include/ext/pool_allocator.h (debug_allocator::deallocate):
+       Check pointer value.
+       * include/ext/debug_allocator.h (debug_allocator::deallocate):
+       Throw exceptions, don't abort.
+       * include/ext/array_allocator.h
+       (array_allocator_base::deallocate): Remove unused parameters.
+       * testsuite/testsuite_allocator.h (check_deallocate_null): New.
+       * testsuite/ext/mt_allocator/check_deallocate_null.cc: New.
+       * testsuite/ext/mt_allocator/check_deallocate_null_thread.cc: New.
+       * testsuite/ext/array_allocator/check_deallocate_null.cc: New.
+       * testsuite/ext/debug_allocator/check_deallocate_null.cc: New.
+       * testsuite/ext/malloc_allocator/check_deallocate_null.cc: New.
+       * testsuite/ext/new_allocator/check_deallocate_null.cc: New.
+       * testsuite/ext/pool_allocator/check_deallocate_null.cc: New.
+
+       * testsuite/testsuite_allocator.h (check_new): Add instance argument.
+       * testsuite/ext/array_allocator/check_new.cc: New.
+       
 2004-10-14  Paolo Carlini  <pcarlini@suse.de>
 
        * include/ext/bitmap_allocator.h (bitmap_allocator::_Alloc_block):
 
       address(const_reference __x) const { return &__x; }
 
       void
-      deallocate(pointer __p, size_type)
+      deallocate(pointer, size_type)
       { 
        // Does nothing.
       }
 
 #ifndef _DEBUG_ALLOCATOR_H
 #define _DEBUG_ALLOCATOR_H 1
 
-#include <cstdlib>
+#include <stdexcept>
 
 namespace __gnu_cxx
 {
       void
       deallocate(pointer __p, size_type __n)
       {
-       if (!__p)
-         abort();
-       pointer __real_p = __p - _M_extra;
-        if (*reinterpret_cast<size_type*>(__real_p) != __n)
-          abort();
-        _M_allocator.deallocate(__real_p, __n + _M_extra);
+       if (__p)
+         {
+           pointer __real_p = __p - _M_extra;
+           if (*reinterpret_cast<size_type*>(__real_p) != __n)
+             {
+               throw std::runtime_error("debug_allocator::deallocate"
+                                        " wrong size");
+             }
+           _M_allocator.deallocate(__real_p, __n + _M_extra);
+         }
+       else
+         throw std::runtime_error("debug_allocator::deallocate null pointer");
       }
     };
 } // namespace __gnu_cxx
 
     __mt_alloc<_Tp, _Poolp>::
     deallocate(pointer __p, size_type __n)
     {
-      // Requests larger than _M_max_bytes are handled by operators
-      // new/delete directly.
-      __pool_type& __pool = this->_S_get_pool();
-      const size_t __bytes = __n * sizeof(_Tp);
-      if (__pool._M_check_threshold(__bytes))
-       ::operator delete(__p);
-      else
-       __pool._M_reclaim_block(reinterpret_cast<char*>(__p), __bytes);
+      if (__builtin_expect(__p != 0, true))
+       {
+         // Requests larger than _M_max_bytes are handled by
+         // operators new/delete directly.
+         __pool_type& __pool = this->_S_get_pool();
+         const size_t __bytes = __n * sizeof(_Tp);
+         if (__pool._M_check_threshold(__bytes))
+           ::operator delete(__p);
+         else
+           __pool._M_reclaim_block(reinterpret_cast<char*>(__p), __bytes);
+       }
     }
   
   template<typename _Tp, typename _Poolp>
 
     void
     __pool_alloc<_Tp>::deallocate(pointer __p, size_type __n)
     {
-      if (__n)
+      if (__n && (__p != 0))
        {
          const size_t __bytes = __n * sizeof(_Tp);
          if (__bytes > static_cast<size_t>(_S_max_bytes) || _S_force_new == 1)
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <ext/array_allocator.h>
+#include <testsuite_allocator.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef __gnu_cxx::array_allocator<value_type> allocator_type;
+  __gnu_test::check_deallocate_null<allocator_type>(); 
+  return 0;
+}
+
 
--- /dev/null
+// 2001-11-25  Phil Edwards  <pme@gcc.gnu.org>
+//
+// Copyright (C) 2001, 2003, 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <cstdlib>
+#include <ext/array_allocator.h>
+#include <testsuite_allocator.h>
+
+using __gnu_cxx::array_allocator;
+
+void* 
+operator new(std::size_t n) throw(std::bad_alloc)
+{
+  new_called = true;
+  requested = n;
+  return std::malloc(n);
+}
+
+void
+operator delete(void *v) throw()
+{
+  delete_called = true;
+  return std::free(v);
+}
+
+// These just help tracking down error messages.
+bool test01() 
+{ 
+  typedef unsigned int value_type;
+  typedef std::tr1::array<value_type, 15> array_type;
+  typedef array_allocator<value_type, array_type> allocator_type;
+  array_type store;
+  allocator_type a(&store);
+  return (__gnu_test::check_new<allocator_type, false>(a) == false); 
+}
+
+int main()
+{
+  return test01();
+}
+
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <memory>
+#include <ext/debug_allocator.h>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef std::allocator<value_type> debug_type;
+  typedef __gnu_cxx::debug_allocator<debug_type> allocator_type;
+
+  try
+    {
+      __gnu_test::check_deallocate_null<allocator_type>(); 
+    }
+  catch (std::runtime_error& obj)
+    {
+      // Ok.
+    }
+  catch (...)
+    { 
+      // Shouldn't get here.
+      throw;
+    }
+  return 0;
+}
+
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <ext/malloc_allocator.h>
+#include <testsuite_allocator.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef __gnu_cxx::malloc_allocator<value_type> allocator_type;
+  __gnu_test::check_deallocate_null<allocator_type>(); 
+  return 0;
+}
+
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <ext/mt_allocator.h>
+#include <testsuite_allocator.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef __gnu_cxx::__common_pool_policy<false> policy_type;
+  typedef __gnu_cxx::__mt_alloc<value_type, policy_type> allocator_type;
+  __gnu_test::check_deallocate_null<allocator_type>(); 
+  return 0;
+}
+
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <ext/mt_allocator.h>
+#include <testsuite_allocator.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef __gnu_cxx::__common_pool_policy<true> policy_type;
+  typedef __gnu_cxx::__mt_alloc<value_type, policy_type> allocator_type;
+  __gnu_test::check_deallocate_null<allocator_type>(); 
+  return 0;
+}
+
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <ext/new_allocator.h>
+#include <testsuite_allocator.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef __gnu_cxx::new_allocator<value_type> allocator_type;
+  __gnu_test::check_deallocate_null<allocator_type>(); 
+  return 0;
+}
+
 
--- /dev/null
+//
+// Copyright (C) 2004 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.
+
+// 20.4.1.1 allocator members
+
+#include <ext/pool_allocator.h>
+#include <testsuite_allocator.h>
+
+int main()
+{ 
+  typedef int value_type;
+  typedef __gnu_cxx::__pool_alloc<value_type> allocator_type;
+  __gnu_test::check_deallocate_null<allocator_type>(); 
+  return 0;
+}
+
 
 // -*- C++ -*-
 // Testing allocator for the C++ library testsuite.
 //
-// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2002, 2003, 2004 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
   check_construct_destroy(const char* tag, int expected_c, int expected_d);
 
   template<typename Alloc, bool uses_global_new_and_delete>
-  bool check_new()
-  {
-    bool test __attribute__((unused)) = true;
-    Alloc  a;
-    typename Alloc::pointer p = a.allocate(10);
-    if (uses_global_new_and_delete)  
-      test &= ( requested >= (10 * 15 * sizeof(long)) );
-
-    test &= ( new_called == uses_global_new_and_delete );
-    a.deallocate(p, 10);
-    test &= ( delete_called == uses_global_new_and_delete );
-  
-    return test;
-  }
+    bool 
+    check_new(Alloc a = Alloc())
+    {
+      bool test __attribute__((unused)) = true;
+      typename Alloc::pointer p = a.allocate(10);
+      if (uses_global_new_and_delete)  
+       test &= ( requested >= (10 * 15 * sizeof(long)) );
+      
+      test &= ( new_called == uses_global_new_and_delete );
+      a.deallocate(p, 10);
+      test &= ( delete_called == uses_global_new_and_delete );
+      
+      return test;
+    }
+
+  template<typename Alloc>
+    bool 
+    check_deallocate_null()
+    {
+      // Let's not core here...
+      Alloc  a;
+      a.deallocate(NULL, 10);
+    }
 }; // namespace __gnu_test
 
 #endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H