Re: [v3] More noexcept for vectors

2013-09-16 Thread Paolo Carlini

Hi Marc,

On 09/15/2013 11:12 AM, Marc Glisse wrote:
I had to separate the constructor that takes an allocator from the 
default constructor in debug/profile, since in release the noexcept 
only applies to one of them (and the testsuite asserts that release 
and debug agree on this). An alternative would be to make the release 
vector default constructor conditionally noexcept (depending on the 
allocator). Or to use explicit vector(const Allocator = Allocator()); 
also in normal mode instead of splitting it in two.
Thanks a lot. Now I'm wondering if we shouldn't really do the latter: 
the issue is, if I remember correctly, in C++11, at variance with C++98, 
allocators aren't necessarily default constructible, thus by explicit 
instantiatiation the user can easily tell whether that constructor is 
split or not. What do you think?


Paolo.


Re: [v3] More noexcept for vectors

2013-09-16 Thread Marc Glisse

On Mon, 16 Sep 2013, Paolo Carlini wrote:


On 09/15/2013 11:12 AM, Marc Glisse wrote:
I had to separate the constructor that takes an allocator from the default 
constructor in debug/profile, since in release the noexcept only applies to 
one of them (and the testsuite asserts that release and debug agree on 
this). An alternative would be to make the release vector default 
constructor conditionally noexcept (depending on the allocator). Or to use 
explicit vector(const Allocator = Allocator()); also in normal mode 
instead of splitting it in two.
Thanks a lot. Now I'm wondering if we shouldn't really do the latter: the 
issue is, if I remember correctly, in C++11, at variance with C++98, 
allocators aren't necessarily default constructible, thus by explicit 
instantiatiation the user can easily tell whether that constructor is split 
or not. What do you think?


Shouldn't it just be illegal to explicitly instantiate a full class like 
std::vector?


But ok, I'll post that version as soon as I can test it.

--
Marc Glisse


Re: [v3] More noexcept for vectors

2013-09-16 Thread Jonathan Wakely
On 15 September 2013 10:12, Marc Glisse wrote:

 PR libstdc++/58338
 * include/bits/stl_vector.h
 (_Vector_impl::_Vector_impl(_Tp_alloc_type const),
 _Vector_impl::_Vector_impl(_Tp_alloc_type),
 _Vector_impl::_M_swap_data,
 _Vector_base::_Vector_base(const allocator_type),
 _Vector_base::_Vector_base(allocator_type),
 _Vector_base::_Vector_base(_Vector_base),
 vector::vector(const allocator_type), vector::operator[],
 vector::operator[] const, vector::front, vector::front const,
 vector::back, vector::back const, vector::pop_back,
 vector::_M_erase_at_end): Mark as noexcept.
 (vector::~vector): Remove useless noexcept.

Are you sure the noexcept on the destructors is useless?

A user-defined allocator type could have
is_nothrow_descructibleallocator_type::value==false or
is_nothrow_destructiblepointer::value==false, which would alter the
type of is_nothrow_destructiblevectorT, A.

Although the user-defined allocator must not actually throw from its
destructor, it is not required to have a noexcept destructor.
However, since it must not actually throw (irrespective of its
exception spec) we can unconditionally give std::vector a noexcept
destructor.


Re: [v3] More noexcept for vectors

2013-09-16 Thread Marc Glisse

On Mon, 16 Sep 2013, Jonathan Wakely wrote:


Are you sure the noexcept on the destructors is useless?


Ok, I am putting it back in.

--
Marc Glisse


Re: [v3] More noexcept for vectors

2013-09-16 Thread Marc Glisse

New version that passed testing.

2013-09-16  Marc Glisse  marc.gli...@inria.fr

