[clang-tidy] fix readability-implicit-bool-cast false alarm on |=, &=

llvm-svn: 302161
This commit is contained in:
Alexander Kornienko 2017-05-04 15:34:31 +00:00
parent cbe8d16da4
commit b92cb07bad
2 changed files with 28 additions and 25 deletions

View File

@ -40,24 +40,6 @@ AST_MATCHER(Stmt, isNULLMacroExpansion) {
return isNULLMacroExpansion(&Node, Finder->getASTContext()); return isNULLMacroExpansion(&Node, Finder->getASTContext());
} }
ast_matchers::internal::Matcher<Expr> createExceptionCasesMatcher() {
return expr(anyOf(hasParent(explicitCastExpr()),
allOf(isMacroExpansion(), unless(isNULLMacroExpansion())),
isInTemplateInstantiation(),
hasAncestor(functionTemplateDecl())));
}
StatementMatcher createImplicitCastFromBoolMatcher() {
return implicitCastExpr(
unless(createExceptionCasesMatcher()),
anyOf(hasCastKind(CK_IntegralCast), hasCastKind(CK_IntegralToFloating),
// Prior to C++11 cast from bool literal to pointer was allowed.
allOf(anyOf(hasCastKind(CK_NullToPointer),
hasCastKind(CK_NullToMemberPointer)),
hasSourceExpression(cxxBoolLiteral()))),
hasSourceExpression(expr(hasType(qualType(booleanType())))));
}
StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind, StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type, QualType Type,
ASTContext &Context) { ASTContext &Context) {
@ -284,10 +266,15 @@ void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
return; return;
} }
auto exceptionCases = expr(
anyOf(hasParent(explicitCastExpr()),
allOf(isMacroExpansion(), unless(isNULLMacroExpansion())),
isInTemplateInstantiation(), hasAncestor(functionTemplateDecl())));
Finder->addMatcher( Finder->addMatcher(
implicitCastExpr( implicitCastExpr(
// Exclude cases common to implicit cast to and from bool. // Exclude cases common to implicit cast to and from bool.
unless(createExceptionCasesMatcher()), unless(exceptionCases),
// Exclude case of using if or while statements with variable // Exclude case of using if or while statements with variable
// declaration, e.g.: // declaration, e.g.:
// if (int var = functionCall()) {} // if (int var = functionCall()) {}
@ -303,17 +290,30 @@ void ImplicitBoolCastCheck::registerMatchers(MatchFinder *Finder) {
.bind("implicitCastToBool"), .bind("implicitCastToBool"),
this); this);
auto implicitCastFromBool = implicitCastExpr(
unless(exceptionCases),
anyOf(hasCastKind(CK_IntegralCast), hasCastKind(CK_IntegralToFloating),
// Prior to C++11 cast from bool literal to pointer was allowed.
allOf(anyOf(hasCastKind(CK_NullToPointer),
hasCastKind(CK_NullToMemberPointer)),
hasSourceExpression(cxxBoolLiteral()))),
hasSourceExpression(expr(hasType(booleanType()))));
auto boolComparison = binaryOperator(
anyOf(hasOperatorName("=="), hasOperatorName("!=")),
hasLHS(implicitCastFromBool), hasRHS(implicitCastFromBool));
auto boolOpAssignment = binaryOperator(
anyOf(hasOperatorName("|="), hasOperatorName("&=")),
hasLHS(expr(hasType(booleanType()))), hasRHS(implicitCastFromBool));
Finder->addMatcher( Finder->addMatcher(
implicitCastExpr( implicitCastExpr(
createImplicitCastFromBoolMatcher(), implicitCastFromBool,
// Exclude comparisons of bools, as they are always cast to integers // Exclude comparisons of bools, as they are always cast to integers
// in such context: // in such context:
// bool_expr_a == bool_expr_b // bool_expr_a == bool_expr_b
// bool_expr_a != bool_expr_b // bool_expr_a != bool_expr_b
unless(hasParent(binaryOperator( unless(hasParent(
anyOf(hasOperatorName("=="), hasOperatorName("!=")), binaryOperator(anyOf(boolComparison, boolOpAssignment)))),
hasLHS(createImplicitCastFromBoolMatcher()),
hasRHS(createImplicitCastFromBoolMatcher())))),
// Check also for nested casts, for example: bool -> int -> float. // Check also for nested casts, for example: bool -> int -> float.
anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")), anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")),
anything())) anything()))

View File

@ -48,8 +48,11 @@ float implicitCastFromBoolInReturnValue() {
// CHECK-FIXES: return static_cast<float>(boolean); // CHECK-FIXES: return static_cast<float>(boolean);
} }
void implicitCastFromBoolInSingleBoolExpressions() { void implicitCastFromBoolInSingleBoolExpressions(bool b1, bool b2) {
bool boolean = true; bool boolean = true;
boolean = b1 && b2;
boolean |= !b1 || !b2;
boolean &= b1;
int integer = boolean - 3; int integer = boolean - 3;
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int' // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'