189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-suspicious-memory-comparison %t \
289a1d03eSRichard // RUN: -- -- -target x86_64-unknown-unknown
389a1d03eSRichard 
489a1d03eSRichard namespace std {
589a1d03eSRichard typedef __SIZE_TYPE__ size_t;
689a1d03eSRichard int memcmp(const void *lhs, const void *rhs, size_t count);
789a1d03eSRichard } // namespace std
889a1d03eSRichard 
989a1d03eSRichard namespace sei_cert_example_oop57_cpp {
1089a1d03eSRichard class C {
1189a1d03eSRichard   int i;
1289a1d03eSRichard 
1389a1d03eSRichard public:
1489a1d03eSRichard   virtual void f();
1589a1d03eSRichard };
1689a1d03eSRichard 
f(C & c1,C & c2)1789a1d03eSRichard void f(C &c1, C &c2) {
1889a1d03eSRichard   if (!std::memcmp(&c1, &c2, sizeof(C))) {
19*15f3cd6bSMatheus Izvekov     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: comparing object representation of non-standard-layout type 'C'; consider using a comparison operator instead
2089a1d03eSRichard   }
2189a1d03eSRichard }
2289a1d03eSRichard } // namespace sei_cert_example_oop57_cpp
2389a1d03eSRichard 
2489a1d03eSRichard namespace inner_padding_64bit_only {
2589a1d03eSRichard struct S {
2689a1d03eSRichard   int x;
2789a1d03eSRichard   int *y;
2889a1d03eSRichard };
2989a1d03eSRichard 
test()3089a1d03eSRichard void test() {
3189a1d03eSRichard   S a, b;
3289a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
33*15f3cd6bSMatheus Izvekov   // 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
3489a1d03eSRichard }
3589a1d03eSRichard } // namespace inner_padding_64bit_only
3689a1d03eSRichard 
3789a1d03eSRichard namespace padding_in_base {
3889a1d03eSRichard class Base {
3989a1d03eSRichard   char c;
4089a1d03eSRichard   int i;
4189a1d03eSRichard };
4289a1d03eSRichard 
4389a1d03eSRichard class Derived : public Base {};
4489a1d03eSRichard 
4589a1d03eSRichard class Derived2 : public Derived {};
4689a1d03eSRichard 
testDerived()4789a1d03eSRichard void testDerived() {
4889a1d03eSRichard   Derived a, b;
4989a1d03eSRichard   std::memcmp(&a, &b, sizeof(Base));
50*15f3cd6bSMatheus Izvekov   // 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
5189a1d03eSRichard   std::memcmp(&a, &b, sizeof(Derived));
52*15f3cd6bSMatheus Izvekov   // 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
5389a1d03eSRichard }
5489a1d03eSRichard 
testDerived2()5589a1d03eSRichard void testDerived2() {
5689a1d03eSRichard   Derived2 a, b;
5789a1d03eSRichard   std::memcmp(&a, &b, sizeof(Base));
58*15f3cd6bSMatheus Izvekov   // 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
5989a1d03eSRichard   std::memcmp(&a, &b, sizeof(Derived2));
60*15f3cd6bSMatheus Izvekov   // 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
6189a1d03eSRichard }
6289a1d03eSRichard 
6389a1d03eSRichard } // namespace padding_in_base
6489a1d03eSRichard 
6589a1d03eSRichard namespace no_padding_in_base {
6689a1d03eSRichard class Base {
6789a1d03eSRichard   int a, b;
6889a1d03eSRichard };
6989a1d03eSRichard 
7089a1d03eSRichard class Derived : public Base {};
7189a1d03eSRichard 
7289a1d03eSRichard class Derived2 : public Derived {};
7389a1d03eSRichard 
testDerived()7489a1d03eSRichard void testDerived() {
7589a1d03eSRichard   Derived a, b;
7689a1d03eSRichard   std::memcmp(&a, &b, sizeof(Base));
7789a1d03eSRichard   std::memcmp(&a, &b, sizeof(Derived));
7889a1d03eSRichard }
7989a1d03eSRichard 
testDerived2()8089a1d03eSRichard void testDerived2() {
8189a1d03eSRichard   Derived2 a, b;
8289a1d03eSRichard   std::memcmp(&a, &b, sizeof(char));
8389a1d03eSRichard   std::memcmp(&a, &b, sizeof(Base));
8489a1d03eSRichard   std::memcmp(&a, &b, sizeof(Derived2));
8589a1d03eSRichard }
8689a1d03eSRichard } // namespace no_padding_in_base
8789a1d03eSRichard 
8889a1d03eSRichard namespace non_standard_layout {
8989a1d03eSRichard class C {
9089a1d03eSRichard private:
9189a1d03eSRichard   int x;
9289a1d03eSRichard 
9389a1d03eSRichard public:
9489a1d03eSRichard   int y;
9589a1d03eSRichard };
9689a1d03eSRichard 
test()9789a1d03eSRichard void test() {
9889a1d03eSRichard   C a, b;
9989a1d03eSRichard   std::memcmp(&a, &b, sizeof(C));
100*15f3cd6bSMatheus Izvekov   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of non-standard-layout type 'C'; consider using a comparison operator instead
10189a1d03eSRichard }
10289a1d03eSRichard 
10389a1d03eSRichard } // namespace non_standard_layout
10489a1d03eSRichard 
10589a1d03eSRichard namespace static_ignored {
10689a1d03eSRichard struct S {
10789a1d03eSRichard   static char c;
10889a1d03eSRichard   int i;
10989a1d03eSRichard };
11089a1d03eSRichard 
test()11189a1d03eSRichard void test() {
11289a1d03eSRichard   S a, b;
11389a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
11489a1d03eSRichard }
11589a1d03eSRichard } // namespace static_ignored
11689a1d03eSRichard 
11789a1d03eSRichard namespace operator_void_ptr {
11889a1d03eSRichard struct S {
11989a1d03eSRichard   operator void *() const;
12089a1d03eSRichard };
12189a1d03eSRichard 
test()12289a1d03eSRichard void test() {
12389a1d03eSRichard   S s;
12489a1d03eSRichard   std::memcmp(s, s, sizeof(s));
12589a1d03eSRichard }
12689a1d03eSRichard } // namespace operator_void_ptr
12789a1d03eSRichard 
12889a1d03eSRichard namespace empty_struct {
12989a1d03eSRichard struct S {};
13089a1d03eSRichard 
test()13189a1d03eSRichard void test() {
13289a1d03eSRichard   S a, b;
13389a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
134*15f3cd6bSMatheus Izvekov   // 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
13589a1d03eSRichard }
13689a1d03eSRichard } // namespace empty_struct
13789a1d03eSRichard 
13889a1d03eSRichard namespace empty_field {
13989a1d03eSRichard struct Empty {};
14089a1d03eSRichard struct S {
14189a1d03eSRichard   Empty e;
14289a1d03eSRichard };
14389a1d03eSRichard 
test()14489a1d03eSRichard void test() {
14589a1d03eSRichard   S a, b;
14689a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
147*15f3cd6bSMatheus Izvekov   // 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
14889a1d03eSRichard }
14989a1d03eSRichard } // namespace empty_field
15089a1d03eSRichard 
15189a1d03eSRichard namespace no_unique_address_attribute {
15289a1d03eSRichard struct Empty {};
15389a1d03eSRichard 
15489a1d03eSRichard namespace no_padding {
15589a1d03eSRichard struct S {
15689a1d03eSRichard   char c;
15789a1d03eSRichard   [[no_unique_address]] Empty e;
15889a1d03eSRichard };
15989a1d03eSRichard 
test()16089a1d03eSRichard void test() {
16189a1d03eSRichard   S a, b;
16289a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
16389a1d03eSRichard }
16489a1d03eSRichard 
16589a1d03eSRichard } // namespace no_padding
16689a1d03eSRichard 
16789a1d03eSRichard namespace multiple_empties_same_type {
16889a1d03eSRichard struct S {
16989a1d03eSRichard   char c;
17089a1d03eSRichard   [[no_unique_address]] Empty e1, e2;
17189a1d03eSRichard };
17289a1d03eSRichard 
test()17389a1d03eSRichard void test() {
17489a1d03eSRichard   S a, b;
17589a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
176*15f3cd6bSMatheus Izvekov   // 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
17789a1d03eSRichard }
17889a1d03eSRichard 
17989a1d03eSRichard } // namespace multiple_empties_same_type
18089a1d03eSRichard 
18189a1d03eSRichard namespace multiple_empties_different_types {
18289a1d03eSRichard struct Empty2 {};
18389a1d03eSRichard 
18489a1d03eSRichard struct S {
18589a1d03eSRichard   char c;
18689a1d03eSRichard   [[no_unique_address]] Empty e1;
18789a1d03eSRichard   [[no_unique_address]] Empty2 e2;
18889a1d03eSRichard };
18989a1d03eSRichard 
test()19089a1d03eSRichard void test() {
19189a1d03eSRichard   S a, b;
19289a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
19389a1d03eSRichard }
19489a1d03eSRichard } // namespace multiple_empties_different_types
19589a1d03eSRichard } // namespace no_unique_address_attribute
19689a1d03eSRichard 
19789a1d03eSRichard namespace alignment {
19889a1d03eSRichard struct S {
19989a1d03eSRichard   char x;
20089a1d03eSRichard   alignas(sizeof(int)) char y[sizeof(int)];
20189a1d03eSRichard };
20289a1d03eSRichard 
test()20389a1d03eSRichard void test() {
20489a1d03eSRichard   S a, b;
20589a1d03eSRichard   std::memcmp(&a, &b, sizeof(S));
206*15f3cd6bSMatheus Izvekov   // 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
20789a1d03eSRichard }
20889a1d03eSRichard } // namespace alignment
20989a1d03eSRichard 
21089a1d03eSRichard namespace no_warning_in_template {
21189a1d03eSRichard template <typename T>
compare(const T * l,const T * r)21289a1d03eSRichard int compare(const T *l, const T *r) {
21389a1d03eSRichard   return std::memcmp(l, r, sizeof(T));
21489a1d03eSRichard }
21589a1d03eSRichard 
test()21689a1d03eSRichard void test() {
21789a1d03eSRichard   int a, b;
21889a1d03eSRichard   compare(&a, &b);
21989a1d03eSRichard }
22089a1d03eSRichard } // namespace no_warning_in_template
22189a1d03eSRichard 
22289a1d03eSRichard namespace warning_in_template {
22389a1d03eSRichard template <typename T>
compare(const T * l,const T * r)22489a1d03eSRichard int compare(const T *l, const T *r) {
22589a1d03eSRichard   return std::memcmp(l, r, sizeof(T));
22689a1d03eSRichard   // 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
22789a1d03eSRichard }
22889a1d03eSRichard 
test()22989a1d03eSRichard void test() {
23089a1d03eSRichard   float a, b;
23189a1d03eSRichard   compare(&a, &b);
23289a1d03eSRichard }
23389a1d03eSRichard } // namespace warning_in_template
234