PR libstdc++/58338
* include/bits/stl_vector.h (vector::vector(),
vector::vector(const allocator_type)): Merge.
(_Vector_impl::_Vector_impl(_Tp_alloc_type const),
_Vector_impl::_Vector_impl(_Tp_alloc_type),
_Vector_impl::_M_swap_data,
_Vector_base::_Vector_base(const allocator_type),
_Vector_base::_Vector_base(allocator_type),
_Vector_base::_Vector_base(_Vector_base), _Vector_base::~_Vector_base,
vector::vector(const allocator_type), vector::operator[],
vector::operator[] const, vector::front, vector::front const,
vector::back, vector::back const, vector::pop_back,
vector::_M_erase_at_end): Mark as noexcept.
* include/debug/vector (vector::vector(const _Allocator),
vector::operator[], vector::operator[] const, vector::front,
vector::front const, vector::back, vector::back const, vector::pop_back,
_M_requires_reallocation, _M_update_guaranteed_capacity,
_M_invalidate_after_nth): Mark as noexcept.
* include/profile/vector (vector::vector(const _Allocator),
vector::operator[], vector::operator[] const, vector::front,
vector::front const, vector::back, vector::back const): Mark as
noexcept.
(vector::vector(vector, const _Allocator)): Remove wrong noexcept.
* testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
Adjust line number.
* testsuite/23_containers/vector/requirements/dr438/
constructor_1_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/
constructor_2_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
Likewise.

