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))
67 SourceLocation ExprLoc;
68 bool IsIncrementOp =
false;
70 if (
const auto *MatchedDecl =
71 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"operator")) {
72 ExprLoc = MatchedDecl->getExprLoc();
73 IsIncrementOp = (MatchedDecl->getOperator() == OO_PlusPlus);
74 }
else if (
const auto *MatchedDecl =
75 Result.Nodes.getNodeAs<UnaryOperator>(
"operator")) {
76 ExprLoc = MatchedDecl->getExprLoc();
77 IsIncrementOp = MatchedDecl->isIncrementOp();
82 "%select{decrementing|incrementing}0 and referencing a variable in a "
83 "complex condition can cause unintended side-effects due to C++'s order "
84 "of evaluation, consider moving the modification outside of the "
85 "condition to avoid misunderstandings")
87 diag(Result.Nodes.getNodeAs<Expr>(
"second")->getExprLoc(),
88 "variable is referenced here", DiagnosticIDs::Note);