brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · d5d8a29 Raw
84 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//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(translationUnitDecl(), 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(*Result.Context);66}67 68void AssignmentInIfConditionCheck::report(const Expr *AssignmentExpr) {69  const SourceLocation OpLoc =70      isa<BinaryOperator>(AssignmentExpr)71          ? cast<BinaryOperator>(AssignmentExpr)->getOperatorLoc()72          : cast<CXXOperatorCallExpr>(AssignmentExpr)->getOperatorLoc();73 74  diag(OpLoc, "an assignment within an 'if' condition is bug-prone")75      << AssignmentExpr->getSourceRange();76  diag(OpLoc,77       "if it should be an assignment, move it out of the 'if' condition",78       DiagnosticIDs::Note);79  diag(OpLoc, "if it is meant to be an equality check, change '=' to '=='",80       DiagnosticIDs::Note);81}82 83} // namespace clang::tidy::bugprone84