Skip to content

Commit b45527d

Browse files
authored
[clang-tidy] Add UseUpperCaseLiteralSuffix option to readability-implicit-bool-conversion (#104882)
When readability-implicit-bool-conversion-check and readability-uppercase-literal-suffix-check is enabled this will cause you to apply a fix twice from (!i) -> (i == 0u) to (i == 0U) twice instead will skip the middle one Adding this option allows this check to be in sync with readability-uppercase-literal-suffix, avoiding duplicate warnings. Fixes #40544
1 parent 1cea5c2 commit b45527d

File tree

6 files changed

+68
-6
lines changed

6 files changed

+68
-6
lines changed

clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ bool isUnaryLogicalNotOperator(const Stmt *Statement) {
6666

6767
void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
6868
const ImplicitCastExpr *Cast, const Stmt *Parent,
69-
ASTContext &Context) {
69+
ASTContext &Context,
70+
bool UseUpperCaseLiteralSuffix) {
7071
// In case of expressions like (! integer), we should remove the redundant not
7172
// operator and use inverted comparison (integer == 0).
7273
bool InvertComparison =
@@ -112,9 +113,14 @@ void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
112113
EndLocInsertion += " != ";
113114
}
114115

115-
EndLocInsertion += getZeroLiteralToCompareWithForType(
116+
const StringRef ZeroLiteral = getZeroLiteralToCompareWithForType(
116117
Cast->getCastKind(), SubExpr->getType(), Context);
117118

119+
if (UseUpperCaseLiteralSuffix)
120+
EndLocInsertion += ZeroLiteral.upper();
121+
else
122+
EndLocInsertion += ZeroLiteral;
123+
118124
if (NeedOuterParens) {
119125
EndLocInsertion += ")";
120126
}
@@ -248,12 +254,15 @@ ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
248254
StringRef Name, ClangTidyContext *Context)
249255
: ClangTidyCheck(Name, Context),
250256
AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
251-
AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}
257+
AllowPointerConditions(Options.get("AllowPointerConditions", false)),
258+
UseUpperCaseLiteralSuffix(
259+
Options.get("UseUpperCaseLiteralSuffix", false)) {}
252260

253261
void ImplicitBoolConversionCheck::storeOptions(
254262
ClangTidyOptions::OptionMap &Opts) {
255263
Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
256264
Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
265+
Options.store(Opts, "UseUpperCaseLiteralSuffix", UseUpperCaseLiteralSuffix);
257266
}
258267

259268
void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
@@ -378,7 +387,8 @@ void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
378387
if (!EquivalentLiteral.empty()) {
379388
Diag << tooling::fixit::createReplacement(*Cast, EquivalentLiteral);
380389
} else {
381-
fixGenericExprCastToBool(Diag, Cast, Parent, Context);
390+
fixGenericExprCastToBool(Diag, Cast, Parent, Context,
391+
UseUpperCaseLiteralSuffix);
382392
}
383393
}
384394

@@ -392,8 +402,16 @@ void ImplicitBoolConversionCheck::handleCastFromBool(
392402

393403
if (const auto *BoolLiteral =
394404
dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr()->IgnoreParens())) {
395-
Diag << tooling::fixit::createReplacement(
396-
*Cast, getEquivalentForBoolLiteral(BoolLiteral, DestType, Context));
405+
406+
const auto EquivalentForBoolLiteral =
407+
getEquivalentForBoolLiteral(BoolLiteral, DestType, Context);
408+
if (UseUpperCaseLiteralSuffix)
409+
Diag << tooling::fixit::createReplacement(
410+
*Cast, EquivalentForBoolLiteral.upper());
411+
else
412+
Diag << tooling::fixit::createReplacement(*Cast,
413+
EquivalentForBoolLiteral);
414+
397415
} else {
398416
fixGenericExprCastFromBool(Diag, Cast, Context, DestType.getAsString());
399417
}

clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class ImplicitBoolConversionCheck : public ClangTidyCheck {
3636

3737
const bool AllowIntegerConditions;
3838
const bool AllowPointerConditions;
39+
const bool UseUpperCaseLiteralSuffix;
3940
};
4041

