diff options
author | Simon Marchi <simon.marchi@ericsson.com> | 2018-05-20 21:06:03 -0400 |
---|---|---|
committer | Simon Marchi <simon.marchi@polymtl.ca> | 2018-05-20 21:06:36 -0400 |
commit | 284a0e3cbffa92ee5c94065fcdd5a528482344fc (patch) | |
tree | 8b7ad3a53e77adf130a5f33ed306fe76d4ab0ff8 /gdb/gdb_obstack.h | |
parent | b1aed5de0cc075ab5061453f88cedbf2d3e97ff6 (diff) | |
download | binutils-gdb-284a0e3cbffa92ee5c94065fcdd5a528482344fc.tar.gz |
Introduce obstack_new, poison other "typed" obstack functions
Since we use obstacks with objects that are not default constructible,
we sometimes need to manually call the constructor by hand using
placement new:
foo *f = obstack_alloc (obstack, sizeof (foo));
f = new (f) foo;
It's possible to use allocate_on_obstack instead, but there are types
that we sometimes want to allocate on an obstack, and sometimes on the
regular heap. This patch introduces a utility to make this pattern
simpler if allocate_on_obstack is not an option:
foo *f = obstack_new<foo> (obstack);
Right now there's only one usage (in tdesc_data_init).
To help catch places where we would forget to call new when allocating
such an object on an obstack, this patch also poisons some other methods
of allocating an instance of a type on an obstack:
- OBSTACK_ZALLOC/OBSTACK_CALLOC
- XOBNEW/XOBNEW
- GDBARCH_OBSTACK_ZALLOC/GDBARCH_OBSTACK_CALLOC
Unfortunately, there's no way to catch wrong usages of obstack_alloc.
By pulling on that string though, it tripped on allocating struct
template_symbol using OBSTACK_ZALLOC. The criterion currently used to
know whether it's safe to "malloc" an instance of a struct is whether it
is a POD. Because it inherits from struct symbol, template_symbol is
not a POD. This criterion is a bit too strict however, it should still
safe to allocate memory for a template_symbol and memset it to 0. We
didn't use is_trivially_constructible as the criterion in the first
place only because it is not available in gcc < 5. So here I considered
two alternatives:
1. Relax that criterion to use std::is_trivially_constructible and add a
bit more glue code to make it work with gcc < 5
2. Continue pulling on the string and change how the symbol structures
are allocated and initialized
I managed to do both, but I decided to go with #1 to keep this patch
simpler and more focused. When building with a compiler that does not
have is_trivially_constructible, the check will just not be enforced.
gdb/ChangeLog:
* common/traits.h (HAVE_IS_TRIVIALLY_COPYABLE): Define if
compiler supports std::is_trivially_constructible.
* common/poison.h: Include obstack.h.
(IsMallocable): Define to is_trivially_constructible if the
compiler supports it, define to true_type otherwise.
(xobnew): New.
(XOBNEW): Redefine.
(xobnewvec): New.
(XOBNEWVEC): Redefine.
* gdb_obstack.h (obstack_zalloc): New.
(OBSTACK_ZALLOC): Redefine.
(obstack_calloc): New.
(OBSTACK_CALLOC): Redefine.
(obstack_new): New.
* gdbarch.sh: Include gdb_obstack in gdbarch.h.
(gdbarch_obstack): New declaration in gdbarch.h, definition in
gdbarch.c.
(GDBARCH_OBSTACK_CALLOC, GDBARCH_OBSTACK_ZALLOC): Use
obstack_calloc/obstack_zalloc.
(gdbarch_obstack_zalloc): Remove.
* target-descriptions.c (tdesc_data_init): Use obstack_new.
Diffstat (limited to 'gdb/gdb_obstack.h')
-rw-r--r-- | gdb/gdb_obstack.h | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/gdb/gdb_obstack.h b/gdb/gdb_obstack.h index 1011008ffbd..29cad937e4e 100644 --- a/gdb/gdb_obstack.h +++ b/gdb/gdb_obstack.h @@ -24,12 +24,40 @@ /* Utility macros - wrap obstack alloc into something more robust. */ -#define OBSTACK_ZALLOC(OBSTACK,TYPE) \ - ((TYPE *) memset (obstack_alloc ((OBSTACK), sizeof (TYPE)), 0, sizeof (TYPE))) +template <typename T> +static inline T* +obstack_zalloc (struct obstack *ob) +{ + static_assert (IsMallocable<T>::value, "Trying to use OBSTACK_ZALLOC with a \ +non-POD data type. Use obstack_new instead."); + return ((T *) memset (obstack_alloc (ob, sizeof (T)), 0, sizeof (T))); +} + +#define OBSTACK_ZALLOC(OBSTACK,TYPE) obstack_zalloc<TYPE> ((OBSTACK)) + +template <typename T> +static inline T * +obstack_calloc (struct obstack *ob, size_t number) +{ + static_assert (IsMallocable<T>::value, "Trying to use OBSTACK_CALLOC with a \ +non-POD data type. Use obstack_new instead."); + return ((T *) memset (obstack_alloc (ob, number * sizeof (T)), 0, + number * sizeof (T))); +} #define OBSTACK_CALLOC(OBSTACK,NUMBER,TYPE) \ - ((TYPE *) memset (obstack_alloc ((OBSTACK), (NUMBER) * sizeof (TYPE)), \ - 0, (NUMBER) * sizeof (TYPE))) + obstack_calloc<TYPE> ((OBSTACK), (NUMBER)) + +/* Allocate an object on OB and call its constructor. */ + +template <typename T, typename... Args> +static inline T* +obstack_new (struct obstack *ob, Args&&... args) +{ + T* object = (T *) obstack_alloc (ob, sizeof (T)); + object = new (object) T (std::forward<Args> (args)...); + return object; +} /* Unless explicitly specified, GDB obstacks always use xmalloc() and xfree(). */ |