34 auto OperatorMatcher = expr(
35 anyOf(binaryOperator(anyOf(isComparisonOperator(), isLogicalOperator())),
36 cxxOperatorCallExpr(isComparisonOperator())));
38 auto IsInUnevaluatedContext =
39 expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())),
40 hasAncestor(typeLoc())));
44 OperatorMatcher, unless(isExpansionInSystemHeader()),
45 unless(hasAncestor(OperatorMatcher)), expr().bind(
"parent"),
48 expr(anyOf(unaryOperator(isUnaryPrePostOperator(),
49 hasUnaryOperand(expr().bind(
"operand"))),
52 hasUnaryOperand(expr().bind(
"operand")))),
53 unless(IsInUnevaluatedContext),
55 expr(equalsBoundNode(
"parent"),
57 expr(unless(equalsBoundNode(
"operand")),
58 matchers::isStatementIdenticalToBoundNode(
60 unless(IsInUnevaluatedContext))
68 SourceLocation ExprLoc;
69 bool IsIncrementOp =
false;
71 if (
const auto *MatchedDecl =
72 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"operator")) {
73 ExprLoc = MatchedDecl->getExprLoc();
74 IsIncrementOp = (MatchedDecl->getOperator() == OO_PlusPlus);
75 }
else if (
const auto *MatchedDecl =
76 Result.Nodes.getNodeAs<UnaryOperator>(
"operator")) {
77 ExprLoc = MatchedDecl->getExprLoc();
78 IsIncrementOp = MatchedDecl->isIncrementOp();
83 "%select{decrementing|incrementing}0 and referencing a variable in a "
84 "complex condition can cause unintended side-effects due to C++'s order "
85 "of evaluation, consider moving the modification outside of the "
86 "condition to avoid misunderstandings")
88 diag(Result.Nodes.getNodeAs<Expr>(
"second")->getExprLoc(),
89 "variable is referenced here", DiagnosticIDs::Note);