| 1 | // RUN: %check_clang_tidy %s bugprone-signed-char-misuse %t |
| 2 | |
| 3 | /////////////////////////////////////////////////////////////////// |
| 4 | /// Test cases correctly caught by the check. |
| 5 | |
| 6 | typedef __SIZE_TYPE__ size_t; |
| 7 | |
| 8 | namespace std { |
| 9 | template <typename T, size_t N> |
| 10 | struct array { |
| 11 | T &operator[](size_t n); |
| 12 | T &at(size_t n); |
| 13 | }; |
| 14 | } // namespace std |
| 15 | |
| 16 | int SimpleVarDeclaration() { |
| 17 | signed char CCharacter = -5; |
| 18 | int NCharacter = CCharacter; |
| 19 | // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 20 | |
| 21 | return NCharacter; |
| 22 | } |
| 23 | |
| 24 | int SimpleAssignment() { |
| 25 | signed char CCharacter = -5; |
| 26 | int NCharacter; |
| 27 | NCharacter = CCharacter; |
| 28 | // CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 29 | |
| 30 | return NCharacter; |
| 31 | } |
| 32 | |
| 33 | int CStyleCast() { |
| 34 | signed char CCharacter = -5; |
| 35 | int NCharacter; |
| 36 | NCharacter = (int)CCharacter; |
| 37 | // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 38 | |
| 39 | return NCharacter; |
| 40 | } |
| 41 | |
| 42 | int StaticCast() { |
| 43 | signed char CCharacter = -5; |
| 44 | int NCharacter; |
| 45 | NCharacter = static_cast<int>(CCharacter); |
| 46 | // CHECK-MESSAGES: [[@LINE-1]]:33: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 47 | |
| 48 | return NCharacter; |
| 49 | } |
| 50 | |
| 51 | int FunctionalCast() { |
| 52 | signed char CCharacter = -5; |
| 53 | int NCharacter; |
| 54 | NCharacter = int(CCharacter); |
| 55 | // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 56 | |
| 57 | return NCharacter; |
| 58 | } |
| 59 | |
| 60 | int NegativeConstValue() { |
| 61 | const signed char CCharacter = -5; |
| 62 | int NCharacter = CCharacter; |
| 63 | // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 64 | |
| 65 | return NCharacter; |
| 66 | } |
| 67 | |
| 68 | int CharPointer(signed char *CCharacter) { |
| 69 | int NCharacter = *CCharacter; |
| 70 | // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 71 | |
| 72 | return NCharacter; |
| 73 | } |
| 74 | |
| 75 | int SignedUnsignedCharEquality(signed char SCharacter) { |
| 76 | unsigned char USCharacter = 'a'; |
| 77 | if (SCharacter == USCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse] |
| 78 | return 1; |
| 79 | return 0; |
| 80 | } |
| 81 | |
| 82 | int SignedUnsignedCharIneqiality(signed char SCharacter) { |
| 83 | unsigned char USCharacter = 'a'; |
| 84 | if (SCharacter != USCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse] |
| 85 | return 1; |
| 86 | return 0; |
| 87 | } |
| 88 | |
| 89 | int CompareWithNonAsciiConstant(unsigned char USCharacter) { |
| 90 | const signed char SCharacter = -5; |
| 91 | if (USCharacter == SCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse] |
| 92 | return 1; |
| 93 | return 0; |
| 94 | } |
| 95 | |
| 96 | int CompareWithUnsignedNonAsciiConstant(signed char SCharacter) { |
| 97 | const unsigned char USCharacter = 128; |
| 98 | if (USCharacter == SCharacter) // CHECK-MESSAGES: [[@LINE]]:7: warning: comparison between 'signed char' and 'unsigned char' [bugprone-signed-char-misuse] |
| 99 | return 1; |
| 100 | return 0; |
| 101 | } |
| 102 | |
| 103 | int SignedCharCArraySubscript(signed char SCharacter) { |
| 104 | int Array[3] = {1, 2, 3}; |
| 105 | |
| 106 | return Array[static_cast<unsigned int>(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 107 | } |
| 108 | |
| 109 | int SignedCharSTDArraySubscript(std::array<int, 3> Array, signed char SCharacter) { |
| 110 | return Array[static_cast<unsigned int>(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse] |
| 111 | } |
| 112 | |
| 113 | /////////////////////////////////////////////////////////////////// |
| 114 | /// Test cases correctly ignored by the check. |
| 115 | |
| 116 | int UnsignedCharCast() { |
| 117 | unsigned char CCharacter = 'a'; |
| 118 | int NCharacter = CCharacter; |
| 119 | |
| 120 | return NCharacter; |
| 121 | } |
| 122 | |
| 123 | int PositiveConstValue() { |
| 124 | const signed char CCharacter = 5; |
| 125 | int NCharacter = CCharacter; |
| 126 | |
| 127 | return NCharacter; |
| 128 | } |
| 129 | |
| 130 | // singed char -> integer cast is not the direct child of declaration expression. |
| 131 | int DescendantCast() { |
| 132 | signed char CCharacter = 'a'; |
| 133 | int NCharacter = 10 + CCharacter; |
| 134 | |
| 135 | return NCharacter; |
| 136 | } |
| 137 | |
| 138 | // singed char -> integer cast is not the direct child of assignment expression. |
| 139 | int DescendantCastAssignment() { |
| 140 | signed char CCharacter = 'a'; |
| 141 | int NCharacter; |
| 142 | NCharacter = 10 + CCharacter; |
| 143 | |
| 144 | return NCharacter; |
| 145 | } |
| 146 | |
| 147 | // bool is an integer type in clang; make sure to ignore it. |
| 148 | bool BoolVarDeclaration() { |
| 149 | signed char CCharacter = 'a'; |
| 150 | bool BCharacter = CCharacter == 'b'; |
| 151 | |
| 152 | return BCharacter; |
| 153 | } |
| 154 | |
| 155 | // bool is an integer type in clang; make sure to ignore it. |
| 156 | bool BoolAssignment() { |
| 157 | signed char CCharacter = 'a'; |
| 158 | bool BCharacter; |
| 159 | BCharacter = CCharacter == 'b'; |
| 160 | |
| 161 | return BCharacter; |
| 162 | } |
| 163 | |
| 164 | // char is an integer type in clang; make sure to ignore it. |
| 165 | unsigned char CharToCharCast() { |
| 166 | signed char SCCharacter = 'a'; |
| 167 | unsigned char USCharacter; |
| 168 | USCharacter = SCCharacter; |
| 169 | |
| 170 | return USCharacter; |
| 171 | } |
| 172 | |
| 173 | int FixComparisonWithSignedCharCast(signed char SCharacter) { |
| 174 | unsigned char USCharacter = 'a'; |
| 175 | if (SCharacter == static_cast<signed char>(USCharacter)) |
| 176 | return 1; |
| 177 | return 0; |
| 178 | } |
| 179 | |
| 180 | int FixComparisonWithUnSignedCharCast(signed char SCharacter) { |
| 181 | unsigned char USCharacter = 'a'; |
| 182 | if (static_cast<unsigned char>(SCharacter) == USCharacter) |
| 183 | return 1; |
| 184 | return 0; |
| 185 | } |
| 186 | |
| 187 | // Make sure we don't catch other type of char comparison. |
| 188 | int SameCharTypeComparison(signed char SCharacter) { |
| 189 | signed char SCharacter2 = 'a'; |
| 190 | if (SCharacter == SCharacter2) |
| 191 | return 1; |
| 192 | return 0; |
| 193 | } |
| 194 | |
| 195 | // Make sure we don't catch other type of char comparison. |
| 196 | int SameCharTypeComparison2(unsigned char USCharacter) { |
| 197 | unsigned char USCharacter2 = 'a'; |
| 198 | if (USCharacter == USCharacter2) |
| 199 | return 1; |
| 200 | return 0; |
| 201 | } |
| 202 | |
| 203 | // Make sure we don't catch integer - char comparison. |
| 204 | int CharIntComparison(signed char SCharacter) { |
| 205 | int ICharacter = 10; |
| 206 | if (SCharacter == ICharacter) |
| 207 | return 1; |
| 208 | return 0; |
| 209 | } |
| 210 | |
| 211 | int CompareWithAsciiLiteral(unsigned char USCharacter) { |
| 212 | if (USCharacter == 'x') // no warning |
| 213 | return 1; |
| 214 | return 0; |
| 215 | } |
| 216 | |
| 217 | int CompareWithAsciiConstant(unsigned char USCharacter) { |
| 218 | const signed char SCharacter = 'a'; |
| 219 | if (USCharacter == SCharacter) |
| 220 | return 1; |
| 221 | return 0; |
| 222 | } |
| 223 | |
| 224 | int CompareWithUnsignedAsciiConstant(signed char SCharacter) { |
| 225 | const unsigned char USCharacter = 'a'; |
| 226 | if (USCharacter == SCharacter) |
| 227 | return 1; |
| 228 | return 0; |
| 229 | } |
| 230 | |
| 231 | int UnsignedCharCArraySubscript(unsigned char USCharacter) { |
| 232 | int Array[3] = {1, 2, 3}; |
| 233 | |
| 234 | return Array[static_cast<unsigned int>(USCharacter)]; |
| 235 | } |
| 236 | |
| 237 | int CastedCArraySubscript(signed char SCharacter) { |
| 238 | int Array[3] = {1, 2, 3}; |
| 239 | |
| 240 | return Array[static_cast<unsigned char>(SCharacter)]; |
| 241 | } |
| 242 | |
| 243 | int UnsignedCharSTDArraySubscript(std::array<int, 3> Array, unsigned char USCharacter) { |
| 244 | return Array[static_cast<unsigned int>(USCharacter)]; |
| 245 | } |
| 246 | |
| 247 | int CastedSTDArraySubscript(std::array<int, 3> Array, signed char SCharacter) { |
| 248 | return Array[static_cast<unsigned char>(SCharacter)]; |
| 249 | } |
| 250 | |