llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.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

104 lines
3.4 KiB
C++

// UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This checker detects blocks that capture uninitialized values.
//
//===----------------------------------------------------------------------===//
#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/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace ento;
namespace {
class UndefCapturedBlockVarChecker
: public Checker< check::PostStmt<BlockExpr> > {
mutable llvm::OwningPtr<BugType> BT;
public:
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
};
} // end anonymous namespace
static const BlockDeclRefExpr *FindBlockDeclRefExpr(const Stmt *S,
const VarDecl *VD){
if (const BlockDeclRefExpr *BR = dyn_cast<BlockDeclRefExpr>(S))
if (BR->getDecl() == VD)
return BR;
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
I!=E; ++I)
if (const Stmt *child = *I) {
const BlockDeclRefExpr *BR = FindBlockDeclRefExpr(child, VD);
if (BR)
return BR;
}
return NULL;
}
void
UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
CheckerContext &C) const {
if (!BE->getBlockDecl()->hasCaptures())
return;
const ProgramState *state = C.getState();
const BlockDataRegion *R =
cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
E = R->referenced_vars_end();
for (; I != E; ++I) {
// This VarRegion is the region associated with the block; we need
// the one associated with the encompassing context.
const VarRegion *VR = *I;
const VarDecl *VD = VR->getDecl();
if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
continue;
// Get the VarRegion associated with VD in the local stack frame.
const LocationContext *LC = C.getPredecessor()->getLocationContext();
VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC);
SVal VRVal = state->getSVal(VR);
if (VRVal.isUndef())
if (ExplodedNode *N = C.generateSink()) {
if (!BT)
BT.reset(new BuiltinBug("uninitialized variable captured by block"));
// Generate a bug report.
llvm::SmallString<128> buf;
llvm::raw_svector_ostream os(buf);
os << "Variable '" << VD->getName()
<< "' is uninitialized when captured by block";
BugReport *R = new BugReport(*BT, os.str(), N);
if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
R->addRange(Ex->getSourceRange());
R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
// need location of block
C.EmitReport(R);
}
}
}
void ento::registerUndefCapturedBlockVarChecker(CheckerManager &mgr) {
mgr.registerChecker<UndefCapturedBlockVarChecker>();
}