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 {
~Destructtypes::Destruct35   ~Destruct() {}
36 };
37 
38 struct Copy {
Copytypes::Copy39   Copy() {}
Copytypes::Copy40   Copy(const Copy &) {}
41 };
42 
43 struct Move {
Movetypes::Move44   Move() {}
Movetypes::Move45   Move(Move &&) {}
46 };
47 
48 struct VirtualFunc {
ftypes::VirtualFunc49   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 
f(types::NoDef * s)61 void f(types::NoDef *s) {
62   memset(s, 0, 5);
63 }
64 
65 template <typename T>
memset_temp(T * b)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>
memcpy_temp(S * a,T * b)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>
memmove_temp(S * a,T * b)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 
notTriviallyCopyable()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   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   MEMSET
137   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::VirtualFunc'
138 #define MEMCPY memcpy(&d, &p, sizeof(int));
139   MEMCPY
140   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: undefined behavior, destination object type 'types::Destruct'
141 #define MEMMOVE memmove(&p, &c, sizeof(int));
142   MEMMOVE
143   // 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 
triviallyCopyable()181 void 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