1 // RUN: %check_clang_tidy %s cert-oop57-cpp %t -- \ 2 // RUN: -config='{CheckOptions: \ 3 // RUN: [{key: cert-oop57-cpp.MemSetNames, value: mymemset}, \ 4 // RUN: {key: cert-oop57-cpp.MemCpyNames, value: mymemcpy}, \ 5 // RUN: {key: cert-oop57-cpp.MemCmpNames, value: mymemcmp}]}' \ 6 // RUN: -- 7 8 void mymemset(void *, unsigned char, decltype(sizeof(int))); 9 void mymemcpy(void *, const void *, decltype(sizeof(int))); 10 int mymemcmp(const void *, const void *, decltype(sizeof(int))); 11 12 namespace std { 13 void memset(void *, unsigned char, decltype(sizeof(int))); 14 void memcpy(void *, const void *, decltype(sizeof(int))); 15 void memmove(void *, const void *, decltype(sizeof(int))); 16 void strcpy(void *, const void *, decltype(sizeof(int))); 17 int memcmp(const void *, const void *, decltype(sizeof(int))); 18 int strcmp(const void *, const void *, decltype(sizeof(int))); 19 } // namespace std 20 21 struct Trivial { 22 int I; 23 int J; 24 }; 25 26 struct NonTrivial { 27 int I; 28 int J; 29 30 NonTrivial() : I(0), J(0) {} 31 NonTrivial &operator=(const NonTrivial &Other) { 32 I = Other.I; 33 J = Other.J; 34 return *this; 35 } 36 37 bool operator==(const Trivial &Other) const { 38 return I == Other.I && J == Other.J; 39 } 40 bool operator!=(const Trivial &Other) const { 41 return !(*this == Other); 42 } 43 }; 44 45 void foo(const Trivial &Other) { 46 Trivial Data; 47 std::memset(&Data, 0, sizeof(Data)); 48 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined 49 std::memset(&Data, 0, sizeof(Trivial)); 50 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined 51 std::memcpy(&Data, &Other, sizeof(Data)); 52 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: calling 'memcpy' on a non-trivially copyable class is undefined 53 std::memmove(&Data, &Other, sizeof(Data)); 54 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: calling 'memmove' on a non-trivially copyable class is undefined 55 std::strcpy(&Data, &Other, sizeof(Data)); 56 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: calling 'strcpy' on a non-trivially copyable class is undefined 57 std::memcmp(&Data, &Other, sizeof(Data)); 58 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: consider using comparison operators instead of calling 'memcmp' 59 std::strcmp(&Data, &Other, sizeof(Data)); 60 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: consider using comparison operators instead of calling 'strcmp' 61 } 62 63 void bar(const NonTrivial &Other) { 64 NonTrivial Data; 65 std::memset(&Data, 0, sizeof(Data)); 66 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined 67 // Check it detects sizeof(Type) as well as sizeof(Instantiation) 68 std::memset(&Data, 0, sizeof(NonTrivial)); 69 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined 70 std::memcpy(&Data, &Other, sizeof(Data)); 71 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memcpy' on a non-trivially copyable class is undefined 72 std::memmove(&Data, &Other, sizeof(Data)); 73 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memmove' on a non-trivially copyable class is undefined 74 std::strcpy(&Data, &Other, sizeof(Data)); 75 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'strcpy' on a non-trivially copyable class is undefined 76 std::memcmp(&Data, &Other, sizeof(Data)); 77 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: consider using comparison operators instead of calling 'memcmp' 78 std::strcmp(&Data, &Other, sizeof(Data)); 79 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: consider using comparison operators instead of calling 'strcmp' 80 } 81 82 void baz(const NonTrivial &Other) { 83 NonTrivial Data; 84 mymemset(&Data, 0, sizeof(Data)); 85 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'mymemset' on a non-trivially default constructible class is undefined 86 mymemcpy(&Data, &Other, sizeof(Data)); 87 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'mymemcpy' on a non-trivially copyable class is undefined 88 mymemcmp(&Data, &Other, sizeof(Data)); 89 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: consider using comparison operators instead of calling 'mymemcmp' 90 } 91 92 void nonNullSetValue() { 93 NonTrivial Data; 94 // Check non-null-valued second argument. 95 std::memset(&Data, 1, sizeof(Data)); 96 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined 97 } 98 99 void nonLiteralSetValue(char C) { 100 NonTrivial Data; 101 // Check non-literal second argument. 102 std::memset(&Data, C, sizeof(Data)); 103 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling 'memset' on a non-trivially default constructible class is undefined 104 } 105