10#include "../utils/Matchers.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
21 return Node.isPrefix() ||
Node.isPostfix();
25 return Node.getOperator() == OO_PlusPlus ||
26 Node.getOperator() == OO_MinusMinus;
30 auto OperatorMatcher = expr(
31 anyOf(binaryOperator(anyOf(isComparisonOperator(), isLogicalOperator())),
32 cxxOperatorCallExpr(isComparisonOperator())));
34 auto IsInUnevaluatedContext =
35 expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())),
36 hasAncestor(typeLoc())));
40 OperatorMatcher, unless(isExpansionInSystemHeader()),
41 unless(hasAncestor(OperatorMatcher)), expr().bind(
"parent"),
44 expr(anyOf(unaryOperator(isUnaryPrePostOperator(),
45 hasUnaryOperand(expr().bind(
"operand"))),
48 hasUnaryOperand(expr().bind(
"operand")))),
49 unless(IsInUnevaluatedContext),
51 expr(equalsBoundNode(
"parent"),
53 expr(unless(equalsBoundNode(
"operand")),
54 matchers::isStatementIdenticalToBoundNode(
56 unless(IsInUnevaluatedContext))
65 bool IsIncrementOp =
false;
67 if (
const auto *MatchedDecl =
68 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"operator")) {
69 ExprLoc = MatchedDecl->getExprLoc();
70 IsIncrementOp = (MatchedDecl->getOperator() == OO_PlusPlus);
71 }
else if (
const auto *MatchedDecl =
72 Result.Nodes.getNodeAs<UnaryOperator>(
"operator")) {
73 ExprLoc = MatchedDecl->getExprLoc();
74 IsIncrementOp = MatchedDecl->isIncrementOp();
79 "%select{decrementing|incrementing}0 and referencing a variable in a "
80 "complex condition can cause unintended side-effects due to C++'s order "
81 "of evaluation, consider moving the modification outside of the "
82 "condition to avoid misunderstandings")
84 diag(Result.Nodes.getNodeAs<Expr>(
"second")->getExprLoc(),
85 "variable is referenced here", DiagnosticIDs::Note);
::clang::DynTypedNode Node
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
AST_MATCHER(clang::VarDecl, hasConstantDeclaration)