@@ -259,13 +259,17 @@ ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
259
259
AllowIntegerConditions (Options.get(" AllowIntegerConditions" , false )),
260
260
AllowPointerConditions(Options.get(" AllowPointerConditions" , false )),
261
261
UseUpperCaseLiteralSuffix(
262
- Options.get(" UseUpperCaseLiteralSuffix" , false )) {}
262
+ Options.get(" UseUpperCaseLiteralSuffix" , false )),
263
+ CheckConversionsToBool(Options.get(" CheckConversionsToBool" , true )),
264
+ CheckConversionsFromBool(Options.get(" CheckConversionsFromBool" , true )) {}
263
265
264
266
void ImplicitBoolConversionCheck::storeOptions (
265
267
ClangTidyOptions::OptionMap &Opts) {
266
268
Options.store (Opts, " AllowIntegerConditions" , AllowIntegerConditions);
267
269
Options.store (Opts, " AllowPointerConditions" , AllowPointerConditions);
268
270
Options.store (Opts, " UseUpperCaseLiteralSuffix" , UseUpperCaseLiteralSuffix);
271
+ Options.store (Opts, " CheckConversionsToBool" , CheckConversionsToBool);
272
+ Options.store (Opts, " CheckConversionsFromBool" , CheckConversionsFromBool);
269
273
}
270
274
271
275
void ImplicitBoolConversionCheck::registerMatchers (MatchFinder *Finder) {
@@ -277,6 +281,7 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
277
281
expr (hasType (qualType ().bind (" type" )),
278
282
hasParent (initListExpr (hasParent (explicitCastExpr (
279
283
hasType (qualType (equalsBoundNode (" type" ))))))))));
284
+
280
285
auto ImplicitCastFromBool = implicitCastExpr (
281
286
anyOf (hasCastKind (CK_IntegralCast), hasCastKind (CK_IntegralToFloating),
282
287
// Prior to C++11 cast from bool literal to pointer was allowed.
@@ -287,72 +292,84 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
287
292
auto BoolXor =
288
293
binaryOperator (hasOperatorName (" ^" ), hasLHS (ImplicitCastFromBool),
289
294
hasRHS (ImplicitCastFromBool));
290
- auto ComparisonInCall = allOf (
291
- hasParent (callExpr ()),
292
- hasSourceExpression (binaryOperator (hasAnyOperatorName (" ==" , " !=" ))));
293
-
294
295
auto IsInCompilerGeneratedFunction = hasAncestor (namedDecl (anyOf (
295
296
isImplicit (), functionDecl (isDefaulted ()), functionTemplateDecl ())));
296
297
297
- Finder->addMatcher (
298
- traverse (TK_AsIs,
299
- implicitCastExpr (
300
- anyOf (hasCastKind (CK_IntegralToBoolean),
301
- hasCastKind (CK_FloatingToBoolean),
302
- hasCastKind (CK_PointerToBoolean),
303
- hasCastKind (CK_MemberPointerToBoolean)),
304
- // Exclude cases of C23 comparison result.
305
- unless (allOf (isC23 (),
306
- hasSourceExpression (ignoringParens (
307
- binaryOperator (hasAnyOperatorName (
308
- " >" , " >=" , " ==" , " !=" , " <" , " <=" )))))),
309
- // Exclude case of using if or while statements with variable
310
- // declaration, e.g.:
311
- // if (int var = functionCall()) {}
312
- unless (hasParent (
313
- stmt (anyOf (ifStmt (), whileStmt ()), has (declStmt ())))),
314
- // Exclude cases common to implicit cast to and from bool.
315
- unless (ExceptionCases), unless (has (BoolXor)),
316
- // Exclude C23 cases common to implicit cast to bool.
317
- unless (ComparisonInCall),
318
- // Retrieve also parent statement, to check if we need
319
- // additional parens in replacement.
320
- optionally (hasParent (stmt ().bind (" parentStmt" ))),
321
- unless (isInTemplateInstantiation ()),
322
- unless (IsInCompilerGeneratedFunction))
323
- .bind (" implicitCastToBool" )),
324
- this );
325
-
326
- auto BoolComparison = binaryOperator (hasAnyOperatorName (" ==" , " !=" ),
327
- hasLHS (ImplicitCastFromBool),
328
- hasRHS (ImplicitCastFromBool));
329
- auto BoolOpAssignment = binaryOperator (hasAnyOperatorName (" |=" , " &=" ),
330
- hasLHS (expr (hasType (booleanType ()))));
331
- auto BitfieldAssignment = binaryOperator (
332
- hasLHS (memberExpr (hasDeclaration (fieldDecl (hasBitWidth (1 ))))));
333
- auto BitfieldConstruct = cxxConstructorDecl (hasDescendant (cxxCtorInitializer (
334
- withInitializer (equalsBoundNode (" implicitCastFromBool" )),
335
- forField (hasBitWidth (1 )))));
336
- Finder->addMatcher (
337
- traverse (
338
- TK_AsIs,
339
- implicitCastExpr (
340
- ImplicitCastFromBool, unless (ExceptionCases),
341
- // Exclude comparisons of bools, as they are always cast to
342
- // integers in such context:
343
- // bool_expr_a == bool_expr_b
344
- // bool_expr_a != bool_expr_b
345
- unless (hasParent (
346
- binaryOperator (anyOf (BoolComparison, BoolXor,
347
- BoolOpAssignment, BitfieldAssignment)))),
348
- implicitCastExpr ().bind (" implicitCastFromBool" ),
349
- unless (hasParent (BitfieldConstruct)),
350
- // Check also for nested casts, for example: bool -> int -> float.
351
- anyOf (hasParent (implicitCastExpr ().bind (" furtherImplicitCast" )),
352
- anything ()),
353
- unless (isInTemplateInstantiation ()),
354
- unless (IsInCompilerGeneratedFunction))),
355
- this );
298
+ if (CheckConversionsToBool) {
299
+ auto ComparisonInCall = allOf (
300
+ hasParent (callExpr ()),
301
+ hasSourceExpression (binaryOperator (hasAnyOperatorName (" ==" , " !=" ))));
302
+
303
+ Finder->addMatcher (
304
+ traverse (
305
+ TK_AsIs,
306
+ implicitCastExpr (
307
+ anyOf (hasCastKind (CK_IntegralToBoolean),
308
+ hasCastKind (CK_FloatingToBoolean),
309
+ hasCastKind (CK_PointerToBoolean),
310
+ hasCastKind (CK_MemberPointerToBoolean)),
311
+ // Exclude cases of C23 comparison result.
312
+ unless (allOf (isC23 (),
313
+ hasSourceExpression (ignoringParens (
314
+ binaryOperator (hasAnyOperatorName (
315
+ " >" , " >=" , " ==" , " !=" , " <" , " <=" )))))),
316
+ // Exclude case of using if or while statements with variable
317
+ // declaration, e.g.:
318
+ // if (int var = functionCall()) {}
319
+ unless (hasParent (
320
+ stmt (anyOf (ifStmt (), whileStmt ()), has (declStmt ())))),
321
+ // Exclude cases common to implicit cast to and from bool.
322
+ unless (ExceptionCases), unless (has (BoolXor)),
323
+ // Exclude C23 cases common to implicit cast to bool.
324
+ unless (ComparisonInCall),
325
+ // Retrieve also parent statement, to check if we need
326
+ // additional parens in replacement.
327
+ optionally (hasParent (stmt ().bind (" parentStmt" ))),
328
+ unless (isInTemplateInstantiation ()),
329
+ unless (IsInCompilerGeneratedFunction))
330
+ .bind (" implicitCastToBool" )),
331
+ this );
332
+ }
333
+
334
+ if (CheckConversionsFromBool) {
335
+
336
+ auto BoolComparison = binaryOperator (hasAnyOperatorName (" ==" , " !=" ),
337
+ hasLHS (ImplicitCastFromBool),
338
+ hasRHS (ImplicitCastFromBool));
339
+
340
+ auto BoolOpAssignment = binaryOperator (
341
+ hasAnyOperatorName (" |=" , " &=" ), hasLHS (expr (hasType (booleanType ()))));
342
+
343
+ auto BitfieldAssignment = binaryOperator (
344
+ hasLHS (memberExpr (hasDeclaration (fieldDecl (hasBitWidth (1 ))))));
345
+
346
+ auto BitfieldConstruct =
347
+ cxxConstructorDecl (hasDescendant (cxxCtorInitializer (
348
+ withInitializer (equalsBoundNode (" implicitCastFromBool" )),
349
+ forField (hasBitWidth (1 )))));
350
+
351
+ Finder->addMatcher (
352
+ traverse (
353
+ TK_AsIs,
354
+ implicitCastExpr (
355
+ ImplicitCastFromBool, unless (ExceptionCases),
356
+ // Exclude comparisons of bools, as they are
357
+ // always cast to integers in such context:
358
+ // bool_expr_a == bool_expr_b
359
+ // bool_expr_a != bool_expr_b
360
+ unless (hasParent (binaryOperator (anyOf (BoolComparison, BoolXor,
361
+ BoolOpAssignment,
362
+ BitfieldAssignment)))),
363
+ implicitCastExpr ().bind (" implicitCastFromBool" ),
364
+ unless (hasParent (BitfieldConstruct)),
365
+ // Check also for nested casts, for example:
366
+ // bool -> int -> float.
367
+ anyOf (hasParent (implicitCastExpr ().bind (" furtherImplicitCast" )),
368
+ anything ()),
369
+ unless (isInTemplateInstantiation ()),
370
+ unless (IsInCompilerGeneratedFunction))),
371
+ this );
372
+ }
356
373
}
357
374
358
375
void ImplicitBoolConversionCheck::check (
0 commit comments