diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 | 
| commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
| tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp | |
| parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp | 518 | 
1 files changed, 0 insertions, 518 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp deleted file mode 100644 index cc2cfb774227..000000000000 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ /dev/null @@ -1,518 +0,0 @@ -//== IdenticalExprChecker.cpp - Identical expression checker----------------==// -// -// 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 -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This defines IdenticalExprChecker, a check that warns about -/// unintended use of identical expressions. -/// -/// It checks for use of identical expressions with comparison operators and -/// inside conditional expressions. -/// -//===----------------------------------------------------------------------===// - -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" - -using namespace clang; -using namespace ento; - -static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, -                            const Stmt *Stmt2, bool IgnoreSideEffects = false); -//===----------------------------------------------------------------------===// -// FindIdenticalExprVisitor - Identify nodes using identical expressions. -//===----------------------------------------------------------------------===// - -namespace { -class FindIdenticalExprVisitor -    : public RecursiveASTVisitor<FindIdenticalExprVisitor> { -  BugReporter &BR; -  const CheckerBase *Checker; -  AnalysisDeclContext *AC; -public: -  explicit FindIdenticalExprVisitor(BugReporter &B, -                                    const CheckerBase *Checker, -                                    AnalysisDeclContext *A) -      : BR(B), Checker(Checker), AC(A) {} -  // FindIdenticalExprVisitor only visits nodes -  // that are binary operators, if statements or -  // conditional operators. -  bool VisitBinaryOperator(const BinaryOperator *B); -  bool VisitIfStmt(const IfStmt *I); -  bool VisitConditionalOperator(const ConditionalOperator *C); - -private: -  void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise, -                           ArrayRef<SourceRange> Sr); -  void checkBitwiseOrLogicalOp(const BinaryOperator *B, bool CheckBitwise); -  void checkComparisonOp(const BinaryOperator *B); -}; -} // end anonymous namespace - -void FindIdenticalExprVisitor::reportIdenticalExpr(const BinaryOperator *B, -                                                   bool CheckBitwise, -                                                   ArrayRef<SourceRange> Sr) { -  StringRef Message; -  if (CheckBitwise) -    Message = "identical expressions on both sides of bitwise operator"; -  else -    Message = "identical expressions on both sides of logical operator"; - -  PathDiagnosticLocation ELoc = -      PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager()); -  BR.EmitBasicReport(AC->getDecl(), Checker, -                     "Use of identical expressions", -                     categories::LogicError, -                     Message, ELoc, Sr); -} - -void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B, -                                                       bool CheckBitwise) { -  SourceRange Sr[2]; - -  const Expr *LHS = B->getLHS(); -  const Expr *RHS = B->getRHS(); - -  // Split operators as long as we still have operators to split on. We will -  // get called for every binary operator in an expression so there is no need -  // to check every one against each other here, just the right most one with -  // the others. -  while (const BinaryOperator *B2 = dyn_cast<BinaryOperator>(LHS)) { -    if (B->getOpcode() != B2->getOpcode()) -      break; -    if (isIdenticalStmt(AC->getASTContext(), RHS, B2->getRHS())) { -      Sr[0] = RHS->getSourceRange(); -      Sr[1] = B2->getRHS()->getSourceRange(); -      reportIdenticalExpr(B, CheckBitwise, Sr); -    } -    LHS = B2->getLHS(); -  } - -  if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) { -    Sr[0] = RHS->getSourceRange(); -    Sr[1] = LHS->getSourceRange(); -    reportIdenticalExpr(B, CheckBitwise, Sr); -  } -} - -bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { -  const Stmt *Stmt1 = I->getThen(); -  const Stmt *Stmt2 = I->getElse(); - -  // Check for identical inner condition: -  // -  // if (x<10) { -  //   if (x<10) { -  //   .. -  if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(Stmt1)) { -    if (!CS->body_empty()) { -      const IfStmt *InnerIf = dyn_cast<IfStmt>(*CS->body_begin()); -      if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*IgnoreSideEffects=*/ false)) { -        PathDiagnosticLocation ELoc(InnerIf->getCond(), BR.getSourceManager(), AC); -        BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions", -          categories::LogicError, -          "conditions of the inner and outer statements are identical", -          ELoc); -      } -    } -  } - -  // Check for identical conditions: -  // -  // if (b) { -  //   foo1(); -  // } else if (b) { -  //   foo2(); -  // } -  if (Stmt1 && Stmt2) { -    const Expr *Cond1 = I->getCond(); -    const Stmt *Else = Stmt2; -    while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) { -      const Expr *Cond2 = I2->getCond(); -      if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) { -        SourceRange Sr = Cond1->getSourceRange(); -        PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC); -        BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions", -                           categories::LogicError, -                           "expression is identical to previous condition", -                           ELoc, Sr); -      } -      Else = I2->getElse(); -    } -  } - -  if (!Stmt1 || !Stmt2) -    return true; - -  // Special handling for code like: -  // -  // if (b) { -  //   i = 1; -  // } else -  //   i = 1; -  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) { -    if (CompStmt->size() == 1) -      Stmt1 = CompStmt->body_back(); -  } -  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) { -    if (CompStmt->size() == 1) -      Stmt2 = CompStmt->body_back(); -  } - -  if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) { -      PathDiagnosticLocation ELoc = -          PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC); -      BR.EmitBasicReport(AC->getDecl(), Checker, -                         "Identical branches", -                         categories::LogicError, -                         "true and false branches are identical", ELoc); -  } -  return true; -} - -bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) { -  BinaryOperator::Opcode Op = B->getOpcode(); - -  if (BinaryOperator::isBitwiseOp(Op)) -    checkBitwiseOrLogicalOp(B, true); - -  if (BinaryOperator::isLogicalOp(Op)) -    checkBitwiseOrLogicalOp(B, false); - -  if (BinaryOperator::isComparisonOp(Op)) -    checkComparisonOp(B); - -  // We want to visit ALL nodes (subexpressions of binary comparison -  // expressions too) that contains comparison operators. -  // True is always returned to traverse ALL nodes. -  return true; -} - -void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) { -  BinaryOperator::Opcode Op = B->getOpcode(); - -  // -  // Special case for floating-point representation. -  // -  // If expressions on both sides of comparison operator are of type float, -  // then for some comparison operators no warning shall be -  // reported even if the expressions are identical from a symbolic point of -  // view. Comparison between expressions, declared variables and literals -  // are treated differently. -  // -  // != and == between float literals that have the same value should NOT warn. -  // < > between float literals that have the same value SHOULD warn. -  // -  // != and == between the same float declaration should NOT warn. -  // < > between the same float declaration SHOULD warn. -  // -  // != and == between eq. expressions that evaluates into float -  //           should NOT warn. -  // < >       between eq. expressions that evaluates into float -  //           should NOT warn. -  // -  const Expr *LHS = B->getLHS()->IgnoreParenImpCasts(); -  const Expr *RHS = B->getRHS()->IgnoreParenImpCasts(); - -  const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS); -  const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS); -  const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS); -  const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS); -  if ((DeclRef1) && (DeclRef2)) { -    if ((DeclRef1->getType()->hasFloatingRepresentation()) && -        (DeclRef2->getType()->hasFloatingRepresentation())) { -      if (DeclRef1->getDecl() == DeclRef2->getDecl()) { -        if ((Op == BO_EQ) || (Op == BO_NE)) { -          return; -        } -      } -    } -  } else if ((FloatLit1) && (FloatLit2)) { -    if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) { -      if ((Op == BO_EQ) || (Op == BO_NE)) { -        return; -      } -    } -  } else if (LHS->getType()->hasFloatingRepresentation()) { -    // If any side of comparison operator still has floating-point -    // representation, then it's an expression. Don't warn. -    // Here only LHS is checked since RHS will be implicit casted to float. -    return; -  } else { -    // No special case with floating-point representation, report as usual. -  } - -  if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) { -    PathDiagnosticLocation ELoc = -        PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager()); -    StringRef Message; -    if (Op == BO_Cmp) -      Message = "comparison of identical expressions always evaluates to " -                "'equal'"; -    else if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE))) -      Message = "comparison of identical expressions always evaluates to true"; -    else -      Message = "comparison of identical expressions always evaluates to false"; -    BR.EmitBasicReport(AC->getDecl(), Checker, -                       "Compare of identical expressions", -                       categories::LogicError, Message, ELoc); -  } -} - -bool FindIdenticalExprVisitor::VisitConditionalOperator( -    const ConditionalOperator *C) { - -  // Check if expressions in conditional expression are identical -  // from a symbolic point of view. - -  if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(), -                      C->getFalseExpr(), true)) { -    PathDiagnosticLocation ELoc = -        PathDiagnosticLocation::createConditionalColonLoc( -            C, BR.getSourceManager()); - -    SourceRange Sr[2]; -    Sr[0] = C->getTrueExpr()->getSourceRange(); -    Sr[1] = C->getFalseExpr()->getSourceRange(); -    BR.EmitBasicReport( -        AC->getDecl(), Checker, -        "Identical expressions in conditional expression", -        categories::LogicError, -        "identical expressions on both sides of ':' in conditional expression", -        ELoc, Sr); -  } -  // We want to visit ALL nodes (expressions in conditional -  // expressions too) that contains conditional operators, -  // thus always return true to traverse ALL nodes. -  return true; -} - -/// Determines whether two statement trees are identical regarding -/// operators and symbols. -/// -/// Exceptions: expressions containing macros or functions with possible side -/// effects are never considered identical. -/// Limitations: (t + u) and (u + t) are not considered identical. -/// t*(u + t) and t*u + t*t are not considered identical. -/// -static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, -                            const Stmt *Stmt2, bool IgnoreSideEffects) { - -  if (!Stmt1 || !Stmt2) { -    return !Stmt1 && !Stmt2; -  } - -  // If Stmt1 & Stmt2 are of different class then they are not -  // identical statements. -  if (Stmt1->getStmtClass() != Stmt2->getStmtClass()) -    return false; - -  const Expr *Expr1 = dyn_cast<Expr>(Stmt1); -  const Expr *Expr2 = dyn_cast<Expr>(Stmt2); - -  if (Expr1 && Expr2) { -    // If Stmt1 has side effects then don't warn even if expressions -    // are identical. -    if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx)) -      return false; -    // If either expression comes from a macro then don't warn even if -    // the expressions are identical. -    if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID())) -      return false; - -    // If all children of two expressions are identical, return true. -    Expr::const_child_iterator I1 = Expr1->child_begin(); -    Expr::const_child_iterator I2 = Expr2->child_begin(); -    while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) { -      if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects)) -        return false; -      ++I1; -      ++I2; -    } -    // If there are different number of children in the statements, return -    // false. -    if (I1 != Expr1->child_end()) -      return false; -    if (I2 != Expr2->child_end()) -      return false; -  } - -  switch (Stmt1->getStmtClass()) { -  default: -    return false; -  case Stmt::CallExprClass: -  case Stmt::ArraySubscriptExprClass: -  case Stmt::OMPArraySectionExprClass: -  case Stmt::ImplicitCastExprClass: -  case Stmt::ParenExprClass: -  case Stmt::BreakStmtClass: -  case Stmt::ContinueStmtClass: -  case Stmt::NullStmtClass: -    return true; -  case Stmt::CStyleCastExprClass: { -    const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1); -    const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2); - -    return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten(); -  } -  case Stmt::ReturnStmtClass: { -    const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1); -    const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2); - -    return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(), -                           ReturnStmt2->getRetValue(), IgnoreSideEffects); -  } -  case Stmt::ForStmtClass: { -    const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1); -    const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2); - -    if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(), -                         IgnoreSideEffects)) -      return false; -    return true; -  } -  case Stmt::DoStmtClass: { -    const DoStmt *DStmt1 = cast<DoStmt>(Stmt1); -    const DoStmt *DStmt2 = cast<DoStmt>(Stmt2); - -    if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(), -                         IgnoreSideEffects)) -      return false; -    return true; -  } -  case Stmt::WhileStmtClass: { -    const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1); -    const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2); - -    if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(), -                         IgnoreSideEffects)) -      return false; -    return true; -  } -  case Stmt::IfStmtClass: { -    const IfStmt *IStmt1 = cast<IfStmt>(Stmt1); -    const IfStmt *IStmt2 = cast<IfStmt>(Stmt2); - -    if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(), -                         IgnoreSideEffects)) -      return false; -    if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(), -                         IgnoreSideEffects)) -      return false; -    return true; -  } -  case Stmt::CompoundStmtClass: { -    const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1); -    const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2); - -    if (CompStmt1->size() != CompStmt2->size()) -      return false; - -    CompoundStmt::const_body_iterator I1 = CompStmt1->body_begin(); -    CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin(); -    while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) { -      if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects)) -        return false; -      ++I1; -      ++I2; -    } - -    return true; -  } -  case Stmt::CompoundAssignOperatorClass: -  case Stmt::BinaryOperatorClass: { -    const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1); -    const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2); -    return BinOp1->getOpcode() == BinOp2->getOpcode(); -  } -  case Stmt::CharacterLiteralClass: { -    const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1); -    const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2); -    return CharLit1->getValue() == CharLit2->getValue(); -  } -  case Stmt::DeclRefExprClass: { -    const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1); -    const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2); -    return DeclRef1->getDecl() == DeclRef2->getDecl(); -  } -  case Stmt::IntegerLiteralClass: { -    const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1); -    const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2); - -    llvm::APInt I1 = IntLit1->getValue(); -    llvm::APInt I2 = IntLit2->getValue(); -    if (I1.getBitWidth() != I2.getBitWidth()) -      return false; -    return  I1 == I2; -  } -  case Stmt::FloatingLiteralClass: { -    const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1); -    const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2); -    return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue()); -  } -  case Stmt::StringLiteralClass: { -    const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1); -    const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2); -    return StringLit1->getBytes() == StringLit2->getBytes(); -  } -  case Stmt::MemberExprClass: { -    const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1); -    const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2); -    return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl(); -  } -  case Stmt::UnaryOperatorClass: { -    const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1); -    const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2); -    return UnaryOp1->getOpcode() == UnaryOp2->getOpcode(); -  } -  } -} - -//===----------------------------------------------------------------------===// -// FindIdenticalExprChecker -//===----------------------------------------------------------------------===// - -namespace { -class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> { -public: -  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, -                        BugReporter &BR) const { -    FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D)); -    Visitor.TraverseDecl(const_cast<Decl *>(D)); -  } -}; -} // end anonymous namespace - -void ento::registerIdenticalExprChecker(CheckerManager &Mgr) { -  Mgr.registerChecker<FindIdenticalExprChecker>(); -} - -bool ento::shouldRegisterIdenticalExprChecker(const LangOptions &LO) { -  return true; -}  | 
