Bug 1411613 - mark certain allocation functions as non-throwing; r=glandium

glibc marks various allocation functions as `throw()`.  This addition
hasn't been a problem until we tried to enable C++17, where clang
started complaining that we were redeclaring functions with mismatched
exception specifications.  Peculiarly, glibc declares virtually
everything we redeclare as `throw()`, but clang only complains about the
mismatches for a particular subset of functions.

The approach taken in this patch is to add another potentially defined
macro to malloc_decls.h, `NOTHROW_MALLOC_DECL`.  This macro works
exactly like `MALLOC_DECL`, except that clients can define
`NOTHROW_MALLOC_DECL` to add appropriate `throw()` specifiers when
declaring functions at global scope, and thereby avoid mismatched
exception specifications.

Differential Revision: https://phabricator.services.mozilla.com/D44045

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nathan Froyd 2019-09-04 23:40:15 +00:00
parent eb4179edc3
commit b47e23e17a
5 changed files with 38 additions and 16 deletions

View File

@ -34,18 +34,31 @@
#endif
#ifdef MALLOC_DECL
// NOTHROW_MALLOC_DECL is intended for functions where the standard library
// declares the functions in question as `throw()`. Not all platforms
// consistent declare certain functions as `throw()`, though.
// Bionic and OS X don't seem to care about `throw()`ness.
# if defined(ANDROID) || defined(XP_DARWIN)
# undef NOTHROW_MALLOC_DECL
# define NOTHROW_MALLOC_DECL MALLOC_DECL
// Some places don't care about the distinction.
# elif !defined(NOTHROW_MALLOC_DECL)
# define NOTHROW_MALLOC_DECL MALLOC_DECL
# endif
# if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC_BASE
MALLOC_DECL(malloc, void*, size_t)
MALLOC_DECL(calloc, void*, size_t, size_t)
MALLOC_DECL(realloc, void*, void*, size_t)
MALLOC_DECL(free, void, void*)
MALLOC_DECL(memalign, void*, size_t, size_t)
NOTHROW_MALLOC_DECL(free, void, void*)
NOTHROW_MALLOC_DECL(memalign, void*, size_t, size_t)
# endif
# if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC_EXTRA
MALLOC_DECL(posix_memalign, int, void**, size_t, size_t)
MALLOC_DECL(aligned_alloc, void*, size_t, size_t)
MALLOC_DECL(valloc, void*, size_t)
MALLOC_DECL(malloc_usable_size, size_t, usable_ptr_t)
NOTHROW_MALLOC_DECL(posix_memalign, int, void**, size_t, size_t)
NOTHROW_MALLOC_DECL(aligned_alloc, void*, size_t, size_t)
NOTHROW_MALLOC_DECL(valloc, void*, size_t)
NOTHROW_MALLOC_DECL(malloc_usable_size, size_t, usable_ptr_t)
MALLOC_DECL(malloc_good_size, size_t, size_t)
# endif
# if MALLOC_FUNCS & MALLOC_FUNCS_JEMALLOC
@ -122,5 +135,6 @@ MALLOC_DECL(moz_arena_memalign, void*, arena_id_t, size_t, size_t)
#endif // MALLOC_DECL
#undef NOTHROW_MALLOC_DECL
#undef MALLOC_DECL
#undef MALLOC_FUNCS

View File

@ -4683,31 +4683,33 @@ static void replace_malloc_init_funcs(malloc_table_t* table) {
return_type name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
__attribute__((alias(MOZ_STRINGIFY(name_impl))));
#define GENERIC_MALLOC_DECL2(name, name_impl, return_type, ...) \
return_type name_impl(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) { \
#define GENERIC_MALLOC_DECL2(attributes, name, name_impl, return_type, ...) \
return_type name_impl(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) attributes { \
return DefaultMalloc::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
}
#ifndef __MINGW32__
# define GENERIC_MALLOC_DECL(name, return_type, ...) \
GENERIC_MALLOC_DECL2(name, name##_impl, return_type, ##__VA_ARGS__)
# define GENERIC_MALLOC_DECL(attributes, name, return_type, ...) \
GENERIC_MALLOC_DECL2(attributes, name, name##_impl, return_type, ##__VA_ARGS__)
#else
# define GENERIC_MALLOC_DECL(name, return_type, ...) \
GENERIC_MALLOC_DECL2(name, name##_impl, return_type, ##__VA_ARGS__) \
# define GENERIC_MALLOC_DECL(attributes, name, return_type, ...) \
GENERIC_MALLOC_DECL2(attributes, name, name##_impl, return_type, ##__VA_ARGS__) \
GENERIC_MALLOC_DECL2_MINGW(name, name##_impl, return_type, ##__VA_ARGS__)
#endif
#define NOTHROW_MALLOC_DECL(...) \
MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL, (noexcept(true), __VA_ARGS__))
#define MALLOC_DECL(...) \
MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL, (, __VA_ARGS__))
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
#include "malloc_decls.h"
#undef GENERIC_MALLOC_DECL
#define GENERIC_MALLOC_DECL(name, return_type, ...) \
GENERIC_MALLOC_DECL2(name, name, return_type, ##__VA_ARGS__)
#define GENERIC_MALLOC_DECL(attributes, name, return_type, ...) \
GENERIC_MALLOC_DECL2(attributes, name, name, return_type, ##__VA_ARGS__)
#define MALLOC_DECL(...) \
MOZ_JEMALLOC_API MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
MOZ_JEMALLOC_API MACRO_CALL(GENERIC_MALLOC_DECL, (, __VA_ARGS__))
#define MALLOC_FUNCS (MALLOC_FUNCS_JEMALLOC | MALLOC_FUNCS_ARENA)
#include "malloc_decls.h"
// ***************************************************************************

View File

@ -50,6 +50,8 @@ static inline size_t _malloc_good_size(size_t size) {
#endif
#define NOTHROW_MALLOC_DECL(name, return_type, ...) \
MOZ_JEMALLOC_API return_type name(__VA_ARGS__) noexcept(true);
#define MALLOC_DECL(name, return_type, ...) \
MOZ_JEMALLOC_API return_type name(__VA_ARGS__);
#define MALLOC_FUNCS MALLOC_FUNCS_ARENA

View File

@ -10,6 +10,8 @@
// Declare malloc implementation functions with the right return and
// argument types.
#define NOTHROW_MALLOC_DECL(name, return_type, ...) \
MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__) noexcept(true);
#define MALLOC_DECL(name, return_type, ...) \
MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__);
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC

View File

@ -16,6 +16,8 @@
// need to use _impl suffixes, which is becoming cumbersome. We'll have to use
// something like a malloc.h wrapper and allow the use of the functions without
// a _impl suffix. In the meanwhile, this is enough to get by for C++ code.
# define NOTHROW_MALLOC_DECL(name, return_type, ...) \
MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__) noexcept(true);
# define MALLOC_DECL(name, return_type, ...) \
MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__);
# include "malloc_decls.h"