clang API Documentation
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 }