xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/poison.h (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
18dffb485Schristos /* Poison symbols at compile time.
28dffb485Schristos 
3*5ba1f45fSchristos    Copyright (C) 2017-2024 Free Software Foundation, Inc.
48dffb485Schristos 
58dffb485Schristos    This file is part of GDB.
68dffb485Schristos 
78dffb485Schristos    This program is free software; you can redistribute it and/or modify
88dffb485Schristos    it under the terms of the GNU General Public License as published by
98dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
108dffb485Schristos    (at your option) any later version.
118dffb485Schristos 
128dffb485Schristos    This program is distributed in the hope that it will be useful,
138dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
148dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158dffb485Schristos    GNU General Public License for more details.
168dffb485Schristos 
178dffb485Schristos    You should have received a copy of the GNU General Public License
188dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
198dffb485Schristos 
208dffb485Schristos #ifndef COMMON_POISON_H
218dffb485Schristos #define COMMON_POISON_H
228dffb485Schristos 
238dffb485Schristos #include "traits.h"
248dffb485Schristos #include "obstack.h"
258dffb485Schristos 
268dffb485Schristos /* Poison memset of non-POD types.  The idea is catching invalid
278dffb485Schristos    initialization of non-POD structs that is easy to be introduced as
288dffb485Schristos    side effect of refactoring.  For example, say this:
298dffb485Schristos 
308dffb485Schristos  struct S { VEC(foo_s) *m_data; };
318dffb485Schristos 
328dffb485Schristos is converted to this at some point:
338dffb485Schristos 
348dffb485Schristos  struct S {
358dffb485Schristos    S() { m_data.reserve (10); }
368dffb485Schristos    std::vector<foo> m_data;
378dffb485Schristos  };
388dffb485Schristos 
398dffb485Schristos and old code was initializing S objects like this:
408dffb485Schristos 
418dffb485Schristos  struct S s;
428dffb485Schristos  memset (&s, 0, sizeof (S)); // whoops, now wipes vector.
438dffb485Schristos 
448dffb485Schristos Declaring memset as deleted for non-POD types makes the memset above
458dffb485Schristos be a compile-time error.  */
468dffb485Schristos 
478dffb485Schristos /* Helper for SFINAE.  True if "T *" is memsettable.  I.e., if T is
488dffb485Schristos    either void, or POD.  */
498dffb485Schristos template<typename T>
508dffb485Schristos struct IsMemsettable
518dffb485Schristos   : gdb::Or<std::is_void<T>,
52*5ba1f45fSchristos 	    gdb::And<std::is_standard_layout<T>, std::is_trivial<T>>>
538dffb485Schristos {};
548dffb485Schristos 
558dffb485Schristos template <typename T,
568dffb485Schristos 	  typename = gdb::Requires<gdb::Not<IsMemsettable<T>>>>
578dffb485Schristos void *memset (T *s, int c, size_t n) = delete;
588dffb485Schristos 
598dffb485Schristos /* Similarly, poison memcpy and memmove of non trivially-copyable
608dffb485Schristos    types, which is undefined.  */
618dffb485Schristos 
628dffb485Schristos /* True if "T *" is relocatable.  I.e., copyable with memcpy/memmove.
638dffb485Schristos    I.e., T is either trivially copyable, or void.  */
648dffb485Schristos template<typename T>
658dffb485Schristos struct IsRelocatable
668dffb485Schristos   : gdb::Or<std::is_void<T>,
678dffb485Schristos 	    std::is_trivially_copyable<T>>
688dffb485Schristos {};
698dffb485Schristos 
708dffb485Schristos /* True if both source and destination are relocatable.  */
718dffb485Schristos 
728dffb485Schristos template <typename D, typename S>
738dffb485Schristos using BothAreRelocatable
748dffb485Schristos   = gdb::And<IsRelocatable<D>, IsRelocatable<S>>;
758dffb485Schristos 
768dffb485Schristos template <typename D, typename S,
778dffb485Schristos 	  typename = gdb::Requires<gdb::Not<BothAreRelocatable<D, S>>>>
788dffb485Schristos void *memcpy (D *dest, const S *src, size_t n) = delete;
798dffb485Schristos 
808dffb485Schristos template <typename D, typename S,
818dffb485Schristos 	  typename = gdb::Requires<gdb::Not<BothAreRelocatable<D, S>>>>
828dffb485Schristos void *memmove (D *dest, const S *src, size_t n) = delete;
838dffb485Schristos 
848dffb485Schristos /* Poison XNEW and friends to catch usages of malloc-style allocations on
858dffb485Schristos    objects that require new/delete.  */
868dffb485Schristos 
878dffb485Schristos template<typename T>
888dffb485Schristos using IsMallocable = std::is_trivially_constructible<T>;
898dffb485Schristos 
908dffb485Schristos template<typename T>
918dffb485Schristos using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>;
928dffb485Schristos 
938dffb485Schristos template <typename T, typename = gdb::Requires<gdb::Not<IsFreeable<T>>>>
948dffb485Schristos void free (T *ptr) = delete;
958dffb485Schristos 
968dffb485Schristos template<typename T>
978dffb485Schristos static T *
988dffb485Schristos xnew ()
998dffb485Schristos {
1008dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XNEW with a non-POD \
1018dffb485Schristos data type.  Use operator new instead.");
1028dffb485Schristos   return XNEW (T);
1038dffb485Schristos }
1048dffb485Schristos 
1058dffb485Schristos #undef XNEW
1068dffb485Schristos #define XNEW(T) xnew<T>()
1078dffb485Schristos 
1088dffb485Schristos template<typename T>
1098dffb485Schristos static T *
1108dffb485Schristos xcnew ()
1118dffb485Schristos {
1128dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XCNEW with a non-POD \
1138dffb485Schristos data type.  Use operator new instead.");
1148dffb485Schristos   return XCNEW (T);
1158dffb485Schristos }
1168dffb485Schristos 
1178dffb485Schristos #undef XCNEW
1188dffb485Schristos #define XCNEW(T) xcnew<T>()
1198dffb485Schristos 
1208dffb485Schristos template<typename T>
1218dffb485Schristos static void
1228dffb485Schristos xdelete (T *p)
1238dffb485Schristos {
1248dffb485Schristos   static_assert (IsFreeable<T>::value, "Trying to use XDELETE with a non-POD \
1258dffb485Schristos data type.  Use operator delete instead.");
1268dffb485Schristos   XDELETE (p);
1278dffb485Schristos }
1288dffb485Schristos 
1298dffb485Schristos #undef XDELETE
1308dffb485Schristos #define XDELETE(P) xdelete (P)
1318dffb485Schristos 
1328dffb485Schristos template<typename T>
1338dffb485Schristos static T *
1348dffb485Schristos xnewvec (size_t n)
1358dffb485Schristos {
1368dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XNEWVEC with a \
1378dffb485Schristos non-POD data type.  Use operator new[] (or std::vector) instead.");
1388dffb485Schristos   return XNEWVEC (T, n);
1398dffb485Schristos }
1408dffb485Schristos 
1418dffb485Schristos #undef XNEWVEC
1428dffb485Schristos #define XNEWVEC(T, N) xnewvec<T> (N)
1438dffb485Schristos 
1448dffb485Schristos template<typename T>
1458dffb485Schristos static T *
1468dffb485Schristos xcnewvec (size_t n)
1478dffb485Schristos {
1488dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XCNEWVEC with a \
1498dffb485Schristos non-POD data type.  Use operator new[] (or std::vector) instead.");
1508dffb485Schristos   return XCNEWVEC (T, n);
1518dffb485Schristos }
1528dffb485Schristos 
1538dffb485Schristos #undef XCNEWVEC
1548dffb485Schristos #define XCNEWVEC(T, N) xcnewvec<T> (N)
1558dffb485Schristos 
1568dffb485Schristos template<typename T>
1578dffb485Schristos static T *
1588dffb485Schristos xresizevec (T *p, size_t n)
1598dffb485Schristos {
1608dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XRESIZEVEC with a \
1618dffb485Schristos non-POD data type.");
1628dffb485Schristos   return XRESIZEVEC (T, p, n);
1638dffb485Schristos }
1648dffb485Schristos 
1658dffb485Schristos #undef XRESIZEVEC
1668dffb485Schristos #define XRESIZEVEC(T, P, N) xresizevec<T> (P, N)
1678dffb485Schristos 
1688dffb485Schristos template<typename T>
1698dffb485Schristos static void
1708dffb485Schristos xdeletevec (T *p)
1718dffb485Schristos {
1728dffb485Schristos   static_assert (IsFreeable<T>::value, "Trying to use XDELETEVEC with a \
1738dffb485Schristos non-POD data type.  Use operator delete[] (or std::vector) instead.");
1748dffb485Schristos   XDELETEVEC (p);
1758dffb485Schristos }
1768dffb485Schristos 
1778dffb485Schristos #undef XDELETEVEC
1788dffb485Schristos #define XDELETEVEC(P) xdeletevec (P)
1798dffb485Schristos 
1808dffb485Schristos template<typename T>
1818dffb485Schristos static T *
1828dffb485Schristos xnewvar (size_t s)
1838dffb485Schristos {
1848dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XNEWVAR with a \
1858dffb485Schristos non-POD data type.");
1868dffb485Schristos   return XNEWVAR (T, s);;
1878dffb485Schristos }
1888dffb485Schristos 
1898dffb485Schristos #undef XNEWVAR
1908dffb485Schristos #define XNEWVAR(T, S) xnewvar<T> (S)
1918dffb485Schristos 
1928dffb485Schristos template<typename T>
1938dffb485Schristos static T *
1948dffb485Schristos xcnewvar (size_t s)
1958dffb485Schristos {
1968dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XCNEWVAR with a \
1978dffb485Schristos non-POD data type.");
1988dffb485Schristos   return XCNEWVAR (T, s);
1998dffb485Schristos }
2008dffb485Schristos 
2018dffb485Schristos #undef XCNEWVAR
2028dffb485Schristos #define XCNEWVAR(T, S) xcnewvar<T> (S)
2038dffb485Schristos 
2048dffb485Schristos template<typename T>
2058dffb485Schristos static T *
2068dffb485Schristos xresizevar (T *p, size_t s)
2078dffb485Schristos {
2088dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XRESIZEVAR with a \
2098dffb485Schristos non-POD data type.");
2108dffb485Schristos   return XRESIZEVAR (T, p, s);
2118dffb485Schristos }
2128dffb485Schristos 
2138dffb485Schristos #undef XRESIZEVAR
2148dffb485Schristos #define XRESIZEVAR(T, P, S) xresizevar<T> (P, S)
2158dffb485Schristos 
2168dffb485Schristos template<typename T>
2178dffb485Schristos static T *
2188dffb485Schristos xobnew (obstack *ob)
2198dffb485Schristos {
2208dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XOBNEW with a \
2218dffb485Schristos non-POD data type.");
2228dffb485Schristos   return XOBNEW (ob, T);
2238dffb485Schristos }
2248dffb485Schristos 
2258dffb485Schristos #undef XOBNEW
2268dffb485Schristos #define XOBNEW(O, T) xobnew<T> (O)
2278dffb485Schristos 
2288dffb485Schristos template<typename T>
2298dffb485Schristos static T *
2308dffb485Schristos xobnewvec (obstack *ob, size_t n)
2318dffb485Schristos {
2328dffb485Schristos   static_assert (IsMallocable<T>::value, "Trying to use XOBNEWVEC with a \
2338dffb485Schristos non-POD data type.");
2348dffb485Schristos   return XOBNEWVEC (ob, T, n);
2358dffb485Schristos }
2368dffb485Schristos 
2378dffb485Schristos #undef XOBNEWVEC
2388dffb485Schristos #define XOBNEWVEC(O, T, N) xobnewvec<T> (O, N)
2398dffb485Schristos 
2408dffb485Schristos #endif /* COMMON_POISON_H */
241