poison.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* Poison symbols at compile time.
  2. Copyright (C) 2017-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #ifndef COMMON_POISON_H
  15. #define COMMON_POISON_H
  16. #include "traits.h"
  17. #include "obstack.h"
  18. /* Poison memset of non-POD types. The idea is catching invalid
  19. initialization of non-POD structs that is easy to be introduced as
  20. side effect of refactoring. For example, say this:
  21. struct S { VEC(foo_s) *m_data; };
  22. is converted to this at some point:
  23. struct S {
  24. S() { m_data.reserve (10); }
  25. std::vector<foo> m_data;
  26. };
  27. and old code was initializing S objects like this:
  28. struct S s;
  29. memset (&s, 0, sizeof (S)); // whoops, now wipes vector.
  30. Declaring memset as deleted for non-POD types makes the memset above
  31. be a compile-time error. */
  32. /* Helper for SFINAE. True if "T *" is memsettable. I.e., if T is
  33. either void, or POD. */
  34. template<typename T>
  35. struct IsMemsettable
  36. : gdb::Or<std::is_void<T>,
  37. std::is_pod<T>>
  38. {};
  39. template <typename T,
  40. typename = gdb::Requires<gdb::Not<IsMemsettable<T>>>>
  41. void *memset (T *s, int c, size_t n) = delete;
  42. #if HAVE_IS_TRIVIALLY_COPYABLE
  43. /* Similarly, poison memcpy and memmove of non trivially-copyable
  44. types, which is undefined. */
  45. /* True if "T *" is relocatable. I.e., copyable with memcpy/memmove.
  46. I.e., T is either trivially copyable, or void. */
  47. template<typename T>
  48. struct IsRelocatable
  49. : gdb::Or<std::is_void<T>,
  50. std::is_trivially_copyable<T>>
  51. {};
  52. /* True if both source and destination are relocatable. */
  53. template <typename D, typename S>
  54. using BothAreRelocatable
  55. = gdb::And<IsRelocatable<D>, IsRelocatable<S>>;
  56. template <typename D, typename S,
  57. typename = gdb::Requires<gdb::Not<BothAreRelocatable<D, S>>>>
  58. void *memcpy (D *dest, const S *src, size_t n) = delete;
  59. template <typename D, typename S,
  60. typename = gdb::Requires<gdb::Not<BothAreRelocatable<D, S>>>>
  61. void *memmove (D *dest, const S *src, size_t n) = delete;
  62. #endif /* HAVE_IS_TRIVIALLY_COPYABLE */
  63. /* Poison XNEW and friends to catch usages of malloc-style allocations on
  64. objects that require new/delete. */
  65. template<typename T>
  66. #if HAVE_IS_TRIVIALLY_CONSTRUCTIBLE
  67. using IsMallocable = std::is_trivially_constructible<T>;
  68. #else
  69. using IsMallocable = std::true_type;
  70. #endif
  71. template<typename T>
  72. using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>;
  73. template <typename T, typename = gdb::Requires<gdb::Not<IsFreeable<T>>>>
  74. void free (T *ptr) = delete;
  75. template<typename T>
  76. static T *
  77. xnew ()
  78. {
  79. static_assert (IsMallocable<T>::value, "Trying to use XNEW with a non-POD \
  80. data type. Use operator new instead.");
  81. return XNEW (T);
  82. }
  83. #undef XNEW
  84. #define XNEW(T) xnew<T>()
  85. template<typename T>
  86. static T *
  87. xcnew ()
  88. {
  89. static_assert (IsMallocable<T>::value, "Trying to use XCNEW with a non-POD \
  90. data type. Use operator new instead.");
  91. return XCNEW (T);
  92. }
  93. #undef XCNEW
  94. #define XCNEW(T) xcnew<T>()
  95. template<typename T>
  96. static void
  97. xdelete (T *p)
  98. {
  99. static_assert (IsFreeable<T>::value, "Trying to use XDELETE with a non-POD \
  100. data type. Use operator delete instead.");
  101. XDELETE (p);
  102. }
  103. #undef XDELETE
  104. #define XDELETE(P) xdelete (P)
  105. template<typename T>
  106. static T *
  107. xnewvec (size_t n)
  108. {
  109. static_assert (IsMallocable<T>::value, "Trying to use XNEWVEC with a \
  110. non-POD data type. Use operator new[] (or std::vector) instead.");
  111. return XNEWVEC (T, n);
  112. }
  113. #undef XNEWVEC
  114. #define XNEWVEC(T, N) xnewvec<T> (N)
  115. template<typename T>
  116. static T *
  117. xcnewvec (size_t n)
  118. {
  119. static_assert (IsMallocable<T>::value, "Trying to use XCNEWVEC with a \
  120. non-POD data type. Use operator new[] (or std::vector) instead.");
  121. return XCNEWVEC (T, n);
  122. }
  123. #undef XCNEWVEC
  124. #define XCNEWVEC(T, N) xcnewvec<T> (N)
  125. template<typename T>
  126. static T *
  127. xresizevec (T *p, size_t n)
  128. {
  129. static_assert (IsMallocable<T>::value, "Trying to use XRESIZEVEC with a \
  130. non-POD data type.");
  131. return XRESIZEVEC (T, p, n);
  132. }
  133. #undef XRESIZEVEC
  134. #define XRESIZEVEC(T, P, N) xresizevec<T> (P, N)
  135. template<typename T>
  136. static void
  137. xdeletevec (T *p)
  138. {
  139. static_assert (IsFreeable<T>::value, "Trying to use XDELETEVEC with a \
  140. non-POD data type. Use operator delete[] (or std::vector) instead.");
  141. XDELETEVEC (p);
  142. }
  143. #undef XDELETEVEC
  144. #define XDELETEVEC(P) xdeletevec (P)
  145. template<typename T>
  146. static T *
  147. xnewvar (size_t s)
  148. {
  149. static_assert (IsMallocable<T>::value, "Trying to use XNEWVAR with a \
  150. non-POD data type.");
  151. return XNEWVAR (T, s);;
  152. }
  153. #undef XNEWVAR
  154. #define XNEWVAR(T, S) xnewvar<T> (S)
  155. template<typename T>
  156. static T *
  157. xcnewvar (size_t s)
  158. {
  159. static_assert (IsMallocable<T>::value, "Trying to use XCNEWVAR with a \
  160. non-POD data type.");
  161. return XCNEWVAR (T, s);
  162. }
  163. #undef XCNEWVAR
  164. #define XCNEWVAR(T, S) xcnewvar<T> (S)
  165. template<typename T>
  166. static T *
  167. xresizevar (T *p, size_t s)
  168. {
  169. static_assert (IsMallocable<T>::value, "Trying to use XRESIZEVAR with a \
  170. non-POD data type.");
  171. return XRESIZEVAR (T, p, s);
  172. }
  173. #undef XRESIZEVAR
  174. #define XRESIZEVAR(T, P, S) xresizevar<T> (P, S)
  175. template<typename T>
  176. static T *
  177. xobnew (obstack *ob)
  178. {
  179. static_assert (IsMallocable<T>::value, "Trying to use XOBNEW with a \
  180. non-POD data type.");
  181. return XOBNEW (ob, T);
  182. }
  183. #undef XOBNEW
  184. #define XOBNEW(O, T) xobnew<T> (O)
  185. template<typename T>
  186. static T *
  187. xobnewvec (obstack *ob, size_t n)
  188. {
  189. static_assert (IsMallocable<T>::value, "Trying to use XOBNEWVEC with a \
  190. non-POD data type.");
  191. return XOBNEWVEC (ob, T, n);
  192. }
  193. #undef XOBNEWVEC
  194. #define XOBNEWVEC(O, T, N) xobnewvec<T> (O, N)
  195. #endif /* COMMON_POISON_H */