@@ -440,6 +440,17 @@ requirements of the license of GCC.
<listitem><para>Yes, it can, specifically if EOF is reached while skipping whitespace.
</para></listitem></varlistentry>
+ <varlistentry xml:id="manual.bugs.dr206"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#206">206</link>:
+ <emphasis><code>operator new(size_t, nothrow)</code> may become
+ unlinked to ordinary <code>operator new</code> if ordinary
+ version replaced
+ </emphasis>
+ </term>
+ <listitem><para>The <code>nothrow</code> forms of new and delete were
+ changed to call the throwing forms, handling any exception by
+ catching it and returning a null pointer.
+ </para></listitem></varlistentry>
+
<varlistentry xml:id="manual.bugs.dr211"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#211">211</link>:
<emphasis>operator>>(istream&, string&) doesn't set failbit</emphasis>
</term>
@@ -44,7 +44,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
#pragma GCC diagnostic ignored "-Wsized-deallocation"
_GLIBCXX_WEAK_DEFINITION void
-operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT
+operator delete(void* ptr) noexcept
{
std::free(ptr);
}
@@ -44,7 +44,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
#pragma GCC diagnostic ignored "-Wsized-deallocation"
_GLIBCXX_WEAK_DEFINITION void
-operator delete(void* ptr, std::align_val_t) _GLIBCXX_USE_NOEXCEPT
+operator delete(void* ptr, std::align_val_t) noexcept
{
#if _GLIBCXX_HAVE_ALIGNED_ALLOC || _GLIBCXX_HAVE_POSIX_MEMALIGN \
|| _GLIBCXX_HAVE_MEMALIGN
@@ -27,7 +27,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete (void *ptr, std::align_val_t al, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+operator delete (void *ptr, std::align_val_t al, const std::nothrow_t&) noexcept
{
::operator delete (ptr, al);
}
@@ -41,7 +41,10 @@ _GLIBCXX_END_NAMESPACE_VERSION
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+operator delete (void *ptr, const std::nothrow_t&) noexcept
{
- std::free(ptr);
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 206. operator new(size_t, nothrow) may become unlinked to ordinary
+ // operator new if ordinary version replaced
+ ::operator delete (ptr);
}
@@ -28,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete(void* ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT
+operator delete(void* ptr, std::size_t) noexcept
{
::operator delete (ptr);
}
@@ -27,7 +27,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete(void* ptr, std::size_t, std::align_val_t al) _GLIBCXX_USE_NOEXCEPT
+operator delete(void* ptr, std::size_t, std::align_val_t al) noexcept
{
::operator delete (ptr, al);
}
@@ -30,7 +30,7 @@
#pragma GCC diagnostic ignored "-Wsized-deallocation"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, std::align_val_t al) _GLIBCXX_USE_NOEXCEPT
+operator delete[] (void *ptr, std::align_val_t al) noexcept
{
::operator delete (ptr, al);
}
@@ -27,7 +27,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, std::align_val_t al, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+operator delete[] (void *ptr, std::align_val_t al, const std::nothrow_t&) noexcept
{
::operator delete[] (ptr, al);
}
@@ -27,7 +27,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+operator delete[] (void *ptr, const std::nothrow_t&) noexcept
{
- ::operator delete (ptr);
+ ::operator delete[] (ptr);
}
@@ -28,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT
+operator delete[] (void *ptr, std::size_t) noexcept
{
::operator delete[] (ptr);
}
@@ -27,7 +27,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, std::size_t, std::align_val_t al) _GLIBCXX_USE_NOEXCEPT
+operator delete[] (void *ptr, std::size_t, std::align_val_t al) noexcept
{
::operator delete[] (ptr, al);
}
@@ -44,7 +44,7 @@ operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
void *p;
/* malloc (0) is unpredictable; avoid it. */
- if (sz == 0)
+ if (__builtin_expect (sz == 0, false))
sz = 1;
while ((p = malloc (sz)) == 0)
@@ -101,7 +101,6 @@ aligned_alloc (std::size_t al, std::size_t sz)
_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz, std::align_val_t al)
{
- void *p;
std::size_t align = (std::size_t)al;
/* Alignment must be a power of two. */
@@ -125,8 +124,9 @@ operator new (std::size_t sz, std::align_val_t al)
sz += align - rem;
#endif
- using __gnu_cxx::aligned_alloc;
- while ((p = aligned_alloc (align, sz)) == 0)
+ void *p;
+
+ while ((p = __gnu_cxx::aligned_alloc (align, sz)) == nullptr)
{
new_handler handler = std::get_new_handler ();
if (! handler)
@@ -29,7 +29,7 @@
_GLIBCXX_WEAK_DEFINITION void*
operator new(std::size_t sz, std::align_val_t al, const std::nothrow_t&)
- _GLIBCXX_USE_NOEXCEPT
+ noexcept
{
__try
{
@@ -37,6 +37,6 @@ operator new(std::size_t sz, std::align_val_t al, const std::nothrow_t&)
}
__catch(...)
{
- return 0;
+ return nullptr;
}
}
@@ -32,28 +32,17 @@ using std::bad_alloc;
extern "C" void *malloc (std::size_t);
_GLIBCXX_WEAK_DEFINITION void *
-operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+operator new (std::size_t sz, const std::nothrow_t&) noexcept
{
- void *p;
-
- /* malloc (0) is unpredictable; avoid it. */
- if (sz == 0)
- sz = 1;
-
- while ((p = malloc (sz)) == 0)
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 206. operator new(size_t, nothrow) may become unlinked to ordinary
+ // operator new if ordinary version replaced
+ __try
{
- new_handler handler = std::get_new_handler ();
- if (! handler)
- return 0;
- __try
- {
- handler ();
- }
- __catch(const bad_alloc&)
- {
- return 0;
- }
+ return ::operator new(sz);
+ }
+ __catch (...)
+ {
+ return nullptr;
}
-
- return p;
}
@@ -29,7 +29,7 @@
_GLIBCXX_WEAK_DEFINITION void*
operator new[] (std::size_t sz, std::align_val_t al, const std::nothrow_t&)
- _GLIBCXX_USE_NOEXCEPT
+ noexcept
{
__try
{
@@ -37,6 +37,6 @@ operator new[] (std::size_t sz, std::align_val_t al, const std::nothrow_t&)
}
__catch(...)
{
- return 0;
+ return nullptr;
}
}
@@ -27,8 +27,17 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void*
-operator new[] (std::size_t sz, const std::nothrow_t& nothrow)
- _GLIBCXX_USE_NOEXCEPT
+operator new[] (std::size_t sz, const std::nothrow_t&) noexcept
{
- return ::operator new(sz, nothrow);
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 206. operator new(size_t, nothrow) may become unlinked to ordinary
+ // operator new if ordinary version replaced
+ __try
+ {
+ return ::operator new[](sz);
+ }
+ __catch (...)
+ {
+ return nullptr;
+ }
}
new file mode 100644
@@ -0,0 +1,183 @@
+// Copyright (C) 2018 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run }
+
+#include <new>
+#include <stdlib.h>
+#include <testsuite_hooks.h>
+
+// PR libstdc++/68210
+
+struct MyBadAlloc: std::bad_alloc { };
+
+static bool new_fail;
+static bool bad_alloc_thrown;
+static unsigned new_called;
+static unsigned delete_called;
+static unsigned new_vec_called;
+static unsigned delete_vec_called;
+static unsigned new_handler_called;
+
+static void new_handler ()
+{
+ if (new_handler_called++)
+ throw MyBadAlloc ();
+}
+
+void* operator new (size_t n)
+{
+ static size_t cntr;
+
+ ++new_called;
+
+ for ( ; ; ) {
+ if (void *p = new_fail ? 0 : malloc (n + sizeof n)) {
+ *static_cast<size_t*>(p) = ++cntr;
+ return static_cast<size_t*>(p) + 1;
+ }
+
+ if (std::new_handler h = std::set_new_handler (0)) {
+ std::set_new_handler (h);
+ h ();
+ }
+ else {
+ bad_alloc_thrown = true;
+ throw MyBadAlloc ();
+ }
+ }
+}
+
+void operator delete (void *p)
+{
+ ++delete_called;
+ if (p)
+ free (static_cast<size_t*>(p) - 1);
+}
+
+void* operator new[] (size_t n)
+{
+ ++new_vec_called;
+ return operator new(n);
+}
+
+void operator delete[] (void *p)
+{
+ ++delete_vec_called;
+ operator delete(p);
+}
+
+#if __cplusplus >= 201402L
+void operator delete (void *p, std::size_t)
+{
+ ::operator delete(p);
+}
+void operator delete[] (void *p, std::size_t)
+{
+ ::operator delete[](p);
+}
+#endif
+
+void init()
+{
+ new_fail = false;
+ new_called = 0;
+ delete_called = 0;
+ new_vec_called = 0;
+ delete_vec_called = 0;
+ new_handler_called = 0;
+ std::set_new_handler (0);
+}
+
+void
+test01()
+{
+ init ();
+
+ void *p = operator new (1, std::nothrow);
+
+ VERIFY (p != 0);
+ VERIFY (1 == new_called);
+ VERIFY (0 == new_handler_called);
+ VERIFY (!bad_alloc_thrown);
+
+ operator delete (p, std::nothrow);
+ VERIFY( 1 == delete_called );
+
+ new_fail = true;
+ p = operator new (1, std::nothrow);
+
+ VERIFY (0 == p);
+ VERIFY (2 == new_called);
+ VERIFY (0 == new_handler_called);
+ VERIFY (bad_alloc_thrown);
+
+ new_fail = true;
+ bad_alloc_thrown = false;
+ std::set_new_handler (new_handler);
+ p = operator new (1, std::nothrow);
+
+ VERIFY (0 == p);
+ VERIFY (3 == new_called);
+ VERIFY (2 == new_handler_called);
+ VERIFY (!bad_alloc_thrown);
+}
+
+void
+test02()
+{
+ init ();
+
+ void *p = operator new[] (1, std::nothrow);
+
+ VERIFY (p != 0);
+ VERIFY (1 == new_called);
+ VERIFY (1 == new_vec_called);
+ VERIFY (0 == new_handler_called);
+ VERIFY (!bad_alloc_thrown);
+
+ operator delete[] (p, std::nothrow);
+ VERIFY( 1 == delete_called );
+ VERIFY( 1 == delete_vec_called );
+
+ new_fail = true;
+ p = operator new[] (1, std::nothrow);
+
+ VERIFY (0 == p);
+ VERIFY (2 == new_called);
+ VERIFY (2 == new_vec_called);
+ VERIFY (0 == new_handler_called);
+ VERIFY (bad_alloc_thrown);
+
+ new_fail = true;
+ bad_alloc_thrown = false;
+ std::set_new_handler (new_handler);
+ p = operator new[] (1, std::nothrow);
+
+ VERIFY (0 == p);
+ VERIFY (3 == new_called);
+ VERIFY (3 == new_vec_called);
+ VERIFY (2 == new_handler_called);
+ VERIFY (!bad_alloc_thrown);
+}
+
+
+int main()
+{
+ test01();
+ test02();
+}