1ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//== TestAfterDivZeroChecker.cpp - Test after division by zero checker --*--==// 2ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 3ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// The LLVM Compiler Infrastructure 4ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 5ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// This file is distributed under the University of Illinois Open Source 6ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// License. See LICENSE.TXT for details. 7ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 8ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//===----------------------------------------------------------------------===// 9ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 10ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// This defines TestAfterDivZeroChecker, a builtin check that performs checks 11ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// for division by zero where the division occurs before comparison with zero. 12ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// 13ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//===----------------------------------------------------------------------===// 14ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 15ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "ClangSACheckers.h" 16ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "clang/StaticAnalyzer/Core/Checker.h" 18ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 19ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "llvm/ADT/FoldingSet.h" 21ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 22ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesusing namespace clang; 23ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesusing namespace ento; 24ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 25ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesnamespace { 26ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 27ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass ZeroState { 28ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesprivate: 29ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SymbolRef ZeroSymbol; 30ef8225444452a1486bd721f3285301fe84643b00Stephen Hines unsigned BlockID; 31ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const StackFrameContext *SFC; 32ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 33ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic: 34ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ZeroState(SymbolRef S, unsigned B, const StackFrameContext *SFC) 35ef8225444452a1486bd721f3285301fe84643b00Stephen Hines : ZeroSymbol(S), BlockID(B), SFC(SFC) {} 36ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 37ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const StackFrameContext *getStackFrameContext() const { return SFC; } 38ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 39ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool operator==(const ZeroState &X) const { 40ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return BlockID == X.BlockID && SFC == X.SFC && ZeroSymbol == X.ZeroSymbol; 41ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 42ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 43ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool operator<(const ZeroState &X) const { 44ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (BlockID != X.BlockID) 45ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return BlockID < X.BlockID; 46ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (SFC != X.SFC) 47ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return SFC < X.SFC; 48ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return ZeroSymbol < X.ZeroSymbol; 49ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 51ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void Profile(llvm::FoldingSetNodeID &ID) const { 52ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ID.AddInteger(BlockID); 53ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ID.AddPointer(SFC); 54ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ID.AddPointer(ZeroSymbol); 55ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 56ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}; 57ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 58ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass DivisionBRVisitor : public BugReporterVisitorImpl<DivisionBRVisitor> { 59ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesprivate: 60ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SymbolRef ZeroSymbol; 61ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const StackFrameContext *SFC; 62ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool Satisfied = false; 63ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 64ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic: 65ef8225444452a1486bd721f3285301fe84643b00Stephen Hines DivisionBRVisitor(SymbolRef ZeroSymbol, const StackFrameContext *SFC) 66ef8225444452a1486bd721f3285301fe84643b00Stephen Hines : ZeroSymbol(ZeroSymbol), SFC(SFC) {} 67ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 68ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void Profile(llvm::FoldingSetNodeID &ID) const override { 69ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ID.Add(ZeroSymbol); 70ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ID.Add(SFC); 71ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 72ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 73ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, 74ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const ExplodedNode *Pred, 75ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BugReporterContext &BRC, 76ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BugReport &BR) override; 77ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}; 78ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 79ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass TestAfterDivZeroChecker 80ef8225444452a1486bd721f3285301fe84643b00Stephen Hines : public Checker<check::PreStmt<BinaryOperator>, check::BranchCondition, 81ef8225444452a1486bd721f3285301fe84643b00Stephen Hines check::EndFunction> { 82ef8225444452a1486bd721f3285301fe84643b00Stephen Hines mutable std::unique_ptr<BuiltinBug> DivZeroBug; 83ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void reportBug(SVal Val, CheckerContext &C) const; 84ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 85ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic: 86ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 87ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const; 88ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void checkEndFunction(CheckerContext &C) const; 89ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void setDivZeroMap(SVal Var, CheckerContext &C) const; 90ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool hasDivZeroMap(SVal Var, const CheckerContext &C) const; 91ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool isZero(SVal S, CheckerContext &C) const; 92ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}; 93ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} // end anonymous namespace 94ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 95ef8225444452a1486bd721f3285301fe84643b00Stephen HinesREGISTER_SET_WITH_PROGRAMSTATE(DivZeroMap, ZeroState) 96ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 97ef8225444452a1486bd721f3285301fe84643b00Stephen HinesPathDiagnosticPiece *DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, 98ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const ExplodedNode *Pred, 99ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BugReporterContext &BRC, 100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BugReport &BR) { 101ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Satisfied) 102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return nullptr; 103ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 104ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const Expr *E = nullptr; 105ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 106ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>()) 107ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) { 108ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BinaryOperator::Opcode Op = BO->getOpcode(); 109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Op == BO_Div || Op == BO_Rem || Op == BO_DivAssign || 110ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Op == BO_RemAssign) { 111ef8225444452a1486bd721f3285301fe84643b00Stephen Hines E = BO->getRHS(); 112ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 113ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!E) 116ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return nullptr; 117ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 118ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ProgramStateRef State = Succ->getState(); 119ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SVal S = State->getSVal(E, Succ->getLocationContext()); 120ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (ZeroSymbol == S.getAsSymbol() && SFC == Succ->getStackFrame()) { 121ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Satisfied = true; 122ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 123ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Construct a new PathDiagnosticPiece. 124ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ProgramPoint P = Succ->getLocation(); 125ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PathDiagnosticLocation L = 126ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PathDiagnosticLocation::create(P, BRC.getSourceManager()); 127ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 128ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!L.isValid() || !L.asLocation().isValid()) 129ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return nullptr; 130ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 131ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return new PathDiagnosticEventPiece( 132ef8225444452a1486bd721f3285301fe84643b00Stephen Hines L, "Division with compared value made here"); 133ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 134ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 135ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return nullptr; 136ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 137ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 138ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesbool TestAfterDivZeroChecker::isZero(SVal S, CheckerContext &C) const { 139ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Optional<DefinedSVal> DSV = S.getAs<DefinedSVal>(); 140ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 141ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!DSV) 142ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return false; 143ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 144ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ConstraintManager &CM = C.getConstraintManager(); 145ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return !CM.assume(C.getState(), *DSV, true); 146ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 147ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 148ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid TestAfterDivZeroChecker::setDivZeroMap(SVal Var, CheckerContext &C) const { 149ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SymbolRef SR = Var.getAsSymbol(); 150ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!SR) 151ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return; 152ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 153ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ProgramStateRef State = C.getState(); 154ef8225444452a1486bd721f3285301fe84643b00Stephen Hines State = 155ef8225444452a1486bd721f3285301fe84643b00Stephen Hines State->add<DivZeroMap>(ZeroState(SR, C.getBlockID(), C.getStackFrame())); 156ef8225444452a1486bd721f3285301fe84643b00Stephen Hines C.addTransition(State); 157ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 158ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 159ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesbool TestAfterDivZeroChecker::hasDivZeroMap(SVal Var, 160ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const CheckerContext &C) const { 161ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SymbolRef SR = Var.getAsSymbol(); 162ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!SR) 163ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return false; 164ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 165ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ZeroState ZS(SR, C.getBlockID(), C.getStackFrame()); 166ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return C.getState()->contains<DivZeroMap>(ZS); 167ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 168ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 169ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const { 170ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (ExplodedNode *N = C.generateSink(C.getState())) { 171ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!DivZeroBug) 172ef8225444452a1486bd721f3285301fe84643b00Stephen Hines DivZeroBug.reset(new BuiltinBug(this, "Division by zero")); 173ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 174ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BugReport *R = 175ef8225444452a1486bd721f3285301fe84643b00Stephen Hines new BugReport(*DivZeroBug, "Value being compared against zero has " 176ef8225444452a1486bd721f3285301fe84643b00Stephen Hines "already been used for division", 177ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N); 178ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 179ef8225444452a1486bd721f3285301fe84643b00Stephen Hines R->addVisitor(new DivisionBRVisitor(Val.getAsSymbol(), C.getStackFrame())); 180ef8225444452a1486bd721f3285301fe84643b00Stephen Hines C.emitReport(R); 181ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 182ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 183ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 184ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid TestAfterDivZeroChecker::checkEndFunction(CheckerContext &C) const { 185ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ProgramStateRef State = C.getState(); 186ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 187ef8225444452a1486bd721f3285301fe84643b00Stephen Hines DivZeroMapTy DivZeroes = State->get<DivZeroMap>(); 188ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (DivZeroes.isEmpty()) 189ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return; 190ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 191ef8225444452a1486bd721f3285301fe84643b00Stephen Hines DivZeroMapTy::Factory &F = State->get_context<DivZeroMap>(); 192ef8225444452a1486bd721f3285301fe84643b00Stephen Hines for (llvm::ImmutableSet<ZeroState>::iterator I = DivZeroes.begin(), 193ef8225444452a1486bd721f3285301fe84643b00Stephen Hines E = DivZeroes.end(); 194ef8225444452a1486bd721f3285301fe84643b00Stephen Hines I != E; ++I) { 195ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ZeroState ZS = *I; 196ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (ZS.getStackFrameContext() == C.getStackFrame()) 197ef8225444452a1486bd721f3285301fe84643b00Stephen Hines DivZeroes = F.remove(DivZeroes, ZS); 198ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 199ef8225444452a1486bd721f3285301fe84643b00Stephen Hines C.addTransition(State->set<DivZeroMap>(DivZeroes)); 200ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 201ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 202ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid TestAfterDivZeroChecker::checkPreStmt(const BinaryOperator *B, 203ef8225444452a1486bd721f3285301fe84643b00Stephen Hines CheckerContext &C) const { 204ef8225444452a1486bd721f3285301fe84643b00Stephen Hines BinaryOperator::Opcode Op = B->getOpcode(); 205ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Op == BO_Div || Op == BO_Rem || Op == BO_DivAssign || 206ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Op == BO_RemAssign) { 207ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SVal S = C.getSVal(B->getRHS()); 208ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 209ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!isZero(S, C)) 210ef8225444452a1486bd721f3285301fe84643b00Stephen Hines setDivZeroMap(S, C); 211ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 212ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 213ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 214ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid TestAfterDivZeroChecker::checkBranchCondition(const Stmt *Condition, 215ef8225444452a1486bd721f3285301fe84643b00Stephen Hines CheckerContext &C) const { 216ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) { 217ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (B->isComparisonOp()) { 218ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(B->getRHS()); 219ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool LRHS = true; 220ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!IntLiteral) { 221ef8225444452a1486bd721f3285301fe84643b00Stephen Hines IntLiteral = dyn_cast<IntegerLiteral>(B->getLHS()); 222ef8225444452a1486bd721f3285301fe84643b00Stephen Hines LRHS = false; 223ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 224ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 225ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!IntLiteral || IntLiteral->getValue() != 0) 226ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return; 227ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 228ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SVal Val = C.getSVal(LRHS ? B->getLHS() : B->getRHS()); 229ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (hasDivZeroMap(Val, C)) 230ef8225444452a1486bd721f3285301fe84643b00Stephen Hines reportBug(Val, C); 231ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 232ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(Condition)) { 233ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (U->getOpcode() == UO_LNot) { 234ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SVal Val; 235ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (const ImplicitCastExpr *I = 236ef8225444452a1486bd721f3285301fe84643b00Stephen Hines dyn_cast<ImplicitCastExpr>(U->getSubExpr())) 237ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Val = C.getSVal(I->getSubExpr()); 238ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 239ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (hasDivZeroMap(Val, C)) 240ef8225444452a1486bd721f3285301fe84643b00Stephen Hines reportBug(Val, C); 241ef8225444452a1486bd721f3285301fe84643b00Stephen Hines else { 242ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Val = C.getSVal(U->getSubExpr()); 243ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (hasDivZeroMap(Val, C)) 244ef8225444452a1486bd721f3285301fe84643b00Stephen Hines reportBug(Val, C); 245ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 246ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 247ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } else if (const ImplicitCastExpr *IE = 248ef8225444452a1486bd721f3285301fe84643b00Stephen Hines dyn_cast<ImplicitCastExpr>(Condition)) { 249ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SVal Val = C.getSVal(IE->getSubExpr()); 250ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 251ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (hasDivZeroMap(Val, C)) 252ef8225444452a1486bd721f3285301fe84643b00Stephen Hines reportBug(Val, C); 253ef8225444452a1486bd721f3285301fe84643b00Stephen Hines else { 254ef8225444452a1486bd721f3285301fe84643b00Stephen Hines SVal Val = C.getSVal(Condition); 255ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 256ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (hasDivZeroMap(Val, C)) 257ef8225444452a1486bd721f3285301fe84643b00Stephen Hines reportBug(Val, C); 258ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 259ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 260ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 261ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 262ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid ento::registerTestAfterDivZeroChecker(CheckerManager &mgr) { 263ef8225444452a1486bd721f3285301fe84643b00Stephen Hines mgr.registerChecker<TestAfterDivZeroChecker>(); 264ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 265