Move CheckDivZero into its own files.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85651 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zhongxing Xu 2009-10-31 10:02:37 +00:00
Родитель 246a9ade3e
Коммит 9e56d2360b
3 изменённых файлов: 100 добавлений и 70 удалений

Просмотреть файл

@ -0,0 +1,28 @@
//== DivZeroChecker.h - Division by zero checker ----------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
// checks for division by zeros.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
namespace clang {
class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
BuiltinBug *BT;
public:
DivZeroChecker() : BT(0) {}
static void *getTag();
void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
};
}

Просмотреть файл

@ -0,0 +1,70 @@
//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
// checks for division by zeros.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
using namespace clang;
void *DivZeroChecker::getTag() {
static int x;
return &x;
}
void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
const BinaryOperator *B) {
BinaryOperator::Opcode Op = B->getOpcode();
if (Op != BinaryOperator::Div &&
Op != BinaryOperator::Rem &&
Op != BinaryOperator::DivAssign &&
Op != BinaryOperator::RemAssign)
return;
if (!B->getRHS()->getType()->isIntegerType() ||
!B->getRHS()->getType()->isScalarType())
return;
SVal Denom = C.getState()->getSVal(B->getRHS());
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
// Divide-by-undefined handled in the generic checking for uses of
// undefined values.
if (!DV)
return;
// Check for divide by zero.
ConstraintManager &CM = C.getConstraintManager();
const GRState *stateNotZero, *stateZero;
llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
if (stateZero && !stateNotZero) {
if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
if (!BT)
BT = new BuiltinBug(0, "Division by zero");
EnhancedBugReport *R =
new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
bugreporter::GetDenomExpr(N));
C.EmitReport(R);
}
return;
}
// If we get here, then the denom should not be zero. We abandon the implicit
// zero denom case for now.
if (stateNotZero != C.getState())
C.addTransition(C.GenerateNode(B, stateNotZero));
}

Просмотреть файл

@ -17,6 +17,7 @@
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/PathSensitive/Checkers/NullDerefChecker.h"
#include "clang/Analysis/PathSensitive/Checkers/UndefDerefChecker.h"
#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
@ -134,18 +135,6 @@ public:
}
};
class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
public:
DivZero(GRExprEngine* eng = 0)
: BuiltinBug(eng,"Division by zero") {}
void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode* N,
BuiltinBugReport *R) {
registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
}
};
class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
public:
UndefResult(GRExprEngine* eng)
@ -684,63 +673,6 @@ void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
}
}
class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
DivZero *BT;
public:
CheckDivZero() : BT(0) {}
~CheckDivZero() {}
static void *getTag() {
static int x;
return &x;
}
void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
};
void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
const BinaryOperator *B) {
BinaryOperator::Opcode Op = B->getOpcode();
if (Op != BinaryOperator::Div &&
Op != BinaryOperator::Rem &&
Op != BinaryOperator::DivAssign &&
Op != BinaryOperator::RemAssign)
return;
if (!B->getRHS()->getType()->isIntegerType() ||
!B->getRHS()->getType()->isScalarType())
return;
SVal Denom = C.getState()->getSVal(B->getRHS());
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
// Divide-by-undefined handled in the generic checking for uses of
// undefined values.
if (!DV)
return;
// Check for divide by zero.
ConstraintManager &CM = C.getConstraintManager();
const GRState *stateNotZero, *stateZero;
llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
if (stateZero && !stateNotZero) {
if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
if (!BT)
BT = new DivZero();
C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
}
return;
}
// If we get here, then the denom should not be zero. We abandon the implicit
// zero denom case for now.
if (stateNotZero != C.getState())
C.addTransition(C.GenerateNode(B, stateNotZero));
}
} // end clang namespace
//===----------------------------------------------------------------------===//
@ -772,7 +704,7 @@ void GRExprEngine::RegisterInternalChecks() {
registerCheck<CheckAttrNonNull>(new CheckAttrNonNull());
registerCheck<CheckUndefinedArg>(new CheckUndefinedArg());
registerCheck<CheckBadCall>(new CheckBadCall());
registerCheck<CheckDivZero>(new CheckDivZero());
registerCheck<DivZeroChecker>(new DivZeroChecker());
registerCheck<UndefDerefChecker>(new UndefDerefChecker());
registerCheck<NullDerefChecker>(new NullDerefChecker());
}