Index: clang-tools-extra/trunk/clang-tidy/readability/ImplicitBoolConversionCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -306,6 +306,11 @@ auto boolOpAssignment = binaryOperator(anyOf(hasOperatorName("|="), hasOperatorName("&=")), hasLHS(expr(hasType(booleanType())))); + auto bitfieldAssignment = binaryOperator( + hasLHS(memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1)))))); + auto bitfieldConstruct = cxxConstructorDecl(hasDescendant(cxxCtorInitializer( + withInitializer(equalsBoundNode("implicitCastFromBool")), + forField(hasBitWidth(1))))); Finder->addMatcher( implicitCastExpr( implicitCastFromBool, @@ -313,14 +318,15 @@ // in such context: // bool_expr_a == bool_expr_b // bool_expr_a != bool_expr_b - unless(hasParent(binaryOperator( - anyOf(boolComparison, boolXor, boolOpAssignment)))), + unless(hasParent(binaryOperator(anyOf( + boolComparison, boolXor, boolOpAssignment, bitfieldAssignment)))), + implicitCastExpr().bind("implicitCastFromBool"), + unless(hasParent(bitfieldConstruct)), // Check also for nested casts, for example: bool -> int -> float. anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")), anything()), unless(isInTemplateInstantiation()), - unless(hasAncestor(functionTemplateDecl()))) - .bind("implicitCastFromBool"), + unless(hasAncestor(functionTemplateDecl()))), this); } Index: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst @@ -74,7 +74,8 @@ - pointer/pointer to member/``nullptr``/``NULL`` to boolean, -- boolean expression/literal to integer, +- boolean expression/literal to integer (conversion from boolean to a single + bit bitfield is explicitly allowed), - boolean expression/literal to floating. Index: clang-tools-extra/trunk/test/clang-tidy/readability-implicit-bool-conversion.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/readability-implicit-bool-conversion.cpp +++ clang-tools-extra/trunk/test/clang-tidy/readability-implicit-bool-conversion.cpp @@ -444,14 +444,27 @@ int a; int b : 1; int c : 2; + + S(bool a, bool b, bool c) : a(a), b(b), c(c) {} + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion bool -> 'int' + // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: implicit conversion bool -> 'int' + // CHECK-FIXES: S(bool a, bool b, bool c) : a(static_cast(a)), b(b), c(static_cast(c)) {} }; -bool f(const S& s) { +bool f(S& s) { functionTaking(s.a); // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool // CHECK-FIXES: functionTaking(s.a != 0); functionTaking(s.b); // CHECK-FIXES: functionTaking(s.b); + s.a = true; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion bool -> 'int' + // CHECK-FIXES: s.a = 1; + s.b = true; + // CHECK-FIXES: s.b = true; + s.c = true; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion bool -> 'int' + // CHECK-FIXES: s.c = 1; functionTaking(s.c); // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'int' -> bool // CHECK-FIXES: functionTaking(s.c != 0);