--
Marc GlisseIndex: include/bits/stl_vector.h
===
--- include/bits/stl_vector.h   (revision 202625)
+++ include/bits/stl_vector.h   (working copy)
@@ -80,32 +80,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : public _Tp_alloc_type
   {
pointer _M_start;
pointer _M_finish;
pointer _M_end_of_storage;
 
_Vector_impl()
: _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 
-   _Vector_impl(_Tp_alloc_type const __a)
+   _Vector_impl(_Tp_alloc_type const __a) _GLIBCXX_NOEXCEPT
: _Tp_alloc_type(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 
 #if __cplusplus = 201103L
-   _Vector_impl(_Tp_alloc_type __a)
+   _Vector_impl(_Tp_alloc_type __a) noexcept
: _Tp_alloc_type(std::move(__a)),
  _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 #endif
 
-   void _M_swap_data(_Vector_impl __x)
+   void _M_swap_data(_Vector_impl __x) _GLIBCXX_NOEXCEPT
{
  std::swap(_M_start, __x._M_start);
  std::swap(_M_finish, __x._M_finish);
  std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
   };
   
 public:
   typedef _Alloc allocator_type;
 
@@ -117,53 +117,53 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
   { return *static_castconst _Tp_alloc_type*(this-_M_impl); }
 
   allocator_type
   get_allocator() const _GLIBCXX_NOEXCEPT
   { return allocator_type(_M_get_Tp_allocator()); }
 
   _Vector_base()
   : _M_impl() { }
 
-  _Vector_base(const allocator_type __a)
+  _Vector_base(const allocator_type __a) _GLIBCXX_NOEXCEPT
   : _M_impl(__a) { }
 
   _Vector_base(size_t __n)
   : _M_impl()
   { _M_create_storage(__n); }
 
   _Vector_base(size_t __n, const allocator_type __a)
   : _M_impl(__a)
   { _M_create_storage(__n); }
 
 #if __cplusplus = 201103L
-  _Vector_base(_Tp_alloc_type __a)
+  _Vector_base(_Tp_alloc_type __a) noexcept
   : _M_impl(std::move(__a)) { }
 
-  _Vector_base(_Vector_base __x)
+  _Vector_base(_Vector_base __x) noexcept
   : _M_impl(std::move(__x._M_get_Tp_allocator()))
   { this-_M_impl._M_swap_data(__x._M_impl); }
 
   _Vector_base(_Vector_base __x, const allocator_type __a)
   : _M_impl(__a)
   {
if (__x.get_allocator() == __a)
  this-_M_impl._M_swap_data(__x._M_impl);
else
  {
size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start;
_M_create_storage(__n);
  }
   }
 #endif
 
-  ~_Vector_base()
+  ~_Vector_base() _GLIBCXX_NOEXCEPT
   { _M_deallocate(this-_M_impl._M_start, this-_M_impl._M_end_of_storage
  - this-_M_impl._M_start); }
 
 public:
   _Vector_impl _M_impl;
 
   pointer
   _M_allocate(size_t __n)
   { return __n != 0 ? _M_impl.allocate(__n) : 0; }
 
@@ -236,31 +236,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 protected:
   using _Base::_M_allocate;
   using 

Re: [v3] More noexcept for vectors

2013-09-16 Thread Paolo Carlini

On 09/16/2013 07:32 PM, Marc Glisse wrote:

New version that passed testing.

Looks good to me, thanks!

Paolo.



Re: [v3] More noexcept for vectors

2013-09-15 Thread Marc Glisse
I had to separate the constructor that takes an allocator from the default 
constructor in debug/profile, since in release the noexcept only applies 
to one of them (and the testsuite asserts that release and debug agree on 
this). An alternative would be to make the release vector default 
constructor conditionally noexcept (depending on the allocator). Or to use 
explicit vector(const Allocator = Allocator()); also in normal mode 
instead of splitting it in two.


I also removed a noexcept in profile mode where the release mode doesn't 
have noexcept.


Tested, no regression.

2013-09-15  Marc Glisse  marc.gli...@inria.fr

PR libstdc++/58338
* include/bits/stl_vector.h
(_Vector_impl::_Vector_impl(_Tp_alloc_type const),
_Vector_impl::_Vector_impl(_Tp_alloc_type),
_Vector_impl::_M_swap_data,
_Vector_base::_Vector_base(const allocator_type),
_Vector_base::_Vector_base(allocator_type),
_Vector_base::_Vector_base(_Vector_base),
vector::vector(const allocator_type), vector::operator[],
vector::operator[] const, vector::front, vector::front const,
vector::back, vector::back const, vector::pop_back,
vector::_M_erase_at_end): Mark as noexcept.
(vector::~vector): Remove useless noexcept.
* include/debug/vector (vector::vector()): Split.
(vector::vector(const _Allocator), vector::operator[],
vector::operator[] const, vector::front, vector::front const,
vector::back, vector::back const, vector::pop_back,
_M_requires_reallocation, _M_update_guaranteed_capacity,
_M_invalidate_after_nth): Mark as noexcept.
(vector::~vector): Remove useless noexcept.
* include/profile/vector (vector::vector()): Split.
(vector::vector(const _Allocator), vector::operator[],
vector::operator[] const, vector::front, vector::front const,
vector::back, vector::back const): Mark as noexcept.
(vector::vector(vector, const _Allocator)): Remove wrong noexcept.
(vector::~vector): Remove useless noexcept.

--
Marc GlisseIndex: include/bits/stl_vector.h
===
--- include/bits/stl_vector.h   (revision 202588)
+++ include/bits/stl_vector.h   (working copy)
@@ -80,32 +80,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : public _Tp_alloc_type
   {
pointer _M_start;
pointer _M_finish;
pointer _M_end_of_storage;
 
_Vector_impl()
: _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 
-   _Vector_impl(_Tp_alloc_type const __a)
+   _Vector_impl(_Tp_alloc_type const __a) _GLIBCXX_NOEXCEPT
: _Tp_alloc_type(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 
 #if __cplusplus = 201103L
-   _Vector_impl(_Tp_alloc_type __a)
+   _Vector_impl(_Tp_alloc_type __a) noexcept
: _Tp_alloc_type(std::move(__a)),
  _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 #endif
 
-   void _M_swap_data(_Vector_impl __x)
+   void _M_swap_data(_Vector_impl __x) _GLIBCXX_NOEXCEPT
{
  std::swap(_M_start, __x._M_start);
  std::swap(_M_finish, __x._M_finish);
  std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
   };
   
 public:
   typedef _Alloc allocator_type;
 
@@ -117,36 +117,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
   { return *static_castconst _Tp_alloc_type*(this-_M_impl); }
 
   allocator_type
   get_allocator() const _GLIBCXX_NOEXCEPT
   { return allocator_type(_M_get_Tp_allocator()); }
 
   _Vector_base()
   : _M_impl() { }
 
-  _Vector_base(const allocator_type __a)
+  _Vector_base(const allocator_type __a) _GLIBCXX_NOEXCEPT
   : _M_impl(__a) { }
 
   _Vector_base(size_t __n)
   : _M_impl()
   { _M_create_storage(__n); }
 
   _Vector_base(size_t __n, const allocator_type __a)
   : _M_impl(__a)
   { _M_create_storage(__n); }
 
 #if __cplusplus = 201103L
-  _Vector_base(_Tp_alloc_type __a)
+  _Vector_base(_Tp_alloc_type __a) noexcept
   : _M_impl(std::move(__a)) { }
 
-  _Vector_base(_Vector_base __x)
+  _Vector_base(_Vector_base __x) noexcept
   : _M_impl(std::move(__x._M_get_Tp_allocator()))
   { this-_M_impl._M_swap_data(__x._M_impl); }
 
   _Vector_base(_Vector_base __x, const allocator_type __a)
   : _M_impl(__a)
   {
if (__x.get_allocator() == __a)
  this-_M_impl._M_swap_data(__x._M_impl);
else
  {
@@ -246,21 +246,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*  @brief  Default constructor creates no elements.
*/
   vector()
   : _Base() { }
 
   /**
*  @brief  Creates a %vector with no elements.
*  @param  __a  An allocator object.
*/
   explicit
-  vector(const 

[v3] More noexcept for vectors

2013-09-14 Thread Marc Glisse

Hello,

this patch passes bootstrap+testsuite. The guarantees given by the 
standard on allocators are a bit weird, but I see there is already DR2016 
taking care of it.


2013-09-14  Marc Glisse  marc.gli...@inria.fr

PR libstdc++/58338
* include/bits/stl_vector.h
(_Vector_impl::_Vector_impl(_Tp_alloc_type const),
_Vector_impl::_Vector_impl(_Tp_alloc_type),
_Vector_impl::_M_swap_data,
_Vector_base::_Vector_base(const allocator_type),
_Vector_base::_Vector_base(allocator_type),
_Vector_base::_Vector_base(_Vector_base),
vector::vector(const allocator_type), vector::operator[],
vector::operator[] const, vector::front, vector::front const,
vector::back, vector::back const, vector::pop_back,
vector::_M_erase_at_end): Mark as noexcept.
(vector::~vector): Remove useless noexcept.


--
Marc GlisseIndex: include/bits/stl_vector.h
===
--- include/bits/stl_vector.h   (revision 202588)
+++ include/bits/stl_vector.h   (working copy)
@@ -80,32 +80,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : public _Tp_alloc_type
   {
pointer _M_start;
pointer _M_finish;
pointer _M_end_of_storage;
 
_Vector_impl()
: _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 
-   _Vector_impl(_Tp_alloc_type const __a)
+   _Vector_impl(_Tp_alloc_type const __a) _GLIBCXX_NOEXCEPT
: _Tp_alloc_type(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 
 #if __cplusplus = 201103L
-   _Vector_impl(_Tp_alloc_type __a)
+   _Vector_impl(_Tp_alloc_type __a) noexcept
: _Tp_alloc_type(std::move(__a)),
  _M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
 #endif
 
-   void _M_swap_data(_Vector_impl __x)
+   void _M_swap_data(_Vector_impl __x) _GLIBCXX_NOEXCEPT
{
  std::swap(_M_start, __x._M_start);
  std::swap(_M_finish, __x._M_finish);
  std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
   };
   
 public:
   typedef _Alloc allocator_type;
 
@@ -117,36 +117,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
   { return *static_castconst _Tp_alloc_type*(this-_M_impl); }
 
   allocator_type
   get_allocator() const _GLIBCXX_NOEXCEPT
   { return allocator_type(_M_get_Tp_allocator()); }
 
   _Vector_base()
   : _M_impl() { }
 
-  _Vector_base(const allocator_type __a)
+  _Vector_base(const allocator_type __a) _GLIBCXX_NOEXCEPT
   : _M_impl(__a) { }
 
   _Vector_base(size_t __n)
   : _M_impl()
   { _M_create_storage(__n); }
 
   _Vector_base(size_t __n, const allocator_type __a)
   : _M_impl(__a)
   { _M_create_storage(__n); }
 
 #if __cplusplus = 201103L
-  _Vector_base(_Tp_alloc_type __a)
+  _Vector_base(_Tp_alloc_type __a) noexcept
   : _M_impl(std::move(__a)) { }
 
-  _Vector_base(_Vector_base __x)
+  _Vector_base(_Vector_base __x) noexcept
   : _M_impl(std::move(__x._M_get_Tp_allocator()))
   { this-_M_impl._M_swap_data(__x._M_impl); }
 
   _Vector_base(_Vector_base __x, const allocator_type __a)
   : _M_impl(__a)
   {
if (__x.get_allocator() == __a)
  this-_M_impl._M_swap_data(__x._M_impl);
else
  {
@@ -246,21 +246,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*  @brief  Default constructor creates no elements.
*/
   vector()
   : _Base() { }
 
   /**
*  @brief  Creates a %vector with no elements.
*  @param  __a  An allocator object.
*/
   explicit
-  vector(const allocator_type __a)
+  vector(const allocator_type __a) _GLIBCXX_NOEXCEPT
   : _Base(__a) { }
 
 #if __cplusplus = 201103L
   /**
*  @brief  Creates a %vector with default constructed elements.
*  @param  __n  The number of elements to initially create.
*  @param  __a  An allocator.
*
*  This constructor fills the %vector with @a __n default
*  constructed elements.
@@ -404,21 +404,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  _M_initialize_dispatch(__first, __last, _Integral());
}
 #endif
 
   /**
*  The dtor only erases the elements, and note that if the
*  elements themselves are pointers, the pointed-to memory is
*  not touched in any way.  Managing the pointer is the user's
*  responsibility.
*/
-  ~vector() _GLIBCXX_NOEXCEPT
+  ~vector()
   { std::_Destroy(this-_M_impl._M_start, this-_M_impl._M_finish,
  _M_get_Tp_allocator()); }
 
   /**
*  @brief  %Vector assignment operator.
*  @param  __x  A %vector of identical element and allocator types.
*
*  All the elements of @a __x are copied, but any extra memory in
  

Re: [v3] More noexcept for vectors

2013-09-14 Thread Paolo Carlini


Hi,

Marc Glisse marc.gli...@inria.fr ha scritto:
Hello,

this patch passes bootstrap+testsuite. The guarantees given by the
standard on allocators are a bit weird, but I see there is already
DR2016
taking care of it.

Patch looks good to me, thanks!

Paolo


Re: [v3] More noexcept for vectors

2013-09-14 Thread Paolo Carlini


... what about debug-mode (and profile-mode)? Is in principle possible to 
detect the noexcepts? If we can't exclude that, we should probably change at 
the same time the special modes too. Otherwise seems just matter of consistency?

Paolo



Re: [v3] More noexcept for vectors

2013-09-14 Thread Marc Glisse

On Sat, 14 Sep 2013, Paolo Carlini wrote:

... what about debug-mode (and profile-mode)? Is in principle possible 
to detect the noexcepts? If we can't exclude that, we should probably 
change at the same time the special modes too. Otherwise seems just 
matter of consistency?


I was going one file at a time, and the priority is clearly 
release-mode, since this is about performance. I don't think there is 
anything wrong with debug-mode having a different exception specification 
(it is already binary-incompatible with the default mode) but I understand 
why people may want to keep some consistency. I can do vector in the other 
modes next if you want.


--
Marc Glisse


Re: [v3] More noexcept for vectors

2013-09-14 Thread Paolo Carlini


Hi,

I was going one file at a time, and the priority is clearly
release-mode, since this is about performance. I don't think there is

anything wrong with debug-mode having a different exception
specification
(it is already binary-incompatible with the default mode) but I
understand 
why people may want to keep some consistency. I can do vector in the
other
modes next if you want.

Yes, please. As boring as it may seem, I'm trying to convince myself and the 
other contributors to keep the modes up to date and consistent as much as 
possible. If one day we figure out that we can't, we don't have enough man 
power it will mean we have to remove the special modes (or only some of them) 
from svn.

Thanks!
Paolo