4142
} // namespace clang::tidy::readability

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ Changes in existing checks
112112
<clang-tidy/checks/modernize/use-std-print>` check to support replacing
113113
member function calls too.
114114

115+
- Improved :doc:`readablility-implicit-bool-conversion
116+
<clang-tidy/checks/readability/implicit-bool-conversion>` check
117+
by adding the option `UseUpperCaseLiteralSuffix` to select the
118+
case of the literal suffix in fixes.
119+
115120
- Improved :doc:`readability-redundant-smartptr-get
116121
<clang-tidy/checks/readability/redundant-smartptr-get>` check to
117122
remove `->`, when redundant `get()` is removed.

clang-tools-extra/docs/clang-tidy/checks/readability/implicit-bool-conversion.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,17 @@ Options
133133

134134
When `true`, the check will allow conditional pointer conversions. Default
135135
is `false`.
136+
137+
.. option:: UseUpperCaseLiteralSuffix
138+
139+
When `true`, the replacements will use an uppercase literal suffix in the
140+
provided fixes. Default is `false`.
141+
142+
Example
143+
144+
.. code-block:: c++
145+
146+
uint32_t foo;
147+
if (foo) {}
148+
// ^ propose replacement default: if (foo != 0u) {}
149+
// ^ propose replacement with option `UseUpperCaseLiteralSuffix`: if (foo != 0U) {}

clang-tools-extra/test/clang-tidy/checkers/readability/implicit-bool-conversion.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c23
2+
// RUN: %check_clang_tidy -check-suffix=UPPER-CASE %s readability-implicit-bool-conversion %t -- \
3+
// RUN: -config='{CheckOptions: { \
4+
// RUN: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix: true \
5+
// RUN: }}' -- -std=c23
26

37
#undef NULL
48
#define NULL 0L
@@ -95,6 +99,7 @@ void implicitConversionFromBoolLiterals() {
9599
functionTakingUnsignedLong(false);
96100
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'bool' -> 'unsigned long'
97101
// CHECK-FIXES: functionTakingUnsignedLong(0u);
102+
// CHECK-FIXES-UPPER-CASE: functionTakingUnsignedLong(0U);
98103

99104
functionTakingSignedChar(true);
100105
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'bool' -> 'signed char'
@@ -103,6 +108,7 @@ void implicitConversionFromBoolLiterals() {
103108
functionTakingFloat(false);
104109
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion 'bool' -> 'float'
105110
// CHECK-FIXES: functionTakingFloat(0.0f);
111+
// CHECK-FIXES-UPPER-CASE: functionTakingFloat(0.0F);
106112

107113
functionTakingDouble(true);
108114
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'bool' -> 'double'
@@ -160,11 +166,13 @@ void implicitConversionToBoolSimpleCases() {
160166
functionTakingBool(unsignedLong);
161167
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'unsigned long' -> 'bool'
162168
// CHECK-FIXES: functionTakingBool(unsignedLong != 0u);
169+
// CHECK-FIXES-UPPER-CASE: functionTakingBool(unsignedLong != 0U);
163170

164171
float floating = 0.0f;
165172
functionTakingBool(floating);
166173
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool'
167174
// CHECK-FIXES: functionTakingBool(floating != 0.0f);
175+
// CHECK-FIXES-UPPER-CASE: functionTakingBool(floating != 0.0F);
168176

169177
double doubleFloating = 1.0f;
170178
functionTakingBool(doubleFloating);
@@ -194,6 +202,7 @@ void implicitConversionToBoolInSingleExpressions() {
194202
boolComingFromFloat = floating;
195203
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'float' -> 'bool'
196204
// CHECK-FIXES: boolComingFromFloat = (floating != 0.0f);
205+
// CHECK-FIXES-UPPER-CASE: boolComingFromFloat = (floating != 0.0F);
197206

198207
signed char character = 'a';
199208
bool boolComingFromChar;
@@ -288,6 +297,7 @@ void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
288297
functionTakingBool(-0.0f);
289298
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool'
290299
// CHECK-FIXES: functionTakingBool((-0.0f) != 0.0f);
300+
// CHECK-FIXES-UPPER-CASE: functionTakingBool((-0.0f) != 0.0F);
291301

292302
functionTakingBool(-0.0);
293303
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'double' -> 'bool'

clang-tools-extra/test/clang-tidy/checkers/readability/implicit-bool-conversion.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t
2+
// RUN: %check_clang_tidy -check-suffix=UPPER-CASE %s readability-implicit-bool-conversion %t -- \
3+
// RUN: -config='{CheckOptions: { \
4+
// RUN: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix: true \
5+
// RUN: }}'
26

37
// We need NULL macro, but some buildbots don't like including <cstddef> header
48
// This is a portable way of getting it to work
@@ -99,6 +103,7 @@ void implicitConversionFromBoolLiterals() {
99103
functionTaking<unsigned long>(false);
100104
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'bool' -> 'unsigned long'
101105
// CHECK-FIXES: functionTaking<unsigned long>(0u);
106+
// CHECK-FIXES-UPPER-CASE: functionTaking<unsigned long>(0U);
102107

103108
functionTaking<signed char>(true);
104109
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit conversion 'bool' -> 'signed char'
@@ -107,6 +112,7 @@ void implicitConversionFromBoolLiterals() {
107112
functionTaking<float>(false);
108113
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'bool' -> 'float'
109114
// CHECK-FIXES: functionTaking<float>(0.0f);
115+
// CHECK-FIXES-UPPER-CASE: functionTaking<float>(0.0F);
110116

111117
functionTaking<double>(true);
112118
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion 'bool' -> 'double'
@@ -178,11 +184,13 @@ void implicitConversionToBoolSimpleCases() {
178184
functionTaking<bool>(unsignedLong);
179185
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> 'bool'
180186
// CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
187+
// CHECK-FIXES-UPPER-CASE: functionTaking<bool>(unsignedLong != 0U);
181188

182189
float floating = 0.0f;
183190
functionTaking<bool>(floating);
184191
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> 'bool'
185192
// CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
193+
// CHECK-FIXES-UPPER-CASE: functionTaking<bool>(floating != 0.0F);
186194

187195
double doubleFloating = 1.0f;
188196
functionTaking<bool>(doubleFloating);
@@ -215,6 +223,7 @@ void implicitConversionToBoolInSingleExpressions() {
215223
bool boolComingFromFloat = floating;
216224
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'float' -> 'bool'
217225
// CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
226+
// CHECK-FIXES-UPPER-CASE: bool boolComingFromFloat = floating != 0.0F;
218227

219228
signed char character = 'a';
220229
bool boolComingFromChar = character;
@@ -240,6 +249,7 @@ void implicitConversionToBoolInComplexExpressions() {
240249
bool boolComingFromFloating = floating - 0.3f || boolean;
241250
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'float' -> 'bool'
242251
// CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
252+
// CHECK-FIXES-UPPER-CASE: bool boolComingFromFloating = ((floating - 0.3f) != 0.0F) || boolean;
243253

244254
double doubleFloating = 0.3;
245255
bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
@@ -257,6 +267,7 @@ void implicitConversionInNegationExpressions() {
257267
bool boolComingFromNegatedFloat = ! floating;
258268
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'float' -> 'bool'
259269
// CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
270+
// CHECK-FIXES-UPPER-CASE: bool boolComingFromNegatedFloat = floating == 0.0F;
260271

261272
signed char character = 'a';
262273
bool boolComingFromNegatedChar = (! character);
@@ -284,6 +295,7 @@ void implicitConversionToBoolInControlStatements() {
284295
while (floating) {}
285296
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> 'bool'
286297
// CHECK-FIXES: while (floating != 0.0f) {}
298+
// CHECK-FIXES-UPPER-CASE: while (floating != 0.0F) {}
287299

288300
double doubleFloating = 0.4;
289301
do {} while (doubleFloating);
@@ -296,6 +308,7 @@ bool implicitConversionToBoolInReturnValue() {
296308
return floating;
297309
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> 'bool'
298310
// CHECK-FIXES: return floating != 0.0f;
311+
// CHECK-FIXES-UPPER-CASE: return floating != 0.0F;
299312
}
300313

301314
void implicitConversionToBoolFromLiterals() {
@@ -355,6 +368,7 @@ void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
355368
functionTaking<bool>(-0.0f);
356369
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> 'bool'
357370
// CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
371+
// CHECK-FIXES-UPPER-CASE: functionTaking<bool>((-0.0f) != 0.0F);
358372

359373
functionTaking<bool>(-0.0);
360374
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> 'bool'

0 commit comments

Comments
 (0)