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
9#include "AssignmentInIfConditionCheck.h"
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
18void AssignmentInIfConditionCheck::registerMatchers(MatchFinder *Finder) {
19 Finder->addMatcher(NodeMatch: translationUnitDecl(), Action: this);
20}
21
22void AssignmentInIfConditionCheck::check(
23 const ast_matchers::MatchFinder::MatchResult &Result) {
24 class Visitor : public RecursiveASTVisitor<Visitor> {
25 AssignmentInIfConditionCheck &Check;
26
27 public:
28 explicit Visitor(AssignmentInIfConditionCheck &Check) : Check(Check) {}
29 bool VisitIfStmt(IfStmt *If) {
30 class ConditionVisitor : public RecursiveASTVisitor<ConditionVisitor> {
31 AssignmentInIfConditionCheck &Check;
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 // Dont traverse into any requires expressions.
43 bool TraverseRequiresExpr(RequiresExpr *,
44 DataRecursionQueue * = nullptr) {
45 return true;
46 }
47
48 bool VisitBinaryOperator(BinaryOperator *BO) {
49 if (BO->isAssignmentOp())
50 Check.report(BO);
51 return true;
52 }
53
54 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *OCE) {
55 if (OCE->isAssignmentOp())
56 Check.report(OCE);
57 return true;
58 }
59 };
60
61 ConditionVisitor(Check).TraverseStmt(If->getCond());
62 return true;
63 }
64 };
65 Visitor(*this).TraverseAST(AST&: *Result.Context);
66}
67
68void AssignmentInIfConditionCheck::report(const Expr *AssignmentExpr) {
69 SourceLocation OpLoc =
70 isa<BinaryOperator>(Val: AssignmentExpr)
71 ? cast<BinaryOperator>(Val: AssignmentExpr)->getOperatorLoc()
72 : cast<CXXOperatorCallExpr>(Val: AssignmentExpr)->getOperatorLoc();
73
74 diag(Loc: OpLoc, Description: "an assignment within an 'if' condition is bug-prone")
75 << AssignmentExpr->getSourceRange();
76 diag(Loc: OpLoc,
77 Description: "if it should be an assignment, move it out of the 'if' condition",
78 Level: DiagnosticIDs::Note);
79 diag(Loc: OpLoc, Description: "if it is meant to be an equality check, change '=' to '=='",
80 Level: DiagnosticIDs::Note);
81}
82
83} // namespace clang::tidy::bugprone
84

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp