clang-tools 19.0.0git
AssignmentInIfConditionCheck.cpp
Go to the documentation of this file.
1//===--- AssignmentInIfConditionCheck.cpp - clang-tidy --------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/AST/ASTContext.h"
11#include "clang/AST/RecursiveASTVisitor.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13
14using namespace clang::ast_matchers;
15
16namespace clang::tidy::bugprone {
17
19 Finder->addMatcher(translationUnitDecl(), this);
20}
21
23 const ast_matchers::MatchFinder::MatchResult &Result) {
24 class Visitor : public RecursiveASTVisitor<Visitor> {
26
27 public:
28 explicit Visitor(AssignmentInIfConditionCheck &Check) : Check(Check) {}
29 bool VisitIfStmt(IfStmt *If) {
30 class ConditionVisitor : public RecursiveASTVisitor<ConditionVisitor> {
32
33 public:
34 explicit ConditionVisitor(AssignmentInIfConditionCheck &Check)
35 : Check(Check) {}
36
37 // Dont traverse into any lambda expressions.
38 bool TraverseLambdaExpr(LambdaExpr *, DataRecursionQueue * = nullptr) {
39 return true;
40 }
41
42 bool VisitBinaryOperator(BinaryOperator *BO) {
43 if (BO->isAssignmentOp())
44 Check.report(BO);
45 return true;
46 }
47
48 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *OCE) {
49 if (OCE->isAssignmentOp())
50 Check.report(OCE);
51 return true;
52 }
53 };
54
55 ConditionVisitor(Check).TraverseStmt(If->getCond());
56 return true;
57 }
58 };
59 Visitor(*this).TraverseAST(*Result.Context);
60}
61
62void AssignmentInIfConditionCheck::report(const Expr *AssignmentExpr) {
63 SourceLocation OpLoc =
64 isa<BinaryOperator>(AssignmentExpr)
65 ? cast<BinaryOperator>(AssignmentExpr)->getOperatorLoc()
66 : cast<CXXOperatorCallExpr>(AssignmentExpr)->getOperatorLoc();
67
68 diag(OpLoc, "an assignment within an 'if' condition is bug-prone")
69 << AssignmentExpr->getSourceRange();
70 diag(OpLoc,
71 "if it should be an assignment, move it out of the 'if' condition",
72 DiagnosticIDs::Note);
73 diag(OpLoc, "if it is meant to be an equality check, change '=' to '=='",
74 DiagnosticIDs::Note);
75}
76
77} // namespace clang::tidy::bugprone
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
Catches assignments within the condition clause of an if statement.
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.