1// RUN: %check_clang_tidy %s bugprone-undefined-memory-manipulation %t
2
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 Z
23};
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 types
60
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 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>(b: &vf);
146 memcpy_temp<types::Plain, types::VirtualFunc>(a: &p, b: &vf);
147 memmove_temp<types::Plain, types::VirtualFunc>(a: &p, b: &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

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/undefined-memory-manipulation.cpp