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 #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
triviallyCopyable()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