1 // UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- 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 checker detects blocks that capture uninitialized values.
12 //===----------------------------------------------------------------------===//
14 #include "GRExprEngineInternalChecks.h"
15 #include "clang/GR/PathSensitive/CheckerVisitor.h"
16 #include "clang/GR/PathSensitive/GRExprEngine.h"
17 #include "clang/GR/BugReporter/BugType.h"
18 #include "llvm/Support/raw_ostream.h"
20 using namespace clang
;
23 class UndefCapturedBlockVarChecker
24 : public CheckerVisitor
<UndefCapturedBlockVarChecker
> {
28 UndefCapturedBlockVarChecker() : BT(0) {}
29 static void *getTag() { static int tag
= 0; return &tag
; }
30 void PostVisitBlockExpr(CheckerContext
&C
, const BlockExpr
*BE
);
32 } // end anonymous namespace
34 void clang::RegisterUndefCapturedBlockVarChecker(GRExprEngine
&Eng
) {
35 Eng
.registerCheck(new UndefCapturedBlockVarChecker());
38 static const BlockDeclRefExpr
*FindBlockDeclRefExpr(const Stmt
*S
,
40 if (const BlockDeclRefExpr
*BR
= dyn_cast
<BlockDeclRefExpr
>(S
))
41 if (BR
->getDecl() == VD
)
44 for (Stmt::const_child_iterator I
= S
->child_begin(), E
= S
->child_end();
46 if (const Stmt
*child
= *I
) {
47 const BlockDeclRefExpr
*BR
= FindBlockDeclRefExpr(child
, VD
);
56 UndefCapturedBlockVarChecker::PostVisitBlockExpr(CheckerContext
&C
,
57 const BlockExpr
*BE
) {
58 if (!BE
->hasBlockDeclRefExprs())
61 const GRState
*state
= C
.getState();
62 const BlockDataRegion
*R
=
63 cast
<BlockDataRegion
>(state
->getSVal(BE
).getAsRegion());
65 BlockDataRegion::referenced_vars_iterator I
= R
->referenced_vars_begin(),
66 E
= R
->referenced_vars_end();
69 // This VarRegion is the region associated with the block; we need
70 // the one associated with the encompassing context.
71 const VarRegion
*VR
= *I
;
72 const VarDecl
*VD
= VR
->getDecl();
74 if (VD
->getAttr
<BlocksAttr
>() || !VD
->hasLocalStorage())
77 // Get the VarRegion associated with VD in the local stack frame.
78 const LocationContext
*LC
= C
.getPredecessor()->getLocationContext();
79 VR
= C
.getSValBuilder().getRegionManager().getVarRegion(VD
, LC
);
81 if (state
->getSVal(VR
).isUndef())
82 if (ExplodedNode
*N
= C
.generateSink()) {
84 BT
= new BuiltinBug("Captured block variable is uninitialized");
86 // Generate a bug report.
87 llvm::SmallString
<128> buf
;
88 llvm::raw_svector_ostream
os(buf
);
90 os
<< "Variable '" << VD
->getName() << "' is captured by block with "
93 EnhancedBugReport
*R
= new EnhancedBugReport(*BT
, os
.str(), N
);
94 if (const Expr
*Ex
= FindBlockDeclRefExpr(BE
->getBody(), VD
))
95 R
->addRange(Ex
->getSourceRange());
96 R
->addVisitorCreator(bugreporter::registerFindLastStore
, VR
);
97 // need location of block