1 // RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t 2 3 void *memset(void *, int, __SIZE_TYPE__); 4 void *memcpy(void *, const void *, __SIZE_TYPE__); 5 void *memmove(void *, const void *, __SIZE_TYPE__); 6 7 namespace std { 8 using ::memcpy; 9 using ::memmove; 10 using ::memset; 11 } 12 13 namespace types { 14 // TriviallyCopyable types: 15 struct Plain { 16 int n; 17 }; 18 19 enum E { 20 X, 21 Y, 22 Z 23 }; 24 25 struct Base { 26 float b; 27 }; 28 29 struct Derived : Base { 30 bool d; 31 }; 32 33 // not TriviallyCopyable types: 34 struct Destruct { 35 ~Destruct() {} 36 }; 37 38 struct Copy { 39 Copy() {} 40 Copy(const Copy &) {} 41 }; 42 43 struct Move { 44 Move() {} 45 Move(Move &&) {} 46 }; 47 48 struct VirtualFunc { 49 virtual void f() {} 50 }; 51 52 struct VirtualBase : virtual Base { 53 int vb; 54 }; 55 56 // Incomplete type, assume it is TriviallyCopyable. 57 struct NoDef; 58 59 } // end namespace types 60 61 void f(types::NoDef *s) { 62 memset(s, 0, 5); 63 } 64 65 template <typename T> 66 void memset_temp(T *b) { 67 memset(b, 0, sizeof(T)); 68 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' is not TriviallyCopyable [bugprone-undefined-memory-manipulation] 69 } 70 71 template <typename S, typename T> 72 void memcpy_temp(S *a, T *b) { 73 memcpy(a, b, sizeof(T)); 74 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc' 75 } 76 77 template <typename S, typename T> 78 void memmove_temp(S *a, T *b) { 79 memmove(a, b, sizeof(T)); 80 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc' 81 } 82 83 namespace aliases { 84 using Copy2 = types::Copy; 85 typedef types::Move Move2; 86 } 87 88 void notTriviallyCopyable() { 89 types::Plain p; // TriviallyCopyable for variety 90 types::Destruct d; 91 types::Copy c; 92 types::Move m; 93 types::VirtualFunc vf; 94 types::VirtualBase vb; 95 96 memset(&vf, 0, sizeof(int)); 97 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' 98 memset(&d, 0, sizeof(int)); 99 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct' 100 memset(&c, 0, sizeof(int)); 101 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy' 102 std::memset(&m, 0, sizeof(int)); 103 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move' 104 ::memset(&vb, 0, sizeof(int)); 105 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase' 106 107 memcpy(&p, &vf, sizeof(int)); 108 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualFunc' 109 memcpy(&p, &d, sizeof(int)); 110 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Destruct' 111 memcpy(&c, &p, sizeof(int)); 112 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy' 113 std::memcpy(&m, &p, sizeof(int)); 114 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Move' 115 ::memcpy(&vb, &p, sizeof(int)); 116 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualBase' 117 118 memmove(&vf, &p, sizeof(int)); 119 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' 120 memmove(&d, &p, sizeof(int)); 121 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct' 122 memmove(&p, &c, sizeof(int)); 123 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy' 124 std::memmove(&p, &m, sizeof(int)); 125 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Move' 126 ::memmove(&p, &vb, sizeof(int)); 127 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::VirtualBase' 128 129 #define MEMSET memset(&vf, 0, sizeof(int)); 130 MEMSET 131 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc' 132 #define MEMCPY memcpy(&d, &p, sizeof(int)); 133 MEMCPY 134 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct' 135 #define MEMMOVE memmove(&p, &c, sizeof(int)); 136 MEMMOVE 137 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy' 138 139 memset_temp<types::VirtualFunc>(&vf); 140 memcpy_temp<types::Plain, types::VirtualFunc>(&p, &vf); 141 memmove_temp<types::Plain, types::VirtualFunc>(&p, &vf); 142 143 aliases::Copy2 c2; 144 aliases::Move2 m2; 145 memset(&c2, 0, sizeof(int)); 146 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2' 147 memset(&m2, 0, sizeof(int)); 148 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Move2' 149 150 typedef aliases::Copy2 Copy3; 151 typedef aliases::Copy2 *PCopy2; 152 typedef Copy3 *PCopy3; 153 Copy3 c3; 154 PCopy2 pc2; 155 PCopy3 pc3; 156 memset(&c3, 0, sizeof(int)); 157 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3' 158 memset(pc2, 0, sizeof(int)); 159 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2' 160 memset(pc3, 0, sizeof(int)); 161 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3' 162 } 163 164 void triviallyCopyable() { 165 types::Plain p; 166 types::Base base; 167 types::Derived derived; 168 169 int i = 5; 170 int ia[3] = {1, 2, 3}; 171 float f = 3.14; 172 float fa[3] = {1.1, 2.2, 3.3}; 173 bool b = false; 174 bool ba[2] = {true, false}; 175 types::E e = types::X; 176 p.n = 2; 177 178 memset(&p, 0, sizeof(int)); 179 memset(&base, 0, sizeof(float)); 180 memset(&derived, 0, sizeof(bool)); 181 memset(&i, 0, sizeof(int)); 182 memset(ia, 0, sizeof(int)); 183 memset(&f, 0, sizeof(float)); 184 memset(fa, 0, sizeof(float)); 185 memset(&b, 0, sizeof(bool)); 186 memset(ba, 0, sizeof(bool)); 187 memset(&e, 0, sizeof(int)); 188 memset(&p.n, 0, sizeof(int)); 189 190 memcpy(&p, &p, sizeof(int)); 191 memcpy(&base, &base, sizeof(float)); 192 memcpy(&derived, &derived, sizeof(bool)); 193 memcpy(&i, &i, sizeof(int)); 194 memcpy(ia, ia, sizeof(int)); 195 memcpy(&f, &f, sizeof(float)); 196 memcpy(fa, fa, sizeof(float)); 197 memcpy(&b, &b, sizeof(bool)); 198 memcpy(ba, ba, sizeof(bool)); 199 memcpy(&e, &e, sizeof(int)); 200 memcpy(&p.n, &p.n, sizeof(int)); 201 202 memmove(&p, &p, sizeof(int)); 203 memmove(&base, &base, sizeof(float)); 204 memmove(&derived, &derived, sizeof(bool)); 205 memmove(&i, &i, sizeof(int)); 206 memmove(ia, ia, sizeof(int)); 207 memmove(&f, &f, sizeof(float)); 208 memmove(fa, fa, sizeof(float)); 209 memmove(&b, &b, sizeof(bool)); 210 memmove(ba, ba, sizeof(bool)); 211 memmove(&e, &e, sizeof(int)); 212 memmove(&p.n, &p.n, sizeof(int)); 213 } 214