blob: 9c2359f3b075cf3ca9522459526aaeae368303b8 [file] [log] [blame]
Zhongxing Xu9e56d232009-10-31 10:02:37 +00001//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
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// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
11// checks for division by zeros.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
16
17using namespace clang;
18
19void *DivZeroChecker::getTag() {
20 static int x;
21 return &x;
22}
23
24void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
25 const BinaryOperator *B) {
26 BinaryOperator::Opcode Op = B->getOpcode();
27 if (Op != BinaryOperator::Div &&
28 Op != BinaryOperator::Rem &&
29 Op != BinaryOperator::DivAssign &&
30 Op != BinaryOperator::RemAssign)
31 return;
32
33 if (!B->getRHS()->getType()->isIntegerType() ||
34 !B->getRHS()->getType()->isScalarType())
35 return;
36
37 SVal Denom = C.getState()->getSVal(B->getRHS());
38 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
39
40 // Divide-by-undefined handled in the generic checking for uses of
41 // undefined values.
42 if (!DV)
43 return;
44
45 // Check for divide by zero.
46 ConstraintManager &CM = C.getConstraintManager();
47 const GRState *stateNotZero, *stateZero;
48 llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
49
50 if (stateZero && !stateNotZero) {
51 if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
52 if (!BT)
53 BT = new BuiltinBug(0, "Division by zero");
54
55 EnhancedBugReport *R =
56 new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
57
58 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
59 bugreporter::GetDenomExpr(N));
60
61 C.EmitReport(R);
62 }
63 return;
64 }
65
66 // If we get here, then the denom should not be zero. We abandon the implicit
67 // zero denom case for now.
68 if (stateNotZero != C.getState())
69 C.addTransition(C.GenerateNode(B, stateNotZero));
70}