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