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 ExprEngine that performs
11 // checks for division by zeros.
13 //===----------------------------------------------------------------------===//
15 #include "ExprEngineInternalChecks.h"
16 #include "clang/StaticAnalyzer/BugReporter/BugType.h"
17 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
19 using namespace clang
;
23 class DivZeroChecker
: public CheckerVisitor
<DivZeroChecker
> {
26 DivZeroChecker() : BT(0) {}
27 static void *getTag();
28 void PreVisitBinaryOperator(CheckerContext
&C
, const BinaryOperator
*B
);
30 } // end anonymous namespace
32 void ento::RegisterDivZeroChecker(ExprEngine
&Eng
) {
33 Eng
.registerCheck(new DivZeroChecker());
36 void *DivZeroChecker::getTag() {
41 void DivZeroChecker::PreVisitBinaryOperator(CheckerContext
&C
,
42 const BinaryOperator
*B
) {
43 BinaryOperator::Opcode Op
= B
->getOpcode();
50 if (!B
->getRHS()->getType()->isIntegerType() ||
51 !B
->getRHS()->getType()->isScalarType())
54 SVal Denom
= C
.getState()->getSVal(B
->getRHS());
55 const DefinedSVal
*DV
= dyn_cast
<DefinedSVal
>(&Denom
);
57 // Divide-by-undefined handled in the generic checking for uses of
62 // Check for divide by zero.
63 ConstraintManager
&CM
= C
.getConstraintManager();
64 const GRState
*stateNotZero
, *stateZero
;
65 llvm::tie(stateNotZero
, stateZero
) = CM
.assumeDual(C
.getState(), *DV
);
67 if (stateZero
&& !stateNotZero
) {
68 if (ExplodedNode
*N
= C
.generateSink(stateZero
)) {
70 BT
= new BuiltinBug("Division by zero");
72 EnhancedBugReport
*R
=
73 new EnhancedBugReport(*BT
, BT
->getDescription(), N
);
75 R
->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue
,
76 bugreporter::GetDenomExpr(N
));
83 // If we get here, then the denom should not be zero. We abandon the implicit
84 // zero denom case for now.
85 C
.addTransition(stateNotZero
);