82 lines
2.6 KiB
C++
82 lines
2.6 KiB
C++
//===--- AssignmentInIfConditionCheck.cpp - clang-tidy --------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AssignmentInIfConditionCheck.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/RecursiveASTVisitor.h"
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
|
|
using namespace clang::ast_matchers;
|
|
|
|
namespace clang {
|
|
namespace tidy {
|
|
namespace bugprone {
|
|
|
|
void AssignmentInIfConditionCheck::registerMatchers(MatchFinder *Finder) {
|
|
Finder->addMatcher(translationUnitDecl(), this);
|
|
}
|
|
|
|
void AssignmentInIfConditionCheck::check(
|
|
const ast_matchers::MatchFinder::MatchResult &Result) {
|
|
class Visitor : public RecursiveASTVisitor<Visitor> {
|
|
AssignmentInIfConditionCheck &Check;
|
|
|
|
public:
|
|
explicit Visitor(AssignmentInIfConditionCheck &Check) : Check(Check) {}
|
|
bool VisitIfStmt(IfStmt *If) {
|
|
class ConditionVisitor : public RecursiveASTVisitor<ConditionVisitor> {
|
|
AssignmentInIfConditionCheck &Check;
|
|
|
|
public:
|
|
explicit ConditionVisitor(AssignmentInIfConditionCheck &Check)
|
|
: Check(Check) {}
|
|
|
|
// Dont traverse into any lambda expressions.
|
|
bool TraverseLambdaExpr(LambdaExpr *, DataRecursionQueue * = nullptr) {
|
|
return true;
|
|
}
|
|
|
|
bool VisitBinaryOperator(BinaryOperator *BO) {
|
|
if (BO->isAssignmentOp())
|
|
Check.report(BO);
|
|
return true;
|
|
}
|
|
|
|
bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *OCE) {
|
|
if (OCE->isAssignmentOp())
|
|
Check.report(OCE);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
ConditionVisitor(Check).TraverseStmt(If->getCond());
|
|
return true;
|
|
}
|
|
};
|
|
Visitor(*this).TraverseAST(*Result.Context);
|
|
}
|
|
|
|
void AssignmentInIfConditionCheck::report(const Expr *AssignmentExpr) {
|
|
SourceLocation OpLoc =
|
|
isa<BinaryOperator>(AssignmentExpr)
|
|
? cast<BinaryOperator>(AssignmentExpr)->getOperatorLoc()
|
|
: cast<CXXOperatorCallExpr>(AssignmentExpr)->getOperatorLoc();
|
|
|
|
diag(OpLoc, "an assignment within an 'if' condition is bug-prone")
|
|
<< AssignmentExpr->getSourceRange();
|
|
diag(OpLoc,
|
|
"if it should be an assignment, move it out of the 'if' condition",
|
|
DiagnosticIDs::Note);
|
|
diag(OpLoc, "if it is meant to be an equality check, change '=' to '=='",
|
|
DiagnosticIDs::Note);
|
|
}
|
|
|
|
} // namespace bugprone
|
|
} // namespace tidy
|
|
} // namespace clang
|