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