1 //== IdenticalExprChecker.cpp - Identical expression checker----------------==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief This defines IdenticalExprChecker, a check that warns about 12 /// unintended use of identical expressions. 13 /// 14 /// It checks for use of identical expressions with comparison operators and 15 /// inside conditional expressions. 16 /// 17 //===----------------------------------------------------------------------===// 18 19 #include "ClangSACheckers.h" 20 #include "clang/AST/RecursiveASTVisitor.h" 21 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 22 #include "clang/StaticAnalyzer/Core/Checker.h" 23 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 24 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 25 26 using namespace clang; 27 using namespace ento; 28 29 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, 30 const Stmt *Stmt2, bool IgnoreSideEffects = false); 31 //===----------------------------------------------------------------------===// 32 // FindIdenticalExprVisitor - Identify nodes using identical expressions. 33 //===----------------------------------------------------------------------===// 34 35 namespace { 36 class FindIdenticalExprVisitor 37 : public RecursiveASTVisitor<FindIdenticalExprVisitor> { 38 BugReporter &BR; 39 const CheckerBase *Checker; 40 AnalysisDeclContext *AC; 41 public: 42 explicit FindIdenticalExprVisitor(BugReporter &B, 43 const CheckerBase *Checker, 44 AnalysisDeclContext *A) 45 : BR(B), Checker(Checker), AC(A) {} 46 // FindIdenticalExprVisitor only visits nodes 47 // that are binary operators, if statements or 48 // conditional operators. 49 bool VisitBinaryOperator(const BinaryOperator *B); 50 bool VisitIfStmt(const IfStmt *I); 51 bool VisitConditionalOperator(const ConditionalOperator *C); 52 53 private: 54 void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise, 55 ArrayRef<SourceRange> Sr); 56 void checkBitwiseOrLogicalOp(const BinaryOperator *B, bool CheckBitwise); 57 void checkComparisonOp(const BinaryOperator *B); 58 }; 59 } // end anonymous namespace 60 61 void FindIdenticalExprVisitor::reportIdenticalExpr(const BinaryOperator *B, 62 bool CheckBitwise, 63 ArrayRef<SourceRange> Sr) { 64 StringRef Message; 65 if (CheckBitwise) 66 Message = "identical expressions on both sides of bitwise operator"; 67 else 68 Message = "identical expressions on both sides of logical operator"; 69 70 PathDiagnosticLocation ELoc = 71 PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager()); 72 BR.EmitBasicReport(AC->getDecl(), Checker, 73 "Use of identical expressions", 74 categories::LogicError, 75 Message, ELoc, Sr); 76 } 77 78 void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B, 79 bool CheckBitwise) { 80 SourceRange Sr[2]; 81 82 const Expr *LHS = B->getLHS(); 83 const Expr *RHS = B->getRHS(); 84 85 // Split operators as long as we still have operators to split on. We will 86 // get called for every binary operator in an expression so there is no need 87 // to check every one against each other here, just the right most one with 88 // the others. 89 while (const BinaryOperator *B2 = dyn_cast<BinaryOperator>(LHS)) { 90 if (B->getOpcode() != B2->getOpcode()) 91 break; 92 if (isIdenticalStmt(AC->getASTContext(), RHS, B2->getRHS())) { 93 Sr[0] = RHS->getSourceRange(); 94 Sr[1] = B2->getRHS()->getSourceRange(); 95 reportIdenticalExpr(B, CheckBitwise, Sr); 96 } 97 LHS = B2->getLHS(); 98 } 99 100 if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) { 101 Sr[0] = RHS->getSourceRange(); 102 Sr[1] = LHS->getSourceRange(); 103 reportIdenticalExpr(B, CheckBitwise, Sr); 104 } 105 } 106 107 bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { 108 const Stmt *Stmt1 = I->getThen(); 109 const Stmt *Stmt2 = I->getElse(); 110 111 // Check for identical inner condition: 112 // 113 // if (x<10) { 114 // if (x<10) { 115 // .. 116 if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(Stmt1)) { 117 if (!CS->body_empty()) { 118 const IfStmt *InnerIf = dyn_cast<IfStmt>(*CS->body_begin()); 119 if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*ignoreSideEffects=*/ false)) { 120 PathDiagnosticLocation ELoc(InnerIf->getCond(), BR.getSourceManager(), AC); 121 BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions", 122 categories::LogicError, 123 "conditions of the inner and outer statements are identical", 124 ELoc); 125 } 126 } 127 } 128 129 // Check for identical conditions: 130 // 131 // if (b) { 132 // foo1(); 133 // } else if (b) { 134 // foo2(); 135 // } 136 if (Stmt1 && Stmt2) { 137 const Expr *Cond1 = I->getCond(); 138 const Stmt *Else = Stmt2; 139 while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) { 140 const Expr *Cond2 = I2->getCond(); 141 if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) { 142 SourceRange Sr = Cond1->getSourceRange(); 143 PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC); 144 BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions", 145 categories::LogicError, 146 "expression is identical to previous condition", 147 ELoc, Sr); 148 } 149 Else = I2->getElse(); 150 } 151 } 152 153 if (!Stmt1 || !Stmt2) 154 return true; 155 156 // Special handling for code like: 157 // 158 // if (b) { 159 // i = 1; 160 // } else 161 // i = 1; 162 if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) { 163 if (CompStmt->size() == 1) 164 Stmt1 = CompStmt->body_back(); 165 } 166 if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) { 167 if (CompStmt->size() == 1) 168 Stmt2 = CompStmt->body_back(); 169 } 170 171 if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) { 172 PathDiagnosticLocation ELoc = 173 PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC); 174 BR.EmitBasicReport(AC->getDecl(), Checker, 175 "Identical branches", 176 categories::LogicError, 177 "true and false branches are identical", ELoc); 178 } 179 return true; 180 } 181 182 bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) { 183 BinaryOperator::Opcode Op = B->getOpcode(); 184 185 if (BinaryOperator::isBitwiseOp(Op)) 186 checkBitwiseOrLogicalOp(B, true); 187 188 if (BinaryOperator::isLogicalOp(Op)) 189 checkBitwiseOrLogicalOp(B, false); 190 191 if (BinaryOperator::isComparisonOp(Op)) 192 checkComparisonOp(B); 193 194 // We want to visit ALL nodes (subexpressions of binary comparison 195 // expressions too) that contains comparison operators. 196 // True is always returned to traverse ALL nodes. 197 return true; 198 } 199 200 void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) { 201 BinaryOperator::Opcode Op = B->getOpcode(); 202 203 // 204 // Special case for floating-point representation. 205 // 206 // If expressions on both sides of comparison operator are of type float, 207 // then for some comparison operators no warning shall be 208 // reported even if the expressions are identical from a symbolic point of 209 // view. Comparison between expressions, declared variables and literals 210 // are treated differently. 211 // 212 // != and == between float literals that have the same value should NOT warn. 213 // < > between float literals that have the same value SHOULD warn. 214 // 215 // != and == between the same float declaration should NOT warn. 216 // < > between the same float declaration SHOULD warn. 217 // 218 // != and == between eq. expressions that evaluates into float 219 // should NOT warn. 220 // < > between eq. expressions that evaluates into float 221 // should NOT warn. 222 // 223 const Expr *LHS = B->getLHS()->IgnoreParenImpCasts(); 224 const Expr *RHS = B->getRHS()->IgnoreParenImpCasts(); 225 226 const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS); 227 const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS); 228 const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS); 229 const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS); 230 if ((DeclRef1) && (DeclRef2)) { 231 if ((DeclRef1->getType()->hasFloatingRepresentation()) && 232 (DeclRef2->getType()->hasFloatingRepresentation())) { 233 if (DeclRef1->getDecl() == DeclRef2->getDecl()) { 234 if ((Op == BO_EQ) || (Op == BO_NE)) { 235 return; 236 } 237 } 238 } 239 } else if ((FloatLit1) && (FloatLit2)) { 240 if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) { 241 if ((Op == BO_EQ) || (Op == BO_NE)) { 242 return; 243 } 244 } 245 } else if (LHS->getType()->hasFloatingRepresentation()) { 246 // If any side of comparison operator still has floating-point 247 // representation, then it's an expression. Don't warn. 248 // Here only LHS is checked since RHS will be implicit casted to float. 249 return; 250 } else { 251 // No special case with floating-point representation, report as usual. 252 } 253 254 if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) { 255 PathDiagnosticLocation ELoc = 256 PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager()); 257 StringRef Message; 258 if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE))) 259 Message = "comparison of identical expressions always evaluates to true"; 260 else 261 Message = "comparison of identical expressions always evaluates to false"; 262 BR.EmitBasicReport(AC->getDecl(), Checker, 263 "Compare of identical expressions", 264 categories::LogicError, Message, ELoc); 265 } 266 } 267 268 bool FindIdenticalExprVisitor::VisitConditionalOperator( 269 const ConditionalOperator *C) { 270 271 // Check if expressions in conditional expression are identical 272 // from a symbolic point of view. 273 274 if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(), 275 C->getFalseExpr(), true)) { 276 PathDiagnosticLocation ELoc = 277 PathDiagnosticLocation::createConditionalColonLoc( 278 C, BR.getSourceManager()); 279 280 SourceRange Sr[2]; 281 Sr[0] = C->getTrueExpr()->getSourceRange(); 282 Sr[1] = C->getFalseExpr()->getSourceRange(); 283 BR.EmitBasicReport( 284 AC->getDecl(), Checker, 285 "Identical expressions in conditional expression", 286 categories::LogicError, 287 "identical expressions on both sides of ':' in conditional expression", 288 ELoc, Sr); 289 } 290 // We want to visit ALL nodes (expressions in conditional 291 // expressions too) that contains conditional operators, 292 // thus always return true to traverse ALL nodes. 293 return true; 294 } 295 296 /// \brief Determines whether two statement trees are identical regarding 297 /// operators and symbols. 298 /// 299 /// Exceptions: expressions containing macros or functions with possible side 300 /// effects are never considered identical. 301 /// Limitations: (t + u) and (u + t) are not considered identical. 302 /// t*(u + t) and t*u + t*t are not considered identical. 303 /// 304 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, 305 const Stmt *Stmt2, bool IgnoreSideEffects) { 306 307 if (!Stmt1 || !Stmt2) { 308 if (!Stmt1 && !Stmt2) 309 return true; 310 return false; 311 } 312 313 // If Stmt1 & Stmt2 are of different class then they are not 314 // identical statements. 315 if (Stmt1->getStmtClass() != Stmt2->getStmtClass()) 316 return false; 317 318 const Expr *Expr1 = dyn_cast<Expr>(Stmt1); 319 const Expr *Expr2 = dyn_cast<Expr>(Stmt2); 320 321 if (Expr1 && Expr2) { 322 // If Stmt1 has side effects then don't warn even if expressions 323 // are identical. 324 if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx)) 325 return false; 326 // If either expression comes from a macro then don't warn even if 327 // the expressions are identical. 328 if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID())) 329 return false; 330 331 // If all children of two expressions are identical, return true. 332 Expr::const_child_iterator I1 = Expr1->child_begin(); 333 Expr::const_child_iterator I2 = Expr2->child_begin(); 334 while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) { 335 if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects)) 336 return false; 337 ++I1; 338 ++I2; 339 } 340 // If there are different number of children in the statements, return 341 // false. 342 if (I1 != Expr1->child_end()) 343 return false; 344 if (I2 != Expr2->child_end()) 345 return false; 346 } 347 348 switch (Stmt1->getStmtClass()) { 349 default: 350 return false; 351 case Stmt::CallExprClass: 352 case Stmt::ArraySubscriptExprClass: 353 case Stmt::ImplicitCastExprClass: 354 case Stmt::ParenExprClass: 355 case Stmt::BreakStmtClass: 356 case Stmt::ContinueStmtClass: 357 case Stmt::NullStmtClass: 358 return true; 359 case Stmt::CStyleCastExprClass: { 360 const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1); 361 const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2); 362 363 return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten(); 364 } 365 case Stmt::ReturnStmtClass: { 366 const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1); 367 const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2); 368 369 return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(), 370 ReturnStmt2->getRetValue(), IgnoreSideEffects); 371 } 372 case Stmt::ForStmtClass: { 373 const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1); 374 const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2); 375 376 if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(), 377 IgnoreSideEffects)) 378 return false; 379 if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(), 380 IgnoreSideEffects)) 381 return false; 382 if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(), 383 IgnoreSideEffects)) 384 return false; 385 if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(), 386 IgnoreSideEffects)) 387 return false; 388 return true; 389 } 390 case Stmt::DoStmtClass: { 391 const DoStmt *DStmt1 = cast<DoStmt>(Stmt1); 392 const DoStmt *DStmt2 = cast<DoStmt>(Stmt2); 393 394 if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(), 395 IgnoreSideEffects)) 396 return false; 397 if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(), 398 IgnoreSideEffects)) 399 return false; 400 return true; 401 } 402 case Stmt::WhileStmtClass: { 403 const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1); 404 const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2); 405 406 if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(), 407 IgnoreSideEffects)) 408 return false; 409 if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(), 410 IgnoreSideEffects)) 411 return false; 412 return true; 413 } 414 case Stmt::IfStmtClass: { 415 const IfStmt *IStmt1 = cast<IfStmt>(Stmt1); 416 const IfStmt *IStmt2 = cast<IfStmt>(Stmt2); 417 418 if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(), 419 IgnoreSideEffects)) 420 return false; 421 if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(), 422 IgnoreSideEffects)) 423 return false; 424 if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(), 425 IgnoreSideEffects)) 426 return false; 427 return true; 428 } 429 case Stmt::CompoundStmtClass: { 430 const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1); 431 const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2); 432 433 if (CompStmt1->size() != CompStmt2->size()) 434 return false; 435 436 CompoundStmt::const_body_iterator I1 = CompStmt1->body_begin(); 437 CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin(); 438 while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) { 439 if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects)) 440 return false; 441 ++I1; 442 ++I2; 443 } 444 445 return true; 446 } 447 case Stmt::CompoundAssignOperatorClass: 448 case Stmt::BinaryOperatorClass: { 449 const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1); 450 const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2); 451 return BinOp1->getOpcode() == BinOp2->getOpcode(); 452 } 453 case Stmt::CharacterLiteralClass: { 454 const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1); 455 const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2); 456 return CharLit1->getValue() == CharLit2->getValue(); 457 } 458 case Stmt::DeclRefExprClass: { 459 const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1); 460 const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2); 461 return DeclRef1->getDecl() == DeclRef2->getDecl(); 462 } 463 case Stmt::IntegerLiteralClass: { 464 const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1); 465 const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2); 466 467 llvm::APInt I1 = IntLit1->getValue(); 468 llvm::APInt I2 = IntLit2->getValue(); 469 if (I1.getBitWidth() != I2.getBitWidth()) 470 return false; 471 return I1 == I2; 472 } 473 case Stmt::FloatingLiteralClass: { 474 const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1); 475 const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2); 476 return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue()); 477 } 478 case Stmt::StringLiteralClass: { 479 const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1); 480 const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2); 481 return StringLit1->getBytes() == StringLit2->getBytes(); 482 } 483 case Stmt::MemberExprClass: { 484 const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1); 485 const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2); 486 return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl(); 487 } 488 case Stmt::UnaryOperatorClass: { 489 const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1); 490 const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2); 491 return UnaryOp1->getOpcode() == UnaryOp2->getOpcode(); 492 } 493 } 494 } 495 496 //===----------------------------------------------------------------------===// 497 // FindIdenticalExprChecker 498 //===----------------------------------------------------------------------===// 499 500 namespace { 501 class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> { 502 public: 503 void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, 504 BugReporter &BR) const { 505 FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D)); 506 Visitor.TraverseDecl(const_cast<Decl *>(D)); 507 } 508 }; 509 } // end anonymous namespace 510 511 void ento::registerIdenticalExprChecker(CheckerManager &Mgr) { 512 Mgr.registerChecker<FindIdenticalExprChecker>(); 513 } 514