Index: clang-tidy/modernize/UseBoolLiteralsCheck.cpp =================================================================== --- clang-tidy/modernize/UseBoolLiteralsCheck.cpp +++ clang-tidy/modernize/UseBoolLiteralsCheck.cpp @@ -29,25 +29,46 @@ unless(isInTemplateInstantiation()), anyOf(hasParent(explicitCastExpr().bind("cast")), anything())), this); + + Finder->addMatcher( + conditionalOperator( + hasParent(implicitCastExpr( + hasImplicitDestinationType(qualType(booleanType())), + unless(isInTemplateInstantiation()))), + // anyOf() is not evaluating second argument if first is evaluated as + // 'true'. We'd like to bind both literals if they are presents. Thus, + // using anyOf(BINDLITERAL(), anything()). + anyOf(hasTrueExpression(ignoringParenImpCasts( + integerLiteral().bind("trueBranchLiteral"))), + anything()), + anyOf(hasFalseExpression(ignoringParenImpCasts( + integerLiteral().bind("falseBranchLiteral"))), + anything())), + this); } void UseBoolLiteralsCheck::check(const MatchFinder::MatchResult &Result) { - const auto *Literal = Result.Nodes.getNodeAs("literal"); - const auto *Cast = Result.Nodes.getNodeAs("cast"); - bool LiteralBooleanValue = Literal->getValue().getBoolValue(); + for (const auto &BindingName : + {"literal", "trueBranchLiteral", "falseBranchLiteral"}) { + const auto *Literal = Result.Nodes.getNodeAs(BindingName); + if (!Literal) + continue; + const auto *Cast = Result.Nodes.getNodeAs("cast"); + bool LiteralBooleanValue = Literal->getValue().getBoolValue(); - if (Literal->isInstantiationDependent()) - return; + if (Literal->isInstantiationDependent()) + continue; - const Expr *Expression = Cast ? Cast : Literal; + const Expr *Expression = Cast ? Cast : Literal; - auto Diag = - diag(Expression->getExprLoc(), - "converting integer literal to bool, use bool literal instead"); + auto Diag = + diag(Expression->getExprLoc(), + "converting integer literal to bool, use bool literal instead"); - if (!Expression->getLocStart().isMacroID()) - Diag << FixItHint::CreateReplacement( - Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false"); + if (!Expression->getLocStart().isMacroID()) + Diag << FixItHint::CreateReplacement( + Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false"); + } } } // namespace modernize Index: docs/clang-tidy/checks/modernize-use-bool-literals.rst =================================================================== --- docs/clang-tidy/checks/modernize-use-bool-literals.rst +++ docs/clang-tidy/checks/modernize-use-bool-literals.rst @@ -10,9 +10,11 @@ bool p = 1; bool f = static_cast(1); std::ios_base::sync_with_stdio(0); + bool x = p ? 1 : 0; // transforms to bool p = true; bool f = true; std::ios_base::sync_with_stdio(false); + bool x = p ? true : false; Index: test/clang-tidy/modernize-use-bool-literals.cpp =================================================================== --- test/clang-tidy/modernize-use-bool-literals.cpp +++ test/clang-tidy/modernize-use-bool-literals.cpp @@ -116,3 +116,33 @@ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} // CHECK-FIXES: {{^ *}}IntToTrue = true;{{$}} } + +static int Value = 1; + +bool Function1() { + bool Result = Value == 1 ? 1 : 0; + // CHECK-MESSAGES: :[[@LINE-1]]:30: {{.*}} + // CHECK-MESSAGES: :[[@LINE-2]]:34: {{.*}} + // CHECK-FIXES: {{^ *}}bool Result = Value == 1 ? true : false;{{$}} + return Result; +} + +bool Function2() { + return Value == 1 ? 1 : 0; + // CHECK-MESSAGES: :[[@LINE-1]]:23: {{.*}} + // CHECK-MESSAGES: :[[@LINE-2]]:27: {{.*}} + // CHECK-FIXES: {{^ *}}return Value == 1 ? true : false;{{$}} +} + +void foo() { + bool Result; + Result = Value == 1 ? true : 0; + // CHECK-MESSAGES: :[[@LINE-1]]:32: {{.*}} + // CHECK-FIXES: {{^ *}}Result = Value == 1 ? true : false;{{$}} + Result = Value == 1 ? false : bool(0); + // CHECK-MESSAGES: :[[@LINE-1]]:33: {{.*}} + // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}} + Result = Value == 1 ? (bool)0 : false; + // CHECK-MESSAGES: :[[@LINE-1]]:25: {{.*}} + // CHECK-FIXES: {{^ *}}Result = Value == 1 ? false : false;{{$}} +}