blob: f4406b222eeb02eed59b9a7d428b9d1e360ef83c [file] [log] [blame]
// RUN: %check_clang_tidy %s bugprone-suspicious-memory-comparison %t \
// RUN: -- -- -target x86_64-unknown-unknown
namespace std {
typedef __SIZE_TYPE__ size_t;
int memcmp(const void *lhs, const void *rhs, size_t count);
} // namespace std
namespace sei_cert_example_oop57_cpp {
class C {
int i;
public:
virtual void f();
};
void f(C &c1, C &c2) {
if (!std::memcmp(&c1, &c2, sizeof(C))) {
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: comparing object representation of non-standard-layout type 'sei_cert_example_oop57_cpp::C'; consider using a comparison operator instead
}
}
} // namespace sei_cert_example_oop57_cpp
namespace inner_padding_64bit_only {
struct S {
int x;
int *y;
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'inner_padding_64bit_only::S' which does not have a unique object representation; consider comparing the members of the object manually
}
} // namespace inner_padding_64bit_only
namespace padding_in_base {
class Base {
char c;
int i;
};
class Derived : public Base {};
class Derived2 : public Derived {};
void testDerived() {
Derived a, b;
std::memcmp(&a, &b, sizeof(Base));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'padding_in_base::Derived' which does not have a unique object representation; consider comparing the members of the object manually
std::memcmp(&a, &b, sizeof(Derived));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'padding_in_base::Derived' which does not have a unique object representation; consider comparing the members of the object manually
}
void testDerived2() {
Derived2 a, b;
std::memcmp(&a, &b, sizeof(Base));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'padding_in_base::Derived2' which does not have a unique object representation; consider comparing the members of the object manually
std::memcmp(&a, &b, sizeof(Derived2));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'padding_in_base::Derived2' which does not have a unique object representation; consider comparing the members of the object manually
}
} // namespace padding_in_base
namespace no_padding_in_base {
class Base {
int a, b;
};
class Derived : public Base {};
class Derived2 : public Derived {};
void testDerived() {
Derived a, b;
std::memcmp(&a, &b, sizeof(Base));
std::memcmp(&a, &b, sizeof(Derived));
}
void testDerived2() {
Derived2 a, b;
std::memcmp(&a, &b, sizeof(char));
std::memcmp(&a, &b, sizeof(Base));
std::memcmp(&a, &b, sizeof(Derived2));
}
} // namespace no_padding_in_base
namespace non_standard_layout {
class C {
private:
int x;
public:
int y;
};
void test() {
C a, b;
std::memcmp(&a, &b, sizeof(C));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of non-standard-layout type 'non_standard_layout::C'; consider using a comparison operator instead
}
} // namespace non_standard_layout
namespace static_ignored {
struct S {
static char c;
int i;
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
}
} // namespace static_ignored
namespace operator_void_ptr {
struct S {
operator void *() const;
};
void test() {
S s;
std::memcmp(s, s, sizeof(s));
}
} // namespace operator_void_ptr
namespace empty_struct {
struct S {};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'empty_struct::S' which does not have a unique object representation; consider comparing the members of the object manually
}
} // namespace empty_struct
namespace empty_field {
struct Empty {};
struct S {
Empty e;
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'empty_field::S' which does not have a unique object representation; consider comparing the members of the object manually
}
} // namespace empty_field
namespace no_unique_address_attribute {
struct Empty {};
namespace no_padding {
struct S {
char c;
[[no_unique_address]] Empty e;
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
}
} // namespace no_padding
namespace multiple_empties_same_type {
struct S {
char c;
[[no_unique_address]] Empty e1, e2;
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'no_unique_address_attribute::multiple_empties_same_type::S' which does not have a unique object representation; consider comparing the members of the object manually
}
} // namespace multiple_empties_same_type
namespace multiple_empties_different_types {
struct Empty2 {};
struct S {
char c;
[[no_unique_address]] Empty e1;
[[no_unique_address]] Empty2 e2;
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
}
} // namespace multiple_empties_different_types
} // namespace no_unique_address_attribute
namespace alignment {
struct S {
char x;
alignas(sizeof(int)) char y[sizeof(int)];
};
void test() {
S a, b;
std::memcmp(&a, &b, sizeof(S));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'alignment::S' which does not have a unique object representation; consider comparing the members of the object manually
}
} // namespace alignment
namespace no_warning_in_template {
template <typename T>
int compare(const T *l, const T *r) {
return std::memcmp(l, r, sizeof(T));
}
void test() {
int a, b;
compare(&a, &b);
}
} // namespace no_warning_in_template
namespace warning_in_template {
template <typename T>
int compare(const T *l, const T *r) {
return std::memcmp(l, r, sizeof(T));
// 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
}
void test() {
float a, b;
compare(&a, &b);
}
} // namespace warning_in_template