231 lines · cpp
1// RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t2 3void *memset(void *, int, __SIZE_TYPE__);4void *memcpy(void *, const void *, __SIZE_TYPE__);5void *memmove(void *, const void *, __SIZE_TYPE__);6 7namespace std {8using ::memcpy;9using ::memmove;10using ::memset;11}12 13namespace types {14// TriviallyCopyable types:15struct Plain {16 int n;17};18 19enum E {20 X,21 Y,22 Z23};24 25struct Base {26 float b;27};28 29struct Derived : Base {30 bool d;31};32 33// not TriviallyCopyable types:34struct Destruct {35 ~Destruct() {}36};37 38struct Copy {39 Copy() {}40 Copy(const Copy &) {}41};42 43struct Move {44 Move() {}45 Move(Move &&) {}46};47 48struct VirtualFunc {49 virtual void f() {}50};51 52struct VirtualBase : virtual Base {53 int vb;54};55 56// Incomplete type, assume it is TriviallyCopyable.57struct NoDef;58 59} // end namespace types60 61void f(types::NoDef *s) {62 memset(s, 0, 5);63}64 65template <typename T>66void 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 71template <typename S, typename T>72void 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 77template <typename S, typename T>78void 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 83namespace aliases {84using Copy2 = types::Copy;85typedef types::Move Move2;86}87 88void notTriviallyCopyable() {89 types::Plain p; // TriviallyCopyable for variety90 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 types::Copy ca[10];130 memset(ca, 0, sizeof(ca));131 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy[10]'132 memset(&ca, 0, sizeof(ca));133 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Copy[10]'134 135#define MEMSET memset(&vf, 0, sizeof(int));136 MEMSET137 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'138#define MEMCPY memcpy(&d, &p, sizeof(int));139 MEMCPY140 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'141#define MEMMOVE memmove(&p, &c, sizeof(int));142 MEMMOVE143 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, source object type 'types::Copy'144 145 memset_temp<types::VirtualFunc>(&vf);146 memcpy_temp<types::Plain, types::VirtualFunc>(&p, &vf);147 memmove_temp<types::Plain, types::VirtualFunc>(&p, &vf);148 149 aliases::Copy2 c2;150 aliases::Move2 m2;151 memset(&c2, 0, sizeof(int));152 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'153 memset(&m2, 0, sizeof(int));154 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Move2'155 156 typedef aliases::Copy2 Copy3;157 typedef aliases::Copy2 *PCopy2;158 typedef Copy3 *PCopy3;159 Copy3 c3;160 PCopy2 pc2;161 PCopy3 pc3;162 memset(&c3, 0, sizeof(int));163 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'164 memset(pc2, 0, sizeof(int));165 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'aliases::Copy2'166 memset(pc3, 0, sizeof(int));167 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3'168 using Copy3Arr = Copy3[5];169 Copy3Arr c3a;170 memset(c3a, 0, sizeof(c3a));171 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3Arr'172 memset(&c3a, 0, sizeof(c3a));173 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3Arr'174 175 typedef Copy3 Copy3Arr2[5];176 Copy3Arr2 c3a2;177 memset(c3a2, 0, sizeof(c3a2));178 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'Copy3Arr2'179}180 181void triviallyCopyable() {182 types::Plain p;183 types::Base base;184 types::Derived derived;185 186 int i = 5;187 int ia[3] = {1, 2, 3};188 float f = 3.14;189 float fa[3] = {1.1, 2.2, 3.3};190 bool b = false;191 bool ba[2] = {true, false};192 types::E e = types::X;193 p.n = 2;194 195 memset(&p, 0, sizeof(int));196 memset(&base, 0, sizeof(float));197 memset(&derived, 0, sizeof(bool));198 memset(&i, 0, sizeof(int));199 memset(ia, 0, sizeof(int));200 memset(&f, 0, sizeof(float));201 memset(fa, 0, sizeof(float));202 memset(&b, 0, sizeof(bool));203 memset(ba, 0, sizeof(bool));204 memset(&e, 0, sizeof(int));205 memset(&p.n, 0, sizeof(int));206 207 memcpy(&p, &p, sizeof(int));208 memcpy(&base, &base, sizeof(float));209 memcpy(&derived, &derived, sizeof(bool));210 memcpy(&i, &i, sizeof(int));211 memcpy(ia, ia, sizeof(int));212 memcpy(&f, &f, sizeof(float));213 memcpy(fa, fa, sizeof(float));214 memcpy(&b, &b, sizeof(bool));215 memcpy(ba, ba, sizeof(bool));216 memcpy(&e, &e, sizeof(int));217 memcpy(&p.n, &p.n, sizeof(int));218 219 memmove(&p, &p, sizeof(int));220 memmove(&base, &base, sizeof(float));221 memmove(&derived, &derived, sizeof(bool));222 memmove(&i, &i, sizeof(int));223 memmove(ia, ia, sizeof(int));224 memmove(&f, &f, sizeof(float));225 memmove(fa, fa, sizeof(float));226 memmove(&b, &b, sizeof(bool));227 memmove(ba, ba, sizeof(bool));228 memmove(&e, &e, sizeof(int));229 memmove(&p.n, &p.n, sizeof(int));230}231