1 //== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This defines DivZeroChecker, a builtin check in GRExprEngine that performs
11 // checks for division by zeros.
13 //===----------------------------------------------------------------------===//
15 #include "GRExprEngineInternalChecks.h"
16 #include "clang/GR/BugReporter/BugType.h"
17 #include "clang/GR/PathSensitive/CheckerVisitor.h"
19 using namespace clang
;
22 class DivZeroChecker
: public CheckerVisitor
<DivZeroChecker
> {
25 DivZeroChecker() : BT(0) {}
26 static void *getTag();
27 void PreVisitBinaryOperator(CheckerContext
&C
, const BinaryOperator
*B
);
29 } // end anonymous namespace
31 void clang::RegisterDivZeroChecker(GRExprEngine
&Eng
) {
32 Eng
.registerCheck(new DivZeroChecker());
35 void *DivZeroChecker::getTag() {
40 void DivZeroChecker::PreVisitBinaryOperator(CheckerContext
&C
,
41 const BinaryOperator
*B
) {
42 BinaryOperator::Opcode Op
= B
->getOpcode();
49 if (!B
->getRHS()->getType()->isIntegerType() ||
50 !B
->getRHS()->getType()->isScalarType())
53 SVal Denom
= C
.getState()->getSVal(B
->getRHS());
54 const DefinedSVal
*DV
= dyn_cast
<DefinedSVal
>(&Denom
);
56 // Divide-by-undefined handled in the generic checking for uses of
61 // Check for divide by zero.
62 ConstraintManager
&CM
= C
.getConstraintManager();
63 const GRState
*stateNotZero
, *stateZero
;
64 llvm::tie(stateNotZero
, stateZero
) = CM
.assumeDual(C
.getState(), *DV
);
66 if (stateZero
&& !stateNotZero
) {
67 if (ExplodedNode
*N
= C
.generateSink(stateZero
)) {
69 BT
= new BuiltinBug("Division by zero");
71 EnhancedBugReport
*R
=
72 new EnhancedBugReport(*BT
, BT
->getDescription(), N
);
74 R
->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue
,
75 bugreporter::GetDenomExpr(N
));
82 // If we get here, then the denom should not be zero. We abandon the implicit
83 // zero denom case for now.
84 C
.addTransition(stateNotZero
);