llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
Anna Zaks f86615ca5c Static Analyzer Diagnostics: Kill the addVisitorCreator(callbackTy, void*) API in favor of addVisitor(BugReporterVisitor*).
1) Create a header file to expose the predefined visitors. And move the parent(BugReporterVisitor) there as well.

2) Remove the registerXXXVisitor functions - the Visitor constructors/getters can be used now to create the object. One exception is registerVarDeclsLastStore(), which registers more then one visitor, so make it static member of FindLastStoreBRVisitor.

3) Modify all the checkers to use the new API.

llvm-svn: 138126
2011-08-19 22:33:38 +00:00

88 lines
2.8 KiB
C++

//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines UndefResultChecker, a builtin check in ExprEngine that
// performs checks for undefined results of non-assignment binary operators.
//
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
using namespace ento;
namespace {
class UndefResultChecker
: public Checker< check::PostStmt<BinaryOperator> > {
mutable llvm::OwningPtr<BugType> BT;
public:
void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
};
} // end anonymous namespace
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
CheckerContext &C) const {
const ProgramState *state = C.getState();
if (state->getSVal(B).isUndef()) {
// Generate an error node.
ExplodedNode *N = C.generateSink();
if (!N)
return;
if (!BT)
BT.reset(new BuiltinBug("Result of operation is garbage or undefined"));
llvm::SmallString<256> sbuf;
llvm::raw_svector_ostream OS(sbuf);
const Expr *Ex = NULL;
bool isLeft = true;
if (state->getSVal(B->getLHS()).isUndef()) {
Ex = B->getLHS()->IgnoreParenCasts();
isLeft = true;
}
else if (state->getSVal(B->getRHS()).isUndef()) {
Ex = B->getRHS()->IgnoreParenCasts();
isLeft = false;
}
if (Ex) {
OS << "The " << (isLeft ? "left" : "right")
<< " operand of '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
<< "' is a garbage value";
}
else {
// Neither operand was undefined, but the result is undefined.
OS << "The result of the '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
<< "' expression is undefined";
}
BugReport *report = new BugReport(*BT, OS.str(), N);
if (Ex) {
report->addRange(Ex->getSourceRange());
report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
}
else
report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B));
C.EmitReport(report);
}
}
void ento::registerUndefResultChecker(CheckerManager &mgr) {
mgr.registerChecker<UndefResultChecker>();
}