summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc_cpp.cc30
-rw-r--r--include/gc_cpp.h15
2 files changed, 32 insertions, 13 deletions
diff --git a/gc_cpp.cc b/gc_cpp.cc
index 621a3165..88ffe96e 100644
--- a/gc_cpp.cc
+++ b/gc_cpp.cc
@@ -27,16 +27,30 @@ built-in "new" and "delete".
# define GC_BUILD
#endif
-#include "gc_cpp.h"
+#include "gc.h"
-#if !defined(GC_NEW_DELETE_THROW_NOT_NEEDED) \
- && !defined(GC_NEW_DELETE_NEED_THROW) && GC_GNUC_PREREQ(4, 2) \
- && (__cplusplus < 201103L || defined(__clang__))
-# define GC_NEW_DELETE_NEED_THROW
+#include <new> // for bad_alloc, precedes include of gc_cpp.h
+
+#include "gc_cpp.h" // for GC_OPERATOR_NEW_ARRAY, GC_NOEXCEPT
+
+#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS)
+# define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom()
+#else
+# define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc()
#endif
+GC_API void GC_CALL GC_throw_bad_alloc() {
+ GC_ALLOCATOR_THROW_OR_ABORT();
+}
+
#if !defined(_MSC_VER) && !defined(__DMC__)
+# if !defined(GC_NEW_DELETE_THROW_NOT_NEEDED) \
+ && !defined(GC_NEW_DELETE_NEED_THROW) && GC_GNUC_PREREQ(4, 2) \
+ && (__cplusplus < 201103L || defined(__clang__))
+# define GC_NEW_DELETE_NEED_THROW
+# endif
+
# ifdef GC_NEW_DELETE_NEED_THROW
# define GC_DECL_NEW_THROW throw(std::bad_alloc)
# else
@@ -45,7 +59,8 @@ built-in "new" and "delete".
void* operator new(size_t size) GC_DECL_NEW_THROW {
void* obj = GC_MALLOC_UNCOLLECTABLE(size);
- GC_OP_NEW_OOM_CHECK(obj);
+ if (0 == obj)
+ GC_ALLOCATOR_THROW_OR_ABORT();
return obj;
}
@@ -56,7 +71,8 @@ built-in "new" and "delete".
# if defined(GC_OPERATOR_NEW_ARRAY) && !defined(CPPCHECK)
void* operator new[](size_t size) GC_DECL_NEW_THROW {
void* obj = GC_MALLOC_UNCOLLECTABLE(size);
- GC_OP_NEW_OOM_CHECK(obj);
+ if (0 == obj)
+ GC_ALLOCATOR_THROW_OR_ABORT();
return obj;
}
diff --git a/include/gc_cpp.h b/include/gc_cpp.h
index 64a10d25..83a8477d 100644
--- a/include/gc_cpp.h
+++ b/include/gc_cpp.h
@@ -141,7 +141,6 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
****************************************************************************/
#include "gc.h"
-#include <new> // for bad_alloc
#ifdef GC_NAMESPACE
# define GC_NS_QUALIFY(T) boehmgc::T
@@ -190,13 +189,17 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
# endif
#endif // !GC_NOEXCEPT
-#if !defined(GC_NEW_ABORTS_ON_OOM) && !defined(_LIBCPP_NO_EXCEPTIONS)
-# define GC_OP_NEW_OOM_CHECK(obj) \
- do { if (!(obj)) throw std::bad_alloc(); } while (0)
-#else
+#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS)
# define GC_OP_NEW_OOM_CHECK(obj) \
do { if (!(obj)) GC_abort_on_oom(); } while (0)
-#endif // !GC_NEW_ABORTS_ON_OOM
+#elif defined(GC_INCLUDE_NEW)
+# include <new> // for bad_alloc
+# define GC_OP_NEW_OOM_CHECK(obj) if (obj) {} else throw std::bad_alloc()
+#else
+ // "new" header is not included, so bad_alloc cannot be thrown directly.
+ GC_API void GC_CALL GC_throw_bad_alloc();
+# define GC_OP_NEW_OOM_CHECK(obj) if (obj) {} else GC_throw_bad_alloc()
+#endif // !GC_NEW_ABORTS_ON_OOM && !GC_INCLUDE_NEW
#ifdef GC_NAMESPACE
namespace boehmgc