6 Commits

Author SHA1 Message Date
284a0e3cbf 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.
2018-05-20 21:06:36 -04:00
e2882c8578 Update copyright year range in all GDB files
gdb/ChangeLog:

        Update copyright year range in all GDB files
2018-01-02 07:38:06 +04:00
6d83e819df Fix typo in poison.h
gdb/ChangeLog:

	* common/poison.h (XDELETE): Fix typo.
2017-12-02 20:28:41 -05:00
8172f16b5b Poison XNEW and friends for types that should use new/delete
This patch (finally!) makes it so that trying to use XNEW with a type
that requires "new" will cause a compilation error.  The criterion I
initially used to allow a type to use XNEW (which calls malloc in the
end) was std::is_trivially_constructible, but then realized that gcc 4.8
did not have it.  Instead, I went with:

  using IsMallocatable = std::is_pod<T>;

which is just a bit more strict, which doesn't hurt.  A similar thing is
done for macros that free instead of allocated, the criterion is:

  using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>;

Trying to use XNEW on a type that requires new will result in an error
like this:

    In file included from /home/simark/src/binutils-gdb/gdb/common/common-utils.h:26:0,
                     from /home/simark/src/binutils-gdb/gdb/common/common-defs.h:78,
                     from /home/simark/src/binutils-gdb/gdb/defs.h:28,
                     from /home/simark/src/binutils-gdb/gdb/lala.c:1:
    /home/simark/src/binutils-gdb/gdb/common/poison.h: In instantiation of ‘T* xnew() [with T = bar]’:
    /home/simark/src/binutils-gdb/gdb/lala.c:13:3:   required from here
    /home/simark/src/binutils-gdb/gdb/common/poison.h:103:3: error: static assertion failed: Trying to use XNEW with a non-POD data type.  Use operator new instead.
       static_assert (IsMallocatable<T>::value, "Trying to use XNEW with a non-POD\
       ^~~~~~~~~~~~~

Generated-code-wise, it adds one more function call (xnew<T>) when using
XNEW and building with -O0, but it all goes away with optimizations
enabled.

gdb/ChangeLog:

	* common/common-utils.h: Include poison.h.
	(xfree): Remove declaration, add definition with static_assert.
	* common/common-utils.c (xfree): Remove.
	* common/poison.h (IsMallocatable): Define.
	(IsFreeable): Define.
	(free): Delete for non-freeable types.
	(xnew): New.
	(XNEW): Undef and redefine.
	(xcnew): New.
	(XCNEW): Undef and redefine.
	(xdelete): New.
	(XDELETE): Undef and redefine.
	(xnewvec): New.
	(XNEWVEC): Undef and redefine.
	(xcnewvec): New.
	(XCNEWVEC): Undef and redefine.
	(xresizevec): New.
	(XRESIZEVEC): Undef and redefine.
	(xdeletevec): New.
	(XDELETEVEC): Undef and redefine.
	(xnewvar): New.
	(XNEWVAR): Undef and redefine.
	(xcnewvar): New.
	(XCNEWVAR): Undef and redefine.
	(xresizevar): New.
	(XRESIZEVAR): Undef and redefine.
2017-11-24 10:42:25 -05:00
debed3db48 Fix build on gcc < 5 (std::is_trivially_copyable missing)
Ref: https://sourceware.org/ml/gdb-patches/2017-04/msg00660.html

Simply skip the poisoning on older compilers.

gdb/ChangeLog:
2017-04-25  Pedro Alves  <palves@redhat.com>

	* common/poison.h [!HAVE_IS_TRIVIALLY_COPYABLE] (IsRelocatable)
	(BothAreRelocatable, memcopy, memmove): Don't define.
	* common/traits.h (__has_feature, HAVE_IS_TRIVIALLY_COPYABLE): New
	macros.
2017-04-25 10:58:57 +01:00
b0b92aeb38 Poison non-POD memset & non-trivially-copyable memcpy/memmove
This patch catches invalid initialization of non-POD types with
memset, at compile time.

This is what I used to catch the problems fixed by the previous
patches in the series:

  $ make -k 2>&1 | grep "deleted function"
  src/gdb/breakpoint.c:951:53: error: use of deleted function ‘void* memset(T*, int, size_t) [with T = bp_location; <template-parameter-1-2> = void; size_t = long unsigned int]’
  src/gdb/breakpoint.c:7325:32: error: use of deleted function ‘void* memset(T*, int, size_t) [with T = bp_location; <template-parameter-1-2> = void; size_t = long unsigned int]’
  src/gdb/btrace.c:1153:42: error: use of deleted function ‘void* memset(T*, int, size_t) [with T = btrace_insn; <template-parameter-1-2> = void; size_t = long unsigned int]’
...

gdb/ChangeLog:
2017-04-25  Pedro Alves  <palves@redhat.com>

	* common/common-defs.h: Include "common/poison.h".
	* common/function-view.h: (Not, Or, Requires): Move to traits.h
	and adjust.
	* common/poison.h: New file.
	* common/traits.h: Include <type_traits>.
	(Not, Or, Requires): New, moved from common/function-view.h.
2017-04-25 01:46:19 +01:00