clang API Documentation

IdenticalExprChecker.cpp
Go to the documentation of this file.
00001 //== IdenticalExprChecker.cpp - Identical expression checker----------------==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 ///
00010 /// \file
00011 /// \brief This defines IdenticalExprChecker, a check that warns about
00012 /// unintended use of identical expressions.
00013 ///
00014 /// It checks for use of identical expressions with comparison operators and
00015 /// inside conditional expressions.
00016 ///
00017 //===----------------------------------------------------------------------===//
00018 
00019 #include "ClangSACheckers.h"
00020 #include "clang/AST/RecursiveASTVisitor.h"
00021 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
00022 #include "clang/StaticAnalyzer/Core/Checker.h"
00023 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
00024 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
00025 
00026 using namespace clang;
00027 using namespace ento;
00028 
00029 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
00030                             const Stmt *Stmt2, bool IgnoreSideEffects = false);
00031 //===----------------------------------------------------------------------===//
00032 // FindIdenticalExprVisitor - Identify nodes using identical expressions.
00033 //===----------------------------------------------------------------------===//
00034 
00035 namespace {
00036 class FindIdenticalExprVisitor
00037     : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
00038   BugReporter &BR;
00039   const CheckerBase *Checker;
00040   AnalysisDeclContext *AC;
00041 public:
00042   explicit FindIdenticalExprVisitor(BugReporter &B,
00043                                     const CheckerBase *Checker,
00044                                     AnalysisDeclContext *A)
00045       : BR(B), Checker(Checker), AC(A) {}
00046   // FindIdenticalExprVisitor only visits nodes
00047   // that are binary operators, if statements or
00048   // conditional operators.
00049   bool VisitBinaryOperator(const BinaryOperator *B);
00050   bool VisitIfStmt(const IfStmt *I);
00051   bool VisitConditionalOperator(const ConditionalOperator *C);
00052 
00053 private:
00054   void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise,
00055                            ArrayRef<SourceRange> Sr);
00056   void checkBitwiseOrLogicalOp(const BinaryOperator *B, bool CheckBitwise);
00057   void checkComparisonOp(const BinaryOperator *B);
00058 };
00059 } // end anonymous namespace
00060 
00061 void FindIdenticalExprVisitor::reportIdenticalExpr(const BinaryOperator *B,
00062                                                    bool CheckBitwise,
00063                                                    ArrayRef<SourceRange> Sr) {
00064   StringRef Message;
00065   if (CheckBitwise)
00066     Message = "identical expressions on both sides of bitwise operator";
00067   else
00068     Message = "identical expressions on both sides of logical operator";
00069 
00070   PathDiagnosticLocation ELoc =
00071       PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
00072   BR.EmitBasicReport(AC->getDecl(), Checker,
00073                      "Use of identical expressions",
00074                      categories::LogicError,
00075                      Message, ELoc, Sr);
00076 }
00077 
00078 void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B,
00079                                                        bool CheckBitwise) {
00080   SourceRange Sr[2];
00081 
00082   const Expr *LHS = B->getLHS();
00083   const Expr *RHS = B->getRHS();
00084 
00085   // Split operators as long as we still have operators to split on. We will
00086   // get called for every binary operator in an expression so there is no need
00087   // to check every one against each other here, just the right most one with
00088   // the others.
00089   while (const BinaryOperator *B2 = dyn_cast<BinaryOperator>(LHS)) {
00090     if (B->getOpcode() != B2->getOpcode())
00091       break;
00092     if (isIdenticalStmt(AC->getASTContext(), RHS, B2->getRHS())) {
00093       Sr[0] = RHS->getSourceRange();
00094       Sr[1] = B2->getRHS()->getSourceRange();
00095       reportIdenticalExpr(B, CheckBitwise, Sr);
00096     }
00097     LHS = B2->getLHS();
00098   }
00099   
00100   if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) {
00101     Sr[0] = RHS->getSourceRange();
00102     Sr[1] = LHS->getSourceRange();
00103     reportIdenticalExpr(B, CheckBitwise, Sr);
00104   }
00105 }
00106 
00107 bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
00108   const Stmt *Stmt1 = I->getThen();
00109   const Stmt *Stmt2 = I->getElse();
00110 
00111   // Check for identical conditions:
00112   //
00113   // if (b) {
00114   //   foo1();
00115   // } else if (b) {
00116   //   foo2();
00117   // }
00118   if (Stmt1 && Stmt2) {
00119     const Expr *Cond1 = I->getCond();
00120     const Stmt *Else = Stmt2;
00121     while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) {
00122       const Expr *Cond2 = I2->getCond();
00123       if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
00124         SourceRange Sr = Cond1->getSourceRange();
00125         PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC);
00126         BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
00127                            categories::LogicError,
00128                            "expression is identical to previous condition",
00129                            ELoc, Sr);
00130       }
00131       Else = I2->getElse();
00132     }
00133   }
00134 
00135   if (!Stmt1 || !Stmt2)
00136     return true;
00137 
00138   // Special handling for code like:
00139   //
00140   // if (b) {
00141   //   i = 1;
00142   // } else
00143   //   i = 1;
00144   if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) {
00145     if (CompStmt->size() == 1)
00146       Stmt1 = CompStmt->body_back();
00147   }
00148   if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) {
00149     if (CompStmt->size() == 1)
00150       Stmt2 = CompStmt->body_back();
00151   }
00152 
00153   if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) {
00154       PathDiagnosticLocation ELoc =
00155           PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC);
00156       BR.EmitBasicReport(AC->getDecl(), Checker,
00157                          "Identical branches",
00158                          categories::LogicError,
00159                          "true and false branches are identical", ELoc);
00160   }
00161   return true;
00162 }
00163 
00164 bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
00165   BinaryOperator::Opcode Op = B->getOpcode();
00166 
00167   if (BinaryOperator::isBitwiseOp(Op))
00168     checkBitwiseOrLogicalOp(B, true);
00169 
00170   if (BinaryOperator::isLogicalOp(Op))
00171     checkBitwiseOrLogicalOp(B, false);
00172 
00173   if (BinaryOperator::isComparisonOp(Op))
00174     checkComparisonOp(B);
00175 
00176   // We want to visit ALL nodes (subexpressions of binary comparison
00177   // expressions too) that contains comparison operators.
00178   // True is always returned to traverse ALL nodes.
00179   return true;
00180 }
00181 
00182 void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
00183   BinaryOperator::Opcode Op = B->getOpcode();
00184 
00185   //
00186   // Special case for floating-point representation.
00187   //
00188   // If expressions on both sides of comparison operator are of type float,
00189   // then for some comparison operators no warning shall be
00190   // reported even if the expressions are identical from a symbolic point of
00191   // view. Comparison between expressions, declared variables and literals
00192   // are treated differently.
00193   //
00194   // != and == between float literals that have the same value should NOT warn.
00195   // < > between float literals that have the same value SHOULD warn.
00196   //
00197   // != and == between the same float declaration should NOT warn.
00198   // < > between the same float declaration SHOULD warn.
00199   //
00200   // != and == between eq. expressions that evaluates into float
00201   //           should NOT warn.
00202   // < >       between eq. expressions that evaluates into float
00203   //           should NOT warn.
00204   //
00205   const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
00206   const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();
00207 
00208   const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
00209   const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
00210   const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
00211   const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
00212   if ((DeclRef1) && (DeclRef2)) {
00213     if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
00214         (DeclRef2->getType()->hasFloatingRepresentation())) {
00215       if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
00216         if ((Op == BO_EQ) || (Op == BO_NE)) {
00217           return;
00218         }
00219       }
00220     }
00221   } else if ((FloatLit1) && (FloatLit2)) {
00222     if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
00223       if ((Op == BO_EQ) || (Op == BO_NE)) {
00224         return;
00225       }
00226     }
00227   } else if (LHS->getType()->hasFloatingRepresentation()) {
00228     // If any side of comparison operator still has floating-point
00229     // representation, then it's an expression. Don't warn.
00230     // Here only LHS is checked since RHS will be implicit casted to float.
00231     return;
00232   } else {
00233     // No special case with floating-point representation, report as usual.
00234   }
00235 
00236   if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) {
00237     PathDiagnosticLocation ELoc =
00238         PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
00239     StringRef Message;
00240     if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
00241       Message = "comparison of identical expressions always evaluates to true";
00242     else
00243       Message = "comparison of identical expressions always evaluates to false";
00244     BR.EmitBasicReport(AC->getDecl(), Checker,
00245                        "Compare of identical expressions",
00246                        categories::LogicError, Message, ELoc);
00247   }
00248 }
00249 
00250 bool FindIdenticalExprVisitor::VisitConditionalOperator(
00251     const ConditionalOperator *C) {
00252 
00253   // Check if expressions in conditional expression are identical
00254   // from a symbolic point of view.
00255 
00256   if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(),
00257                       C->getFalseExpr(), true)) {
00258     PathDiagnosticLocation ELoc =
00259         PathDiagnosticLocation::createConditionalColonLoc(
00260             C, BR.getSourceManager());
00261 
00262     SourceRange Sr[2];
00263     Sr[0] = C->getTrueExpr()->getSourceRange();
00264     Sr[1] = C->getFalseExpr()->getSourceRange();
00265     BR.EmitBasicReport(
00266         AC->getDecl(), Checker,
00267         "Identical expressions in conditional expression",
00268         categories::LogicError,
00269         "identical expressions on both sides of ':' in conditional expression",
00270         ELoc, Sr);
00271   }
00272   // We want to visit ALL nodes (expressions in conditional
00273   // expressions too) that contains conditional operators,
00274   // thus always return true to traverse ALL nodes.
00275   return true;
00276 }
00277 
00278 /// \brief Determines whether two statement trees are identical regarding
00279 /// operators and symbols.
00280 ///
00281 /// Exceptions: expressions containing macros or functions with possible side
00282 /// effects are never considered identical.
00283 /// Limitations: (t + u) and (u + t) are not considered identical.
00284 /// t*(u + t) and t*u + t*t are not considered identical.
00285 ///
00286 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
00287                             const Stmt *Stmt2, bool IgnoreSideEffects) {
00288 
00289   if (!Stmt1 || !Stmt2) {
00290     if (!Stmt1 && !Stmt2)
00291       return true;
00292     return false;
00293   }
00294 
00295   // If Stmt1 & Stmt2 are of different class then they are not
00296   // identical statements.
00297   if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
00298     return false;
00299 
00300   const Expr *Expr1 = dyn_cast<Expr>(Stmt1);
00301   const Expr *Expr2 = dyn_cast<Expr>(Stmt2);
00302 
00303   if (Expr1 && Expr2) {
00304     // If Stmt1 has side effects then don't warn even if expressions
00305     // are identical.
00306     if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx))
00307       return false;
00308     // If either expression comes from a macro then don't warn even if
00309     // the expressions are identical.
00310     if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
00311       return false;
00312 
00313     // If all children of two expressions are identical, return true.
00314     Expr::const_child_iterator I1 = Expr1->child_begin();
00315     Expr::const_child_iterator I2 = Expr2->child_begin();
00316     while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
00317       if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
00318         return false;
00319       ++I1;
00320       ++I2;
00321     }
00322     // If there are different number of children in the statements, return
00323     // false.
00324     if (I1 != Expr1->child_end())
00325       return false;
00326     if (I2 != Expr2->child_end())
00327       return false;
00328   }
00329 
00330   switch (Stmt1->getStmtClass()) {
00331   default:
00332     return false;
00333   case Stmt::CallExprClass:
00334   case Stmt::ArraySubscriptExprClass:
00335   case Stmt::ImplicitCastExprClass:
00336   case Stmt::ParenExprClass:
00337   case Stmt::BreakStmtClass:
00338   case Stmt::ContinueStmtClass:
00339   case Stmt::NullStmtClass:
00340     return true;
00341   case Stmt::CStyleCastExprClass: {
00342     const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1);
00343     const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2);
00344 
00345     return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
00346   }
00347   case Stmt::ReturnStmtClass: {
00348     const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
00349     const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
00350 
00351     return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(),
00352                            ReturnStmt2->getRetValue(), IgnoreSideEffects);
00353   }
00354   case Stmt::ForStmtClass: {
00355     const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1);
00356     const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2);
00357 
00358     if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(),
00359                          IgnoreSideEffects))
00360       return false;
00361     if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(),
00362                          IgnoreSideEffects))
00363       return false;
00364     if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(),
00365                          IgnoreSideEffects))
00366       return false;
00367     if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(),
00368                          IgnoreSideEffects))
00369       return false;
00370     return true;
00371   }
00372   case Stmt::DoStmtClass: {
00373     const DoStmt *DStmt1 = cast<DoStmt>(Stmt1);
00374     const DoStmt *DStmt2 = cast<DoStmt>(Stmt2);
00375 
00376     if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(),
00377                          IgnoreSideEffects))
00378       return false;
00379     if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(),
00380                          IgnoreSideEffects))
00381       return false;
00382     return true;
00383   }
00384   case Stmt::WhileStmtClass: {
00385     const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1);
00386     const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2);
00387 
00388     if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(),
00389                          IgnoreSideEffects))
00390       return false;
00391     if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(),
00392                          IgnoreSideEffects))
00393       return false;
00394     return true;
00395   }
00396   case Stmt::IfStmtClass: {
00397     const IfStmt *IStmt1 = cast<IfStmt>(Stmt1);
00398     const IfStmt *IStmt2 = cast<IfStmt>(Stmt2);
00399 
00400     if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(),
00401                          IgnoreSideEffects))
00402       return false;
00403     if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(),
00404                          IgnoreSideEffects))
00405       return false;
00406     if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(),
00407                          IgnoreSideEffects))
00408       return false;
00409     return true;
00410   }
00411   case Stmt::CompoundStmtClass: {
00412     const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1);
00413     const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2);
00414 
00415     if (CompStmt1->size() != CompStmt2->size())
00416       return false;
00417 
00418     CompoundStmt::const_body_iterator I1 = CompStmt1->body_begin();
00419     CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin();
00420     while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) {
00421       if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
00422         return false;
00423       ++I1;
00424       ++I2;
00425     }
00426 
00427     return true;
00428   }
00429   case Stmt::CompoundAssignOperatorClass:
00430   case Stmt::BinaryOperatorClass: {
00431     const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1);
00432     const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2);
00433     return BinOp1->getOpcode() == BinOp2->getOpcode();
00434   }
00435   case Stmt::CharacterLiteralClass: {
00436     const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1);
00437     const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2);
00438     return CharLit1->getValue() == CharLit2->getValue();
00439   }
00440   case Stmt::DeclRefExprClass: {
00441     const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1);
00442     const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2);
00443     return DeclRef1->getDecl() == DeclRef2->getDecl();
00444   }
00445   case Stmt::IntegerLiteralClass: {
00446     const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1);
00447     const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2);
00448 
00449     llvm::APInt I1 = IntLit1->getValue();
00450     llvm::APInt I2 = IntLit2->getValue();
00451     if (I1.getBitWidth() != I2.getBitWidth())
00452       return false;
00453     return  I1 == I2;
00454   }
00455   case Stmt::FloatingLiteralClass: {
00456     const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1);
00457     const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2);
00458     return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
00459   }
00460   case Stmt::StringLiteralClass: {
00461     const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1);
00462     const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2);
00463     return StringLit1->getBytes() == StringLit2->getBytes();
00464   }
00465   case Stmt::MemberExprClass: {
00466     const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1);
00467     const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2);
00468     return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
00469   }
00470   case Stmt::UnaryOperatorClass: {
00471     const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1);
00472     const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2);
00473     return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
00474   }
00475   }
00476 }
00477 
00478 //===----------------------------------------------------------------------===//
00479 // FindIdenticalExprChecker
00480 //===----------------------------------------------------------------------===//
00481 
00482 namespace {
00483 class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
00484 public:
00485   void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
00486                         BugReporter &BR) const {
00487     FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
00488     Visitor.TraverseDecl(const_cast<Decl *>(D));
00489   }
00490 };
00491 } // end anonymous namespace
00492 
00493 void ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
00494   Mgr.registerChecker<FindIdenticalExprChecker>();
00495 }