forked from OSchip/llvm-project
234 lines
6.0 KiB
C++
234 lines
6.0 KiB
C++
|
// 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
|