@@ -56,26 +56,23 @@ AST_MATCHER(Expr, usedInBooleanContext) {
56
56
const char *ExprName = " __booleanContextExpr" ;
57
57
auto Result =
58
58
expr (expr ().bind (ExprName),
59
- anyOf (hasParent (varDecl (hasType (booleanType ()))),
59
+ anyOf (hasParent (
60
+ mapAnyOf (varDecl, fieldDecl).with (hasType (booleanType ()))),
60
61
hasParent (cxxConstructorDecl (
61
62
hasAnyConstructorInitializer (cxxCtorInitializer (
62
63
withInitializer (expr (equalsBoundNode (ExprName))),
63
64
forField (hasType (booleanType ())))))),
64
- hasParent (fieldDecl (hasType (booleanType ()))),
65
65
hasParent (stmt (anyOf (
66
66
explicitCastExpr (hasDestinationType (booleanType ())),
67
- ifStmt (hasCondition (expr (equalsBoundNode (ExprName)))),
68
- doStmt (hasCondition (expr (equalsBoundNode (ExprName)))),
69
- whileStmt (hasCondition (expr (equalsBoundNode (ExprName)))),
70
- forStmt (hasCondition (expr (equalsBoundNode (ExprName)))),
71
- conditionalOperator (
72
- hasCondition (expr (equalsBoundNode (ExprName)))),
67
+ mapAnyOf (ifStmt, doStmt, whileStmt, forStmt,
68
+ conditionalOperator)
69
+ .with (hasCondition (expr (equalsBoundNode (ExprName)))),
73
70
parenListExpr (hasParent (varDecl (hasType (booleanType ())))),
74
71
parenExpr (hasParent (
75
72
explicitCastExpr (hasDestinationType (booleanType ())))),
76
73
returnStmt (forFunction (returns (booleanType ()))),
77
74
cxxUnresolvedConstructExpr (hasType (booleanType ())),
78
- callExpr (hasAnyArgumentWithParam (
75
+ invocation (hasAnyArgumentWithParam (
79
76
expr (equalsBoundNode (ExprName)),
80
77
parmVarDecl (hasType (booleanType ())))),
81
78
binaryOperator (hasAnyOperatorName (" &&" , " ||" )),
@@ -181,21 +178,12 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
181
178
expr (hasType (pointsTo (ValidContainer))).bind (" Pointee" ))),
182
179
expr (hasType (ValidContainer)).bind (" STLObject" ));
183
180
Finder->addMatcher (
184
- cxxOperatorCallExpr (
185
- unless (isInTemplateInstantiation ()),
186
- hasAnyOverloadedOperatorName (" ==" , " !=" ),
187
- anyOf (allOf (hasArgument (0 , WrongComparend), hasArgument (1 , STLArg)),
188
- allOf (hasArgument (0 , STLArg), hasArgument (1 , WrongComparend))),
189
- unless (hasAncestor (
190
- cxxMethodDecl (ofClass (equalsBoundNode (" container" ))))))
191
- .bind (" BinCmp" ),
192
- this );
193
- Finder->addMatcher (
194
- binaryOperator (hasAnyOperatorName (" ==" , " !=" ),
195
- anyOf (allOf (hasLHS (WrongComparend), hasRHS (STLArg)),
196
- allOf (hasLHS (STLArg), hasRHS (WrongComparend))),
197
- unless (hasAncestor (
198
- cxxMethodDecl (ofClass (equalsBoundNode (" container" ))))))
181
+ binaryOperation (unless (isInTemplateInstantiation ()),
182
+ hasAnyOperatorName (" ==" , " !=" ),
183
+ hasOperands (ignoringParenImpCasts (WrongComparend),
184
+ ignoringParenImpCasts (STLArg)),
185
+ unless (hasAncestor (cxxMethodDecl (
186
+ ofClass (equalsBoundNode (" container" ))))))
199
187
.bind (" BinCmp" ),
200
188
this );
201
189
}
@@ -206,6 +194,8 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
206
194
Result.Nodes .getNodeAs <Expr>(" MemberCallObject" );
207
195
const auto *BinCmp = Result.Nodes .getNodeAs <CXXOperatorCallExpr>(" BinCmp" );
208
196
const auto *BinCmpTempl = Result.Nodes .getNodeAs <BinaryOperator>(" BinCmp" );
197
+ const auto *BinCmpRewritten =
198
+ Result.Nodes .getNodeAs <CXXRewrittenBinaryOperator>(" BinCmp" );
209
199
const auto *BinaryOp = Result.Nodes .getNodeAs <BinaryOperator>(" SizeBinaryOp" );
210
200
const auto *Pointee = Result.Nodes .getNodeAs <Expr>(" Pointee" );
211
201
const auto *E =
@@ -236,6 +226,12 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
236
226
}
237
227
Hint = FixItHint::CreateReplacement (BinCmpTempl->getSourceRange (),
238
228
ReplacementText);
229
+ } else if (BinCmpRewritten) {
230
+ if (BinCmpRewritten->getOpcode () == BinaryOperatorKind::BO_NE) {
231
+ ReplacementText = " !" + ReplacementText;
232
+ }
233
+ Hint = FixItHint::CreateReplacement (BinCmpRewritten->getSourceRange (),
234
+ ReplacementText);
239
235
} else if (BinaryOp) { // Determine the correct transformation.
240
236
bool Negation = false ;
241
237
const bool ContainerIsLHS =
@@ -313,8 +309,11 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
313
309
" for emptiness instead of 'size'" )
314
310
<< Hint;
315
311
} else {
316
- WarnLoc = BinCmpTempl ? BinCmpTempl->getBeginLoc ()
317
- : (BinCmp ? BinCmp->getBeginLoc () : SourceLocation{});
312
+ WarnLoc = BinCmpTempl
313
+ ? BinCmpTempl->getBeginLoc ()
314
+ : (BinCmp ? BinCmp->getBeginLoc ()
315
+ : (BinCmpRewritten ? BinCmpRewritten->getBeginLoc ()
316
+ : SourceLocation{}));
318
317
diag (WarnLoc, " the 'empty' method should be used to check "
319
318
" for emptiness instead of comparing to an empty object" )
320
319
<< Hint;
0 commit comments