Home | History | Annotate | Line # | Download | only in gdbsupport
      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