blob: 1475a9e1cd3618c39d2e14f4ca558278c979b088 [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//
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000010// This defines DivZeroChecker, a builtin check in ExprEngine that performs
Zhongxing Xu9e56d232009-10-31 10:02:37 +000011// checks for division by zeros.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000015#include "ExprEngineInternalChecks.h"
Argyrios Kyrtzidis98cabba2010-12-22 18:51:49 +000016#include "clang/GR/BugReporter/BugType.h"
17#include "clang/GR/PathSensitive/CheckerVisitor.h"
Zhongxing Xu9e56d232009-10-31 10:02:37 +000018
19using namespace clang;
Argyrios Kyrtzidis5a4f98f2010-12-22 18:53:20 +000020using namespace GR;
Zhongxing Xu9e56d232009-10-31 10:02:37 +000021
Ted Kremenek36df58a2009-11-06 20:47:51 +000022namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000023class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
Ted Kremenek36df58a2009-11-06 20:47:51 +000024 BuiltinBug *BT;
25public:
26 DivZeroChecker() : BT(0) {}
27 static void *getTag();
28 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
29};
30} // end anonymous namespace
31
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000032void GR::RegisterDivZeroChecker(ExprEngine &Eng) {
Ted Kremenek36df58a2009-11-06 20:47:51 +000033 Eng.registerCheck(new DivZeroChecker());
34}
35
Zhongxing Xu9e56d232009-10-31 10:02:37 +000036void *DivZeroChecker::getTag() {
37 static int x;
38 return &x;
39}
40
41void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
42 const BinaryOperator *B) {
43 BinaryOperator::Opcode Op = B->getOpcode();
John McCall2de56d12010-08-25 11:45:40 +000044 if (Op != BO_Div &&
45 Op != BO_Rem &&
46 Op != BO_DivAssign &&
47 Op != BO_RemAssign)
Zhongxing Xu9e56d232009-10-31 10:02:37 +000048 return;
49
50 if (!B->getRHS()->getType()->isIntegerType() ||
51 !B->getRHS()->getType()->isScalarType())
52 return;
53
Ted Kremenek13976632010-02-08 16:18:51 +000054 SVal Denom = C.getState()->getSVal(B->getRHS());
Zhongxing Xu9e56d232009-10-31 10:02:37 +000055 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
56
57 // Divide-by-undefined handled in the generic checking for uses of
58 // undefined values.
59 if (!DV)
60 return;
61
62 // Check for divide by zero.
63 ConstraintManager &CM = C.getConstraintManager();
64 const GRState *stateNotZero, *stateZero;
Ted Kremenek28f47b92010-12-01 22:16:56 +000065 llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV);
Zhongxing Xu9e56d232009-10-31 10:02:37 +000066
67 if (stateZero && !stateNotZero) {
Ted Kremenekd048c6e2010-12-20 21:19:09 +000068 if (ExplodedNode *N = C.generateSink(stateZero)) {
Zhongxing Xu9e56d232009-10-31 10:02:37 +000069 if (!BT)
Ted Kremenek2c791bd2009-11-06 00:44:32 +000070 BT = new BuiltinBug("Division by zero");
Zhongxing Xu9e56d232009-10-31 10:02:37 +000071
72 EnhancedBugReport *R =
Benjamin Kramerd02e2322009-11-14 12:08:24 +000073 new EnhancedBugReport(*BT, BT->getDescription(), N);
Zhongxing Xu9e56d232009-10-31 10:02:37 +000074
75 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
76 bugreporter::GetDenomExpr(N));
77
78 C.EmitReport(R);
79 }
80 return;
81 }
82
83 // If we get here, then the denom should not be zero. We abandon the implicit
84 // zero denom case for now.
Ted Kremenek19d67b52009-11-23 22:22:01 +000085 C.addTransition(stateNotZero);
Zhongxing Xu9e56d232009-10-31 10:02:37 +000086}