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 
SimpleVarDeclaration()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 
SimpleAssignment()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 
CStyleCast()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 
StaticCast()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 
FunctionalCast()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 
NegativeConstValue()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 
CharPointer(signed char * CCharacter)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 
SignedUnsignedCharEquality(signed char SCharacter)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 
SignedUnsignedCharIneqiality(signed char SCharacter)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 
CompareWithNonAsciiConstant(unsigned char USCharacter)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 
CompareWithUnsignedNonAsciiConstant(signed char SCharacter)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 
SignedCharCArraySubscript(signed char SCharacter)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 
SignedCharSTDArraySubscript(std::array<int,3> Array,signed char SCharacter)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 
UnsignedCharCast()116 int UnsignedCharCast() {
117   unsigned char CCharacter = 'a';
118   int NCharacter = CCharacter;
119 
120   return NCharacter;
121 }
122 
PositiveConstValue()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.
DescendantCast()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.
DescendantCastAssignment()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.
BoolVarDeclaration()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.
BoolAssignment()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.
CharToCharCast()165 unsigned char CharToCharCast() {
166   signed char SCCharacter = 'a';
167   unsigned char USCharacter;
168   USCharacter = SCCharacter;
169 
170   return USCharacter;
171 }
172 
FixComparisonWithSignedCharCast(signed char SCharacter)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 
FixComparisonWithUnSignedCharCast(signed char SCharacter)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.
SameCharTypeComparison(signed char SCharacter)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.
SameCharTypeComparison2(unsigned char USCharacter)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.
CharIntComparison(signed char SCharacter)204 int CharIntComparison(signed char SCharacter) {
205   int ICharacter = 10;
206   if (SCharacter == ICharacter)
207     return 1;
208   return 0;
209 }
210 
CompareWithAsciiLiteral(unsigned char USCharacter)211 int CompareWithAsciiLiteral(unsigned char USCharacter) {
212   if (USCharacter == 'x') // no warning
213     return 1;
214   return 0;
215 }
216 
CompareWithAsciiConstant(unsigned char USCharacter)217 int CompareWithAsciiConstant(unsigned char USCharacter) {
218   const signed char SCharacter = 'a';
219   if (USCharacter == SCharacter)
220     return 1;
221   return 0;
222 }
223 
CompareWithUnsignedAsciiConstant(signed char SCharacter)224 int CompareWithUnsignedAsciiConstant(signed char SCharacter) {
225   const unsigned char USCharacter = 'a';
226   if (USCharacter == SCharacter)
227     return 1;
228   return 0;
229 }
230 
UnsignedCharCArraySubscript(unsigned char USCharacter)231 int UnsignedCharCArraySubscript(unsigned char USCharacter) {
232   int Array[3] = {1, 2, 3};
233 
234   return Array[static_cast<unsigned int>(USCharacter)];
235 }
236 
CastedCArraySubscript(signed char SCharacter)237 int CastedCArraySubscript(signed char SCharacter) {
238   int Array[3] = {1, 2, 3};
239 
240   return Array[static_cast<unsigned char>(SCharacter)];
241 }
242 
UnsignedCharSTDArraySubscript(std::array<int,3> Array,unsigned char USCharacter)243 int UnsignedCharSTDArraySubscript(std::array<int, 3> Array, unsigned char USCharacter) {
244   return Array[static_cast<unsigned int>(USCharacter)];
245 }
246 
CastedSTDArraySubscript(std::array<int,3> Array,signed char SCharacter)247 int CastedSTDArraySubscript(std::array<int, 3> Array, signed char SCharacter) {
248   return Array[static_cast<unsigned char>(SCharacter)];
249 }
250