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