1 // RUN: %check_clang_tidy %s bugprone-suspicious-memory-comparison %t \
2 // RUN: -- -- -target x86_64-unknown-unknown
3
4 namespace std {
5 typedef __SIZE_TYPE__ size_t;
6 int memcmp(const void *lhs, const void *rhs, size_t count);
7 } // namespace std
8
9 namespace sei_cert_example_oop57_cpp {
10 class C {
11 int i;
12
13 public:
14 virtual void f();
15 };
16
f(C & c1,C & c2)17 void f(C &c1, C &c2) {
18 if (!std::memcmp(&c1, &c2, sizeof(C))) {
19 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: comparing object representation of non-standard-layout type 'C'; consider using a comparison operator instead
20 }
21 }
22 } // namespace sei_cert_example_oop57_cpp
23
24 namespace inner_padding_64bit_only {
25 struct S {
26 int x;
27 int *y;
28 };
29
test()30 void test() {
31 S a, b;
32 std::memcmp(&a, &b, sizeof(S));
33 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'S' which does not have a unique object representation; consider comparing the members of the object manually
34 }
35 } // namespace inner_padding_64bit_only
36
37 namespace padding_in_base {
38 class Base {
39 char c;
40 int i;
41 };
42
43 class Derived : public Base {};
44
45 class Derived2 : public Derived {};
46
testDerived()47 void testDerived() {
48 Derived a, b;
49 std::memcmp(&a, &b, sizeof(Base));
50 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'Derived' which does not have a unique object representation; consider comparing the members of the object manually
51 std::memcmp(&a, &b, sizeof(Derived));
52 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'Derived' which does not have a unique object representation; consider comparing the members of the object manually
53 }
54
testDerived2()55 void testDerived2() {
56 Derived2 a, b;
57 std::memcmp(&a, &b, sizeof(Base));
58 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'Derived2' which does not have a unique object representation; consider comparing the members of the object manually
59 std::memcmp(&a, &b, sizeof(Derived2));
60 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'Derived2' which does not have a unique object representation; consider comparing the members of the object manually
61 }
62
63 } // namespace padding_in_base
64
65 namespace no_padding_in_base {
66 class Base {
67 int a, b;
68 };
69
70 class Derived : public Base {};
71
72 class Derived2 : public Derived {};
73
testDerived()74 void testDerived() {
75 Derived a, b;
76 std::memcmp(&a, &b, sizeof(Base));
77 std::memcmp(&a, &b, sizeof(Derived));
78 }
79
testDerived2()80 void testDerived2() {
81 Derived2 a, b;
82 std::memcmp(&a, &b, sizeof(char));
83 std::memcmp(&a, &b, sizeof(Base));
84 std::memcmp(&a, &b, sizeof(Derived2));
85 }
86 } // namespace no_padding_in_base
87
88 namespace non_standard_layout {
89 class C {
90 private:
91 int x;
92
93 public:
94 int y;
95 };
96
test()97 void test() {
98 C a, b;
99 std::memcmp(&a, &b, sizeof(C));
100 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of non-standard-layout type 'C'; consider using a comparison operator instead
101 }
102
103 } // namespace non_standard_layout
104
105 namespace static_ignored {
106 struct S {
107 static char c;
108 int i;
109 };
110
test()111 void test() {
112 S a, b;
113 std::memcmp(&a, &b, sizeof(S));
114 }
115 } // namespace static_ignored
116
117 namespace operator_void_ptr {
118 struct S {
119 operator void *() const;
120 };
121
test()122 void test() {
123 S s;
124 std::memcmp(s, s, sizeof(s));
125 }
126 } // namespace operator_void_ptr
127
128 namespace empty_struct {
129 struct S {};
130
test()131 void test() {
132 S a, b;
133 std::memcmp(&a, &b, sizeof(S));
134 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'S' which does not have a unique object representation; consider comparing the members of the object manually
135 }
136 } // namespace empty_struct
137
138 namespace empty_field {
139 struct Empty {};
140 struct S {
141 Empty e;
142 };
143
test()144 void test() {
145 S a, b;
146 std::memcmp(&a, &b, sizeof(S));
147 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'S' which does not have a unique object representation; consider comparing the members of the object manually
148 }
149 } // namespace empty_field
150
151 namespace no_unique_address_attribute {
152 struct Empty {};
153
154 namespace no_padding {
155 struct S {
156 char c;
157 [[no_unique_address]] Empty e;
158 };
159
test()160 void test() {
161 S a, b;
162 std::memcmp(&a, &b, sizeof(S));
163 }
164
165 } // namespace no_padding
166
167 namespace multiple_empties_same_type {
168 struct S {
169 char c;
170 [[no_unique_address]] Empty e1, e2;
171 };
172
test()173 void test() {
174 S a, b;
175 std::memcmp(&a, &b, sizeof(S));
176 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'S' which does not have a unique object representation; consider comparing the members of the object manually
177 }
178
179 } // namespace multiple_empties_same_type
180
181 namespace multiple_empties_different_types {
182 struct Empty2 {};
183
184 struct S {
185 char c;
186 [[no_unique_address]] Empty e1;
187 [[no_unique_address]] Empty2 e2;
188 };
189
test()190 void test() {
191 S a, b;
192 std::memcmp(&a, &b, sizeof(S));
193 }
194 } // namespace multiple_empties_different_types
195 } // namespace no_unique_address_attribute
196
197 namespace alignment {
198 struct S {
199 char x;
200 alignas(sizeof(int)) char y[sizeof(int)];
201 };
202
test()203 void test() {
204 S a, b;
205 std::memcmp(&a, &b, sizeof(S));
206 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'S' which does not have a unique object representation; consider comparing the members of the object manually
207 }
208 } // namespace alignment
209
210 namespace no_warning_in_template {
211 template <typename T>
compare(const T * l,const T * r)212 int compare(const T *l, const T *r) {
213 return std::memcmp(l, r, sizeof(T));
214 }
215
test()216 void test() {
217 int a, b;
218 compare(&a, &b);
219 }
220 } // namespace no_warning_in_template
221
222 namespace warning_in_template {
223 template <typename T>
compare(const T * l,const T * r)224 int compare(const T *l, const T *r) {
225 return std::memcmp(l, r, sizeof(T));
226 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: comparing object representation of type 'float' which does not have a unique object representation; consider comparing the values manually
227 }
228
test()229 void test() {
230 float a, b;
231 compare(&a, &b);
232 }
233 } // namespace warning_in_template
234