1*67e74705SXin Li //==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file implements uninitialized values analysis for source-level CFGs.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "clang/AST/ASTContext.h"
15*67e74705SXin Li #include "clang/AST/Attr.h"
16*67e74705SXin Li #include "clang/AST/Decl.h"
17*67e74705SXin Li #include "clang/AST/DeclCXX.h"
18*67e74705SXin Li #include "clang/AST/StmtVisitor.h"
19*67e74705SXin Li #include "clang/Analysis/Analyses/PostOrderCFGView.h"
20*67e74705SXin Li #include "clang/Analysis/Analyses/UninitializedValues.h"
21*67e74705SXin Li #include "clang/Analysis/AnalysisContext.h"
22*67e74705SXin Li #include "clang/Analysis/CFG.h"
23*67e74705SXin Li #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
24*67e74705SXin Li #include "llvm/ADT/DenseMap.h"
25*67e74705SXin Li #include "llvm/ADT/Optional.h"
26*67e74705SXin Li #include "llvm/ADT/PackedVector.h"
27*67e74705SXin Li #include "llvm/ADT/SmallBitVector.h"
28*67e74705SXin Li #include "llvm/ADT/SmallVector.h"
29*67e74705SXin Li #include "llvm/Support/SaveAndRestore.h"
30*67e74705SXin Li #include <utility>
31*67e74705SXin Li
32*67e74705SXin Li using namespace clang;
33*67e74705SXin Li
34*67e74705SXin Li #define DEBUG_LOGGING 0
35*67e74705SXin Li
isTrackedVar(const VarDecl * vd,const DeclContext * dc)36*67e74705SXin Li static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
37*67e74705SXin Li if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
38*67e74705SXin Li !vd->isExceptionVariable() && !vd->isInitCapture() &&
39*67e74705SXin Li !vd->isImplicit() && vd->getDeclContext() == dc) {
40*67e74705SXin Li QualType ty = vd->getType();
41*67e74705SXin Li return ty->isScalarType() || ty->isVectorType() || ty->isRecordType();
42*67e74705SXin Li }
43*67e74705SXin Li return false;
44*67e74705SXin Li }
45*67e74705SXin Li
46*67e74705SXin Li //------------------------------------------------------------------------====//
47*67e74705SXin Li // DeclToIndex: a mapping from Decls we track to value indices.
48*67e74705SXin Li //====------------------------------------------------------------------------//
49*67e74705SXin Li
50*67e74705SXin Li namespace {
51*67e74705SXin Li class DeclToIndex {
52*67e74705SXin Li llvm::DenseMap<const VarDecl *, unsigned> map;
53*67e74705SXin Li public:
DeclToIndex()54*67e74705SXin Li DeclToIndex() {}
55*67e74705SXin Li
56*67e74705SXin Li /// Compute the actual mapping from declarations to bits.
57*67e74705SXin Li void computeMap(const DeclContext &dc);
58*67e74705SXin Li
59*67e74705SXin Li /// Return the number of declarations in the map.
size() const60*67e74705SXin Li unsigned size() const { return map.size(); }
61*67e74705SXin Li
62*67e74705SXin Li /// Returns the bit vector index for a given declaration.
63*67e74705SXin Li Optional<unsigned> getValueIndex(const VarDecl *d) const;
64*67e74705SXin Li };
65*67e74705SXin Li }
66*67e74705SXin Li
computeMap(const DeclContext & dc)67*67e74705SXin Li void DeclToIndex::computeMap(const DeclContext &dc) {
68*67e74705SXin Li unsigned count = 0;
69*67e74705SXin Li DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()),
70*67e74705SXin Li E(dc.decls_end());
71*67e74705SXin Li for ( ; I != E; ++I) {
72*67e74705SXin Li const VarDecl *vd = *I;
73*67e74705SXin Li if (isTrackedVar(vd, &dc))
74*67e74705SXin Li map[vd] = count++;
75*67e74705SXin Li }
76*67e74705SXin Li }
77*67e74705SXin Li
getValueIndex(const VarDecl * d) const78*67e74705SXin Li Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const {
79*67e74705SXin Li llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d);
80*67e74705SXin Li if (I == map.end())
81*67e74705SXin Li return None;
82*67e74705SXin Li return I->second;
83*67e74705SXin Li }
84*67e74705SXin Li
85*67e74705SXin Li //------------------------------------------------------------------------====//
86*67e74705SXin Li // CFGBlockValues: dataflow values for CFG blocks.
87*67e74705SXin Li //====------------------------------------------------------------------------//
88*67e74705SXin Li
89*67e74705SXin Li // These values are defined in such a way that a merge can be done using
90*67e74705SXin Li // a bitwise OR.
91*67e74705SXin Li enum Value { Unknown = 0x0, /* 00 */
92*67e74705SXin Li Initialized = 0x1, /* 01 */
93*67e74705SXin Li Uninitialized = 0x2, /* 10 */
94*67e74705SXin Li MayUninitialized = 0x3 /* 11 */ };
95*67e74705SXin Li
isUninitialized(const Value v)96*67e74705SXin Li static bool isUninitialized(const Value v) {
97*67e74705SXin Li return v >= Uninitialized;
98*67e74705SXin Li }
isAlwaysUninit(const Value v)99*67e74705SXin Li static bool isAlwaysUninit(const Value v) {
100*67e74705SXin Li return v == Uninitialized;
101*67e74705SXin Li }
102*67e74705SXin Li
103*67e74705SXin Li namespace {
104*67e74705SXin Li
105*67e74705SXin Li typedef llvm::PackedVector<Value, 2, llvm::SmallBitVector> ValueVector;
106*67e74705SXin Li
107*67e74705SXin Li class CFGBlockValues {
108*67e74705SXin Li const CFG &cfg;
109*67e74705SXin Li SmallVector<ValueVector, 8> vals;
110*67e74705SXin Li ValueVector scratch;
111*67e74705SXin Li DeclToIndex declToIndex;
112*67e74705SXin Li public:
113*67e74705SXin Li CFGBlockValues(const CFG &cfg);
114*67e74705SXin Li
getNumEntries() const115*67e74705SXin Li unsigned getNumEntries() const { return declToIndex.size(); }
116*67e74705SXin Li
117*67e74705SXin Li void computeSetOfDeclarations(const DeclContext &dc);
getValueVector(const CFGBlock * block)118*67e74705SXin Li ValueVector &getValueVector(const CFGBlock *block) {
119*67e74705SXin Li return vals[block->getBlockID()];
120*67e74705SXin Li }
121*67e74705SXin Li
122*67e74705SXin Li void setAllScratchValues(Value V);
123*67e74705SXin Li void mergeIntoScratch(ValueVector const &source, bool isFirst);
124*67e74705SXin Li bool updateValueVectorWithScratch(const CFGBlock *block);
125*67e74705SXin Li
hasNoDeclarations() const126*67e74705SXin Li bool hasNoDeclarations() const {
127*67e74705SXin Li return declToIndex.size() == 0;
128*67e74705SXin Li }
129*67e74705SXin Li
130*67e74705SXin Li void resetScratch();
131*67e74705SXin Li
132*67e74705SXin Li ValueVector::reference operator[](const VarDecl *vd);
133*67e74705SXin Li
getValue(const CFGBlock * block,const CFGBlock * dstBlock,const VarDecl * vd)134*67e74705SXin Li Value getValue(const CFGBlock *block, const CFGBlock *dstBlock,
135*67e74705SXin Li const VarDecl *vd) {
136*67e74705SXin Li const Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
137*67e74705SXin Li assert(idx.hasValue());
138*67e74705SXin Li return getValueVector(block)[idx.getValue()];
139*67e74705SXin Li }
140*67e74705SXin Li };
141*67e74705SXin Li } // end anonymous namespace
142*67e74705SXin Li
CFGBlockValues(const CFG & c)143*67e74705SXin Li CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {}
144*67e74705SXin Li
computeSetOfDeclarations(const DeclContext & dc)145*67e74705SXin Li void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
146*67e74705SXin Li declToIndex.computeMap(dc);
147*67e74705SXin Li unsigned decls = declToIndex.size();
148*67e74705SXin Li scratch.resize(decls);
149*67e74705SXin Li unsigned n = cfg.getNumBlockIDs();
150*67e74705SXin Li if (!n)
151*67e74705SXin Li return;
152*67e74705SXin Li vals.resize(n);
153*67e74705SXin Li for (unsigned i = 0; i < n; ++i)
154*67e74705SXin Li vals[i].resize(decls);
155*67e74705SXin Li }
156*67e74705SXin Li
157*67e74705SXin Li #if DEBUG_LOGGING
printVector(const CFGBlock * block,ValueVector & bv,unsigned num)158*67e74705SXin Li static void printVector(const CFGBlock *block, ValueVector &bv,
159*67e74705SXin Li unsigned num) {
160*67e74705SXin Li llvm::errs() << block->getBlockID() << " :";
161*67e74705SXin Li for (unsigned i = 0; i < bv.size(); ++i) {
162*67e74705SXin Li llvm::errs() << ' ' << bv[i];
163*67e74705SXin Li }
164*67e74705SXin Li llvm::errs() << " : " << num << '\n';
165*67e74705SXin Li }
166*67e74705SXin Li #endif
167*67e74705SXin Li
setAllScratchValues(Value V)168*67e74705SXin Li void CFGBlockValues::setAllScratchValues(Value V) {
169*67e74705SXin Li for (unsigned I = 0, E = scratch.size(); I != E; ++I)
170*67e74705SXin Li scratch[I] = V;
171*67e74705SXin Li }
172*67e74705SXin Li
mergeIntoScratch(ValueVector const & source,bool isFirst)173*67e74705SXin Li void CFGBlockValues::mergeIntoScratch(ValueVector const &source,
174*67e74705SXin Li bool isFirst) {
175*67e74705SXin Li if (isFirst)
176*67e74705SXin Li scratch = source;
177*67e74705SXin Li else
178*67e74705SXin Li scratch |= source;
179*67e74705SXin Li }
180*67e74705SXin Li
updateValueVectorWithScratch(const CFGBlock * block)181*67e74705SXin Li bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) {
182*67e74705SXin Li ValueVector &dst = getValueVector(block);
183*67e74705SXin Li bool changed = (dst != scratch);
184*67e74705SXin Li if (changed)
185*67e74705SXin Li dst = scratch;
186*67e74705SXin Li #if DEBUG_LOGGING
187*67e74705SXin Li printVector(block, scratch, 0);
188*67e74705SXin Li #endif
189*67e74705SXin Li return changed;
190*67e74705SXin Li }
191*67e74705SXin Li
resetScratch()192*67e74705SXin Li void CFGBlockValues::resetScratch() {
193*67e74705SXin Li scratch.reset();
194*67e74705SXin Li }
195*67e74705SXin Li
operator [](const VarDecl * vd)196*67e74705SXin Li ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
197*67e74705SXin Li const Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
198*67e74705SXin Li assert(idx.hasValue());
199*67e74705SXin Li return scratch[idx.getValue()];
200*67e74705SXin Li }
201*67e74705SXin Li
202*67e74705SXin Li //------------------------------------------------------------------------====//
203*67e74705SXin Li // Worklist: worklist for dataflow analysis.
204*67e74705SXin Li //====------------------------------------------------------------------------//
205*67e74705SXin Li
206*67e74705SXin Li namespace {
207*67e74705SXin Li class DataflowWorklist {
208*67e74705SXin Li PostOrderCFGView::iterator PO_I, PO_E;
209*67e74705SXin Li SmallVector<const CFGBlock *, 20> worklist;
210*67e74705SXin Li llvm::BitVector enqueuedBlocks;
211*67e74705SXin Li public:
DataflowWorklist(const CFG & cfg,PostOrderCFGView & view)212*67e74705SXin Li DataflowWorklist(const CFG &cfg, PostOrderCFGView &view)
213*67e74705SXin Li : PO_I(view.begin()), PO_E(view.end()),
214*67e74705SXin Li enqueuedBlocks(cfg.getNumBlockIDs(), true) {
215*67e74705SXin Li // Treat the first block as already analyzed.
216*67e74705SXin Li if (PO_I != PO_E) {
217*67e74705SXin Li assert(*PO_I == &cfg.getEntry());
218*67e74705SXin Li enqueuedBlocks[(*PO_I)->getBlockID()] = false;
219*67e74705SXin Li ++PO_I;
220*67e74705SXin Li }
221*67e74705SXin Li }
222*67e74705SXin Li
223*67e74705SXin Li void enqueueSuccessors(const CFGBlock *block);
224*67e74705SXin Li const CFGBlock *dequeue();
225*67e74705SXin Li };
226*67e74705SXin Li }
227*67e74705SXin Li
enqueueSuccessors(const clang::CFGBlock * block)228*67e74705SXin Li void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
229*67e74705SXin Li for (CFGBlock::const_succ_iterator I = block->succ_begin(),
230*67e74705SXin Li E = block->succ_end(); I != E; ++I) {
231*67e74705SXin Li const CFGBlock *Successor = *I;
232*67e74705SXin Li if (!Successor || enqueuedBlocks[Successor->getBlockID()])
233*67e74705SXin Li continue;
234*67e74705SXin Li worklist.push_back(Successor);
235*67e74705SXin Li enqueuedBlocks[Successor->getBlockID()] = true;
236*67e74705SXin Li }
237*67e74705SXin Li }
238*67e74705SXin Li
dequeue()239*67e74705SXin Li const CFGBlock *DataflowWorklist::dequeue() {
240*67e74705SXin Li const CFGBlock *B = nullptr;
241*67e74705SXin Li
242*67e74705SXin Li // First dequeue from the worklist. This can represent
243*67e74705SXin Li // updates along backedges that we want propagated as quickly as possible.
244*67e74705SXin Li if (!worklist.empty())
245*67e74705SXin Li B = worklist.pop_back_val();
246*67e74705SXin Li
247*67e74705SXin Li // Next dequeue from the initial reverse post order. This is the
248*67e74705SXin Li // theoretical ideal in the presence of no back edges.
249*67e74705SXin Li else if (PO_I != PO_E) {
250*67e74705SXin Li B = *PO_I;
251*67e74705SXin Li ++PO_I;
252*67e74705SXin Li }
253*67e74705SXin Li else {
254*67e74705SXin Li return nullptr;
255*67e74705SXin Li }
256*67e74705SXin Li
257*67e74705SXin Li assert(enqueuedBlocks[B->getBlockID()] == true);
258*67e74705SXin Li enqueuedBlocks[B->getBlockID()] = false;
259*67e74705SXin Li return B;
260*67e74705SXin Li }
261*67e74705SXin Li
262*67e74705SXin Li //------------------------------------------------------------------------====//
263*67e74705SXin Li // Classification of DeclRefExprs as use or initialization.
264*67e74705SXin Li //====------------------------------------------------------------------------//
265*67e74705SXin Li
266*67e74705SXin Li namespace {
267*67e74705SXin Li class FindVarResult {
268*67e74705SXin Li const VarDecl *vd;
269*67e74705SXin Li const DeclRefExpr *dr;
270*67e74705SXin Li public:
FindVarResult(const VarDecl * vd,const DeclRefExpr * dr)271*67e74705SXin Li FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {}
272*67e74705SXin Li
getDeclRefExpr() const273*67e74705SXin Li const DeclRefExpr *getDeclRefExpr() const { return dr; }
getDecl() const274*67e74705SXin Li const VarDecl *getDecl() const { return vd; }
275*67e74705SXin Li };
276*67e74705SXin Li
stripCasts(ASTContext & C,const Expr * Ex)277*67e74705SXin Li static const Expr *stripCasts(ASTContext &C, const Expr *Ex) {
278*67e74705SXin Li while (Ex) {
279*67e74705SXin Li Ex = Ex->IgnoreParenNoopCasts(C);
280*67e74705SXin Li if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
281*67e74705SXin Li if (CE->getCastKind() == CK_LValueBitCast) {
282*67e74705SXin Li Ex = CE->getSubExpr();
283*67e74705SXin Li continue;
284*67e74705SXin Li }
285*67e74705SXin Li }
286*67e74705SXin Li break;
287*67e74705SXin Li }
288*67e74705SXin Li return Ex;
289*67e74705SXin Li }
290*67e74705SXin Li
291*67e74705SXin Li /// If E is an expression comprising a reference to a single variable, find that
292*67e74705SXin Li /// variable.
findVar(const Expr * E,const DeclContext * DC)293*67e74705SXin Li static FindVarResult findVar(const Expr *E, const DeclContext *DC) {
294*67e74705SXin Li if (const DeclRefExpr *DRE =
295*67e74705SXin Li dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
296*67e74705SXin Li if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
297*67e74705SXin Li if (isTrackedVar(VD, DC))
298*67e74705SXin Li return FindVarResult(VD, DRE);
299*67e74705SXin Li return FindVarResult(nullptr, nullptr);
300*67e74705SXin Li }
301*67e74705SXin Li
302*67e74705SXin Li /// \brief Classify each DeclRefExpr as an initialization or a use. Any
303*67e74705SXin Li /// DeclRefExpr which isn't explicitly classified will be assumed to have
304*67e74705SXin Li /// escaped the analysis and will be treated as an initialization.
305*67e74705SXin Li class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
306*67e74705SXin Li public:
307*67e74705SXin Li enum Class {
308*67e74705SXin Li Init,
309*67e74705SXin Li Use,
310*67e74705SXin Li SelfInit,
311*67e74705SXin Li Ignore
312*67e74705SXin Li };
313*67e74705SXin Li
314*67e74705SXin Li private:
315*67e74705SXin Li const DeclContext *DC;
316*67e74705SXin Li llvm::DenseMap<const DeclRefExpr*, Class> Classification;
317*67e74705SXin Li
isTrackedVar(const VarDecl * VD) const318*67e74705SXin Li bool isTrackedVar(const VarDecl *VD) const {
319*67e74705SXin Li return ::isTrackedVar(VD, DC);
320*67e74705SXin Li }
321*67e74705SXin Li
322*67e74705SXin Li void classify(const Expr *E, Class C);
323*67e74705SXin Li
324*67e74705SXin Li public:
ClassifyRefs(AnalysisDeclContext & AC)325*67e74705SXin Li ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {}
326*67e74705SXin Li
327*67e74705SXin Li void VisitDeclStmt(DeclStmt *DS);
328*67e74705SXin Li void VisitUnaryOperator(UnaryOperator *UO);
329*67e74705SXin Li void VisitBinaryOperator(BinaryOperator *BO);
330*67e74705SXin Li void VisitCallExpr(CallExpr *CE);
331*67e74705SXin Li void VisitCastExpr(CastExpr *CE);
332*67e74705SXin Li
operator ()(Stmt * S)333*67e74705SXin Li void operator()(Stmt *S) { Visit(S); }
334*67e74705SXin Li
get(const DeclRefExpr * DRE) const335*67e74705SXin Li Class get(const DeclRefExpr *DRE) const {
336*67e74705SXin Li llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I
337*67e74705SXin Li = Classification.find(DRE);
338*67e74705SXin Li if (I != Classification.end())
339*67e74705SXin Li return I->second;
340*67e74705SXin Li
341*67e74705SXin Li const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
342*67e74705SXin Li if (!VD || !isTrackedVar(VD))
343*67e74705SXin Li return Ignore;
344*67e74705SXin Li
345*67e74705SXin Li return Init;
346*67e74705SXin Li }
347*67e74705SXin Li };
348*67e74705SXin Li }
349*67e74705SXin Li
getSelfInitExpr(VarDecl * VD)350*67e74705SXin Li static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
351*67e74705SXin Li if (VD->getType()->isRecordType()) return nullptr;
352*67e74705SXin Li if (Expr *Init = VD->getInit()) {
353*67e74705SXin Li const DeclRefExpr *DRE
354*67e74705SXin Li = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
355*67e74705SXin Li if (DRE && DRE->getDecl() == VD)
356*67e74705SXin Li return DRE;
357*67e74705SXin Li }
358*67e74705SXin Li return nullptr;
359*67e74705SXin Li }
360*67e74705SXin Li
classify(const Expr * E,Class C)361*67e74705SXin Li void ClassifyRefs::classify(const Expr *E, Class C) {
362*67e74705SXin Li // The result of a ?: could also be an lvalue.
363*67e74705SXin Li E = E->IgnoreParens();
364*67e74705SXin Li if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
365*67e74705SXin Li classify(CO->getTrueExpr(), C);
366*67e74705SXin Li classify(CO->getFalseExpr(), C);
367*67e74705SXin Li return;
368*67e74705SXin Li }
369*67e74705SXin Li
370*67e74705SXin Li if (const BinaryConditionalOperator *BCO =
371*67e74705SXin Li dyn_cast<BinaryConditionalOperator>(E)) {
372*67e74705SXin Li classify(BCO->getFalseExpr(), C);
373*67e74705SXin Li return;
374*67e74705SXin Li }
375*67e74705SXin Li
376*67e74705SXin Li if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
377*67e74705SXin Li classify(OVE->getSourceExpr(), C);
378*67e74705SXin Li return;
379*67e74705SXin Li }
380*67e74705SXin Li
381*67e74705SXin Li if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
382*67e74705SXin Li if (VarDecl *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
383*67e74705SXin Li if (!VD->isStaticDataMember())
384*67e74705SXin Li classify(ME->getBase(), C);
385*67e74705SXin Li }
386*67e74705SXin Li return;
387*67e74705SXin Li }
388*67e74705SXin Li
389*67e74705SXin Li if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
390*67e74705SXin Li switch (BO->getOpcode()) {
391*67e74705SXin Li case BO_PtrMemD:
392*67e74705SXin Li case BO_PtrMemI:
393*67e74705SXin Li classify(BO->getLHS(), C);
394*67e74705SXin Li return;
395*67e74705SXin Li case BO_Comma:
396*67e74705SXin Li classify(BO->getRHS(), C);
397*67e74705SXin Li return;
398*67e74705SXin Li default:
399*67e74705SXin Li return;
400*67e74705SXin Li }
401*67e74705SXin Li }
402*67e74705SXin Li
403*67e74705SXin Li FindVarResult Var = findVar(E, DC);
404*67e74705SXin Li if (const DeclRefExpr *DRE = Var.getDeclRefExpr())
405*67e74705SXin Li Classification[DRE] = std::max(Classification[DRE], C);
406*67e74705SXin Li }
407*67e74705SXin Li
VisitDeclStmt(DeclStmt * DS)408*67e74705SXin Li void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
409*67e74705SXin Li for (auto *DI : DS->decls()) {
410*67e74705SXin Li VarDecl *VD = dyn_cast<VarDecl>(DI);
411*67e74705SXin Li if (VD && isTrackedVar(VD))
412*67e74705SXin Li if (const DeclRefExpr *DRE = getSelfInitExpr(VD))
413*67e74705SXin Li Classification[DRE] = SelfInit;
414*67e74705SXin Li }
415*67e74705SXin Li }
416*67e74705SXin Li
VisitBinaryOperator(BinaryOperator * BO)417*67e74705SXin Li void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) {
418*67e74705SXin Li // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this
419*67e74705SXin Li // is not a compound-assignment, we will treat it as initializing the variable
420*67e74705SXin Li // when TransferFunctions visits it. A compound-assignment does not affect
421*67e74705SXin Li // whether a variable is uninitialized, and there's no point counting it as a
422*67e74705SXin Li // use.
423*67e74705SXin Li if (BO->isCompoundAssignmentOp())
424*67e74705SXin Li classify(BO->getLHS(), Use);
425*67e74705SXin Li else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma)
426*67e74705SXin Li classify(BO->getLHS(), Ignore);
427*67e74705SXin Li }
428*67e74705SXin Li
VisitUnaryOperator(UnaryOperator * UO)429*67e74705SXin Li void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) {
430*67e74705SXin Li // Increment and decrement are uses despite there being no lvalue-to-rvalue
431*67e74705SXin Li // conversion.
432*67e74705SXin Li if (UO->isIncrementDecrementOp())
433*67e74705SXin Li classify(UO->getSubExpr(), Use);
434*67e74705SXin Li }
435*67e74705SXin Li
isPointerToConst(const QualType & QT)436*67e74705SXin Li static bool isPointerToConst(const QualType &QT) {
437*67e74705SXin Li return QT->isAnyPointerType() && QT->getPointeeType().isConstQualified();
438*67e74705SXin Li }
439*67e74705SXin Li
VisitCallExpr(CallExpr * CE)440*67e74705SXin Li void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
441*67e74705SXin Li // Classify arguments to std::move as used.
442*67e74705SXin Li if (CE->getNumArgs() == 1) {
443*67e74705SXin Li if (FunctionDecl *FD = CE->getDirectCallee()) {
444*67e74705SXin Li if (FD->isInStdNamespace() && FD->getIdentifier() &&
445*67e74705SXin Li FD->getIdentifier()->isStr("move")) {
446*67e74705SXin Li // RecordTypes are handled in SemaDeclCXX.cpp.
447*67e74705SXin Li if (!CE->getArg(0)->getType()->isRecordType())
448*67e74705SXin Li classify(CE->getArg(0), Use);
449*67e74705SXin Li return;
450*67e74705SXin Li }
451*67e74705SXin Li }
452*67e74705SXin Li }
453*67e74705SXin Li
454*67e74705SXin Li // If a value is passed by const pointer or by const reference to a function,
455*67e74705SXin Li // we should not assume that it is initialized by the call, and we
456*67e74705SXin Li // conservatively do not assume that it is used.
457*67e74705SXin Li for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
458*67e74705SXin Li I != E; ++I) {
459*67e74705SXin Li if ((*I)->isGLValue()) {
460*67e74705SXin Li if ((*I)->getType().isConstQualified())
461*67e74705SXin Li classify((*I), Ignore);
462*67e74705SXin Li } else if (isPointerToConst((*I)->getType())) {
463*67e74705SXin Li const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
464*67e74705SXin Li const UnaryOperator *UO = dyn_cast<UnaryOperator>(Ex);
465*67e74705SXin Li if (UO && UO->getOpcode() == UO_AddrOf)
466*67e74705SXin Li Ex = UO->getSubExpr();
467*67e74705SXin Li classify(Ex, Ignore);
468*67e74705SXin Li }
469*67e74705SXin Li }
470*67e74705SXin Li }
471*67e74705SXin Li
VisitCastExpr(CastExpr * CE)472*67e74705SXin Li void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
473*67e74705SXin Li if (CE->getCastKind() == CK_LValueToRValue)
474*67e74705SXin Li classify(CE->getSubExpr(), Use);
475*67e74705SXin Li else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) {
476*67e74705SXin Li if (CSE->getType()->isVoidType()) {
477*67e74705SXin Li // Squelch any detected load of an uninitialized value if
478*67e74705SXin Li // we cast it to void.
479*67e74705SXin Li // e.g. (void) x;
480*67e74705SXin Li classify(CSE->getSubExpr(), Ignore);
481*67e74705SXin Li }
482*67e74705SXin Li }
483*67e74705SXin Li }
484*67e74705SXin Li
485*67e74705SXin Li //------------------------------------------------------------------------====//
486*67e74705SXin Li // Transfer function for uninitialized values analysis.
487*67e74705SXin Li //====------------------------------------------------------------------------//
488*67e74705SXin Li
489*67e74705SXin Li namespace {
490*67e74705SXin Li class TransferFunctions : public StmtVisitor<TransferFunctions> {
491*67e74705SXin Li CFGBlockValues &vals;
492*67e74705SXin Li const CFG &cfg;
493*67e74705SXin Li const CFGBlock *block;
494*67e74705SXin Li AnalysisDeclContext ∾
495*67e74705SXin Li const ClassifyRefs &classification;
496*67e74705SXin Li ObjCNoReturn objCNoRet;
497*67e74705SXin Li UninitVariablesHandler &handler;
498*67e74705SXin Li
499*67e74705SXin Li public:
TransferFunctions(CFGBlockValues & vals,const CFG & cfg,const CFGBlock * block,AnalysisDeclContext & ac,const ClassifyRefs & classification,UninitVariablesHandler & handler)500*67e74705SXin Li TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
501*67e74705SXin Li const CFGBlock *block, AnalysisDeclContext &ac,
502*67e74705SXin Li const ClassifyRefs &classification,
503*67e74705SXin Li UninitVariablesHandler &handler)
504*67e74705SXin Li : vals(vals), cfg(cfg), block(block), ac(ac),
505*67e74705SXin Li classification(classification), objCNoRet(ac.getASTContext()),
506*67e74705SXin Li handler(handler) {}
507*67e74705SXin Li
508*67e74705SXin Li void reportUse(const Expr *ex, const VarDecl *vd);
509*67e74705SXin Li
510*67e74705SXin Li void VisitBinaryOperator(BinaryOperator *bo);
511*67e74705SXin Li void VisitBlockExpr(BlockExpr *be);
512*67e74705SXin Li void VisitCallExpr(CallExpr *ce);
513*67e74705SXin Li void VisitDeclRefExpr(DeclRefExpr *dr);
514*67e74705SXin Li void VisitDeclStmt(DeclStmt *ds);
515*67e74705SXin Li void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS);
516*67e74705SXin Li void VisitObjCMessageExpr(ObjCMessageExpr *ME);
517*67e74705SXin Li
isTrackedVar(const VarDecl * vd)518*67e74705SXin Li bool isTrackedVar(const VarDecl *vd) {
519*67e74705SXin Li return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl()));
520*67e74705SXin Li }
521*67e74705SXin Li
findVar(const Expr * ex)522*67e74705SXin Li FindVarResult findVar(const Expr *ex) {
523*67e74705SXin Li return ::findVar(ex, cast<DeclContext>(ac.getDecl()));
524*67e74705SXin Li }
525*67e74705SXin Li
getUninitUse(const Expr * ex,const VarDecl * vd,Value v)526*67e74705SXin Li UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) {
527*67e74705SXin Li UninitUse Use(ex, isAlwaysUninit(v));
528*67e74705SXin Li
529*67e74705SXin Li assert(isUninitialized(v));
530*67e74705SXin Li if (Use.getKind() == UninitUse::Always)
531*67e74705SXin Li return Use;
532*67e74705SXin Li
533*67e74705SXin Li // If an edge which leads unconditionally to this use did not initialize
534*67e74705SXin Li // the variable, we can say something stronger than 'may be uninitialized':
535*67e74705SXin Li // we can say 'either it's used uninitialized or you have dead code'.
536*67e74705SXin Li //
537*67e74705SXin Li // We track the number of successors of a node which have been visited, and
538*67e74705SXin Li // visit a node once we have visited all of its successors. Only edges where
539*67e74705SXin Li // the variable might still be uninitialized are followed. Since a variable
540*67e74705SXin Li // can't transfer from being initialized to being uninitialized, this will
541*67e74705SXin Li // trace out the subgraph which inevitably leads to the use and does not
542*67e74705SXin Li // initialize the variable. We do not want to skip past loops, since their
543*67e74705SXin Li // non-termination might be correlated with the initialization condition.
544*67e74705SXin Li //
545*67e74705SXin Li // For example:
546*67e74705SXin Li //
547*67e74705SXin Li // void f(bool a, bool b) {
548*67e74705SXin Li // block1: int n;
549*67e74705SXin Li // if (a) {
550*67e74705SXin Li // block2: if (b)
551*67e74705SXin Li // block3: n = 1;
552*67e74705SXin Li // block4: } else if (b) {
553*67e74705SXin Li // block5: while (!a) {
554*67e74705SXin Li // block6: do_work(&a);
555*67e74705SXin Li // n = 2;
556*67e74705SXin Li // }
557*67e74705SXin Li // }
558*67e74705SXin Li // block7: if (a)
559*67e74705SXin Li // block8: g();
560*67e74705SXin Li // block9: return n;
561*67e74705SXin Li // }
562*67e74705SXin Li //
563*67e74705SXin Li // Starting from the maybe-uninitialized use in block 9:
564*67e74705SXin Li // * Block 7 is not visited because we have only visited one of its two
565*67e74705SXin Li // successors.
566*67e74705SXin Li // * Block 8 is visited because we've visited its only successor.
567*67e74705SXin Li // From block 8:
568*67e74705SXin Li // * Block 7 is visited because we've now visited both of its successors.
569*67e74705SXin Li // From block 7:
570*67e74705SXin Li // * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all
571*67e74705SXin Li // of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively).
572*67e74705SXin Li // * Block 3 is not visited because it initializes 'n'.
573*67e74705SXin Li // Now the algorithm terminates, having visited blocks 7 and 8, and having
574*67e74705SXin Li // found the frontier is blocks 2, 4, and 5.
575*67e74705SXin Li //
576*67e74705SXin Li // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2
577*67e74705SXin Li // and 4), so we report that any time either of those edges is taken (in
578*67e74705SXin Li // each case when 'b == false'), 'n' is used uninitialized.
579*67e74705SXin Li SmallVector<const CFGBlock*, 32> Queue;
580*67e74705SXin Li SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0);
581*67e74705SXin Li Queue.push_back(block);
582*67e74705SXin Li // Specify that we've already visited all successors of the starting block.
583*67e74705SXin Li // This has the dual purpose of ensuring we never add it to the queue, and
584*67e74705SXin Li // of marking it as not being a candidate element of the frontier.
585*67e74705SXin Li SuccsVisited[block->getBlockID()] = block->succ_size();
586*67e74705SXin Li while (!Queue.empty()) {
587*67e74705SXin Li const CFGBlock *B = Queue.pop_back_val();
588*67e74705SXin Li
589*67e74705SXin Li // If the use is always reached from the entry block, make a note of that.
590*67e74705SXin Li if (B == &cfg.getEntry())
591*67e74705SXin Li Use.setUninitAfterCall();
592*67e74705SXin Li
593*67e74705SXin Li for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end();
594*67e74705SXin Li I != E; ++I) {
595*67e74705SXin Li const CFGBlock *Pred = *I;
596*67e74705SXin Li if (!Pred)
597*67e74705SXin Li continue;
598*67e74705SXin Li
599*67e74705SXin Li Value AtPredExit = vals.getValue(Pred, B, vd);
600*67e74705SXin Li if (AtPredExit == Initialized)
601*67e74705SXin Li // This block initializes the variable.
602*67e74705SXin Li continue;
603*67e74705SXin Li if (AtPredExit == MayUninitialized &&
604*67e74705SXin Li vals.getValue(B, nullptr, vd) == Uninitialized) {
605*67e74705SXin Li // This block declares the variable (uninitialized), and is reachable
606*67e74705SXin Li // from a block that initializes the variable. We can't guarantee to
607*67e74705SXin Li // give an earlier location for the diagnostic (and it appears that
608*67e74705SXin Li // this code is intended to be reachable) so give a diagnostic here
609*67e74705SXin Li // and go no further down this path.
610*67e74705SXin Li Use.setUninitAfterDecl();
611*67e74705SXin Li continue;
612*67e74705SXin Li }
613*67e74705SXin Li
614*67e74705SXin Li unsigned &SV = SuccsVisited[Pred->getBlockID()];
615*67e74705SXin Li if (!SV) {
616*67e74705SXin Li // When visiting the first successor of a block, mark all NULL
617*67e74705SXin Li // successors as having been visited.
618*67e74705SXin Li for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(),
619*67e74705SXin Li SE = Pred->succ_end();
620*67e74705SXin Li SI != SE; ++SI)
621*67e74705SXin Li if (!*SI)
622*67e74705SXin Li ++SV;
623*67e74705SXin Li }
624*67e74705SXin Li
625*67e74705SXin Li if (++SV == Pred->succ_size())
626*67e74705SXin Li // All paths from this block lead to the use and don't initialize the
627*67e74705SXin Li // variable.
628*67e74705SXin Li Queue.push_back(Pred);
629*67e74705SXin Li }
630*67e74705SXin Li }
631*67e74705SXin Li
632*67e74705SXin Li // Scan the frontier, looking for blocks where the variable was
633*67e74705SXin Li // uninitialized.
634*67e74705SXin Li for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
635*67e74705SXin Li const CFGBlock *Block = *BI;
636*67e74705SXin Li unsigned BlockID = Block->getBlockID();
637*67e74705SXin Li const Stmt *Term = Block->getTerminator();
638*67e74705SXin Li if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() &&
639*67e74705SXin Li Term) {
640*67e74705SXin Li // This block inevitably leads to the use. If we have an edge from here
641*67e74705SXin Li // to a post-dominator block, and the variable is uninitialized on that
642*67e74705SXin Li // edge, we have found a bug.
643*67e74705SXin Li for (CFGBlock::const_succ_iterator I = Block->succ_begin(),
644*67e74705SXin Li E = Block->succ_end(); I != E; ++I) {
645*67e74705SXin Li const CFGBlock *Succ = *I;
646*67e74705SXin Li if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() &&
647*67e74705SXin Li vals.getValue(Block, Succ, vd) == Uninitialized) {
648*67e74705SXin Li // Switch cases are a special case: report the label to the caller
649*67e74705SXin Li // as the 'terminator', not the switch statement itself. Suppress
650*67e74705SXin Li // situations where no label matched: we can't be sure that's
651*67e74705SXin Li // possible.
652*67e74705SXin Li if (isa<SwitchStmt>(Term)) {
653*67e74705SXin Li const Stmt *Label = Succ->getLabel();
654*67e74705SXin Li if (!Label || !isa<SwitchCase>(Label))
655*67e74705SXin Li // Might not be possible.
656*67e74705SXin Li continue;
657*67e74705SXin Li UninitUse::Branch Branch;
658*67e74705SXin Li Branch.Terminator = Label;
659*67e74705SXin Li Branch.Output = 0; // Ignored.
660*67e74705SXin Li Use.addUninitBranch(Branch);
661*67e74705SXin Li } else {
662*67e74705SXin Li UninitUse::Branch Branch;
663*67e74705SXin Li Branch.Terminator = Term;
664*67e74705SXin Li Branch.Output = I - Block->succ_begin();
665*67e74705SXin Li Use.addUninitBranch(Branch);
666*67e74705SXin Li }
667*67e74705SXin Li }
668*67e74705SXin Li }
669*67e74705SXin Li }
670*67e74705SXin Li }
671*67e74705SXin Li
672*67e74705SXin Li return Use;
673*67e74705SXin Li }
674*67e74705SXin Li };
675*67e74705SXin Li }
676*67e74705SXin Li
reportUse(const Expr * ex,const VarDecl * vd)677*67e74705SXin Li void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
678*67e74705SXin Li Value v = vals[vd];
679*67e74705SXin Li if (isUninitialized(v))
680*67e74705SXin Li handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
681*67e74705SXin Li }
682*67e74705SXin Li
VisitObjCForCollectionStmt(ObjCForCollectionStmt * FS)683*67e74705SXin Li void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
684*67e74705SXin Li // This represents an initialization of the 'element' value.
685*67e74705SXin Li if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) {
686*67e74705SXin Li const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
687*67e74705SXin Li if (isTrackedVar(VD))
688*67e74705SXin Li vals[VD] = Initialized;
689*67e74705SXin Li }
690*67e74705SXin Li }
691*67e74705SXin Li
VisitBlockExpr(BlockExpr * be)692*67e74705SXin Li void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
693*67e74705SXin Li const BlockDecl *bd = be->getBlockDecl();
694*67e74705SXin Li for (const auto &I : bd->captures()) {
695*67e74705SXin Li const VarDecl *vd = I.getVariable();
696*67e74705SXin Li if (!isTrackedVar(vd))
697*67e74705SXin Li continue;
698*67e74705SXin Li if (I.isByRef()) {
699*67e74705SXin Li vals[vd] = Initialized;
700*67e74705SXin Li continue;
701*67e74705SXin Li }
702*67e74705SXin Li reportUse(be, vd);
703*67e74705SXin Li }
704*67e74705SXin Li }
705*67e74705SXin Li
VisitCallExpr(CallExpr * ce)706*67e74705SXin Li void TransferFunctions::VisitCallExpr(CallExpr *ce) {
707*67e74705SXin Li if (Decl *Callee = ce->getCalleeDecl()) {
708*67e74705SXin Li if (Callee->hasAttr<ReturnsTwiceAttr>()) {
709*67e74705SXin Li // After a call to a function like setjmp or vfork, any variable which is
710*67e74705SXin Li // initialized anywhere within this function may now be initialized. For
711*67e74705SXin Li // now, just assume such a call initializes all variables. FIXME: Only
712*67e74705SXin Li // mark variables as initialized if they have an initializer which is
713*67e74705SXin Li // reachable from here.
714*67e74705SXin Li vals.setAllScratchValues(Initialized);
715*67e74705SXin Li }
716*67e74705SXin Li else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) {
717*67e74705SXin Li // Functions labeled like "analyzer_noreturn" are often used to denote
718*67e74705SXin Li // "panic" functions that in special debug situations can still return,
719*67e74705SXin Li // but for the most part should not be treated as returning. This is a
720*67e74705SXin Li // useful annotation borrowed from the static analyzer that is useful for
721*67e74705SXin Li // suppressing branch-specific false positives when we call one of these
722*67e74705SXin Li // functions but keep pretending the path continues (when in reality the
723*67e74705SXin Li // user doesn't care).
724*67e74705SXin Li vals.setAllScratchValues(Unknown);
725*67e74705SXin Li }
726*67e74705SXin Li }
727*67e74705SXin Li }
728*67e74705SXin Li
VisitDeclRefExpr(DeclRefExpr * dr)729*67e74705SXin Li void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
730*67e74705SXin Li switch (classification.get(dr)) {
731*67e74705SXin Li case ClassifyRefs::Ignore:
732*67e74705SXin Li break;
733*67e74705SXin Li case ClassifyRefs::Use:
734*67e74705SXin Li reportUse(dr, cast<VarDecl>(dr->getDecl()));
735*67e74705SXin Li break;
736*67e74705SXin Li case ClassifyRefs::Init:
737*67e74705SXin Li vals[cast<VarDecl>(dr->getDecl())] = Initialized;
738*67e74705SXin Li break;
739*67e74705SXin Li case ClassifyRefs::SelfInit:
740*67e74705SXin Li handler.handleSelfInit(cast<VarDecl>(dr->getDecl()));
741*67e74705SXin Li break;
742*67e74705SXin Li }
743*67e74705SXin Li }
744*67e74705SXin Li
VisitBinaryOperator(BinaryOperator * BO)745*67e74705SXin Li void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) {
746*67e74705SXin Li if (BO->getOpcode() == BO_Assign) {
747*67e74705SXin Li FindVarResult Var = findVar(BO->getLHS());
748*67e74705SXin Li if (const VarDecl *VD = Var.getDecl())
749*67e74705SXin Li vals[VD] = Initialized;
750*67e74705SXin Li }
751*67e74705SXin Li }
752*67e74705SXin Li
VisitDeclStmt(DeclStmt * DS)753*67e74705SXin Li void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
754*67e74705SXin Li for (auto *DI : DS->decls()) {
755*67e74705SXin Li VarDecl *VD = dyn_cast<VarDecl>(DI);
756*67e74705SXin Li if (VD && isTrackedVar(VD)) {
757*67e74705SXin Li if (getSelfInitExpr(VD)) {
758*67e74705SXin Li // If the initializer consists solely of a reference to itself, we
759*67e74705SXin Li // explicitly mark the variable as uninitialized. This allows code
760*67e74705SXin Li // like the following:
761*67e74705SXin Li //
762*67e74705SXin Li // int x = x;
763*67e74705SXin Li //
764*67e74705SXin Li // to deliberately leave a variable uninitialized. Different analysis
765*67e74705SXin Li // clients can detect this pattern and adjust their reporting
766*67e74705SXin Li // appropriately, but we need to continue to analyze subsequent uses
767*67e74705SXin Li // of the variable.
768*67e74705SXin Li vals[VD] = Uninitialized;
769*67e74705SXin Li } else if (VD->getInit()) {
770*67e74705SXin Li // Treat the new variable as initialized.
771*67e74705SXin Li vals[VD] = Initialized;
772*67e74705SXin Li } else {
773*67e74705SXin Li // No initializer: the variable is now uninitialized. This matters
774*67e74705SXin Li // for cases like:
775*67e74705SXin Li // while (...) {
776*67e74705SXin Li // int n;
777*67e74705SXin Li // use(n);
778*67e74705SXin Li // n = 0;
779*67e74705SXin Li // }
780*67e74705SXin Li // FIXME: Mark the variable as uninitialized whenever its scope is
781*67e74705SXin Li // left, since its scope could be re-entered by a jump over the
782*67e74705SXin Li // declaration.
783*67e74705SXin Li vals[VD] = Uninitialized;
784*67e74705SXin Li }
785*67e74705SXin Li }
786*67e74705SXin Li }
787*67e74705SXin Li }
788*67e74705SXin Li
VisitObjCMessageExpr(ObjCMessageExpr * ME)789*67e74705SXin Li void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) {
790*67e74705SXin Li // If the Objective-C message expression is an implicit no-return that
791*67e74705SXin Li // is not modeled in the CFG, set the tracked dataflow values to Unknown.
792*67e74705SXin Li if (objCNoRet.isImplicitNoReturn(ME)) {
793*67e74705SXin Li vals.setAllScratchValues(Unknown);
794*67e74705SXin Li }
795*67e74705SXin Li }
796*67e74705SXin Li
797*67e74705SXin Li //------------------------------------------------------------------------====//
798*67e74705SXin Li // High-level "driver" logic for uninitialized values analysis.
799*67e74705SXin Li //====------------------------------------------------------------------------//
800*67e74705SXin Li
runOnBlock(const CFGBlock * block,const CFG & cfg,AnalysisDeclContext & ac,CFGBlockValues & vals,const ClassifyRefs & classification,llvm::BitVector & wasAnalyzed,UninitVariablesHandler & handler)801*67e74705SXin Li static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
802*67e74705SXin Li AnalysisDeclContext &ac, CFGBlockValues &vals,
803*67e74705SXin Li const ClassifyRefs &classification,
804*67e74705SXin Li llvm::BitVector &wasAnalyzed,
805*67e74705SXin Li UninitVariablesHandler &handler) {
806*67e74705SXin Li wasAnalyzed[block->getBlockID()] = true;
807*67e74705SXin Li vals.resetScratch();
808*67e74705SXin Li // Merge in values of predecessor blocks.
809*67e74705SXin Li bool isFirst = true;
810*67e74705SXin Li for (CFGBlock::const_pred_iterator I = block->pred_begin(),
811*67e74705SXin Li E = block->pred_end(); I != E; ++I) {
812*67e74705SXin Li const CFGBlock *pred = *I;
813*67e74705SXin Li if (!pred)
814*67e74705SXin Li continue;
815*67e74705SXin Li if (wasAnalyzed[pred->getBlockID()]) {
816*67e74705SXin Li vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
817*67e74705SXin Li isFirst = false;
818*67e74705SXin Li }
819*67e74705SXin Li }
820*67e74705SXin Li // Apply the transfer function.
821*67e74705SXin Li TransferFunctions tf(vals, cfg, block, ac, classification, handler);
822*67e74705SXin Li for (CFGBlock::const_iterator I = block->begin(), E = block->end();
823*67e74705SXin Li I != E; ++I) {
824*67e74705SXin Li if (Optional<CFGStmt> cs = I->getAs<CFGStmt>())
825*67e74705SXin Li tf.Visit(const_cast<Stmt*>(cs->getStmt()));
826*67e74705SXin Li }
827*67e74705SXin Li return vals.updateValueVectorWithScratch(block);
828*67e74705SXin Li }
829*67e74705SXin Li
830*67e74705SXin Li /// PruneBlocksHandler is a special UninitVariablesHandler that is used
831*67e74705SXin Li /// to detect when a CFGBlock has any *potential* use of an uninitialized
832*67e74705SXin Li /// variable. It is mainly used to prune out work during the final
833*67e74705SXin Li /// reporting pass.
834*67e74705SXin Li namespace {
835*67e74705SXin Li struct PruneBlocksHandler : public UninitVariablesHandler {
PruneBlocksHandler__anonb0c3abce0611::PruneBlocksHandler836*67e74705SXin Li PruneBlocksHandler(unsigned numBlocks)
837*67e74705SXin Li : hadUse(numBlocks, false), hadAnyUse(false),
838*67e74705SXin Li currentBlock(0) {}
839*67e74705SXin Li
~PruneBlocksHandler__anonb0c3abce0611::PruneBlocksHandler840*67e74705SXin Li ~PruneBlocksHandler() override {}
841*67e74705SXin Li
842*67e74705SXin Li /// Records if a CFGBlock had a potential use of an uninitialized variable.
843*67e74705SXin Li llvm::BitVector hadUse;
844*67e74705SXin Li
845*67e74705SXin Li /// Records if any CFGBlock had a potential use of an uninitialized variable.
846*67e74705SXin Li bool hadAnyUse;
847*67e74705SXin Li
848*67e74705SXin Li /// The current block to scribble use information.
849*67e74705SXin Li unsigned currentBlock;
850*67e74705SXin Li
handleUseOfUninitVariable__anonb0c3abce0611::PruneBlocksHandler851*67e74705SXin Li void handleUseOfUninitVariable(const VarDecl *vd,
852*67e74705SXin Li const UninitUse &use) override {
853*67e74705SXin Li hadUse[currentBlock] = true;
854*67e74705SXin Li hadAnyUse = true;
855*67e74705SXin Li }
856*67e74705SXin Li
857*67e74705SXin Li /// Called when the uninitialized variable analysis detects the
858*67e74705SXin Li /// idiom 'int x = x'. All other uses of 'x' within the initializer
859*67e74705SXin Li /// are handled by handleUseOfUninitVariable.
handleSelfInit__anonb0c3abce0611::PruneBlocksHandler860*67e74705SXin Li void handleSelfInit(const VarDecl *vd) override {
861*67e74705SXin Li hadUse[currentBlock] = true;
862*67e74705SXin Li hadAnyUse = true;
863*67e74705SXin Li }
864*67e74705SXin Li };
865*67e74705SXin Li }
866*67e74705SXin Li
runUninitializedVariablesAnalysis(const DeclContext & dc,const CFG & cfg,AnalysisDeclContext & ac,UninitVariablesHandler & handler,UninitVariablesAnalysisStats & stats)867*67e74705SXin Li void clang::runUninitializedVariablesAnalysis(
868*67e74705SXin Li const DeclContext &dc,
869*67e74705SXin Li const CFG &cfg,
870*67e74705SXin Li AnalysisDeclContext &ac,
871*67e74705SXin Li UninitVariablesHandler &handler,
872*67e74705SXin Li UninitVariablesAnalysisStats &stats) {
873*67e74705SXin Li CFGBlockValues vals(cfg);
874*67e74705SXin Li vals.computeSetOfDeclarations(dc);
875*67e74705SXin Li if (vals.hasNoDeclarations())
876*67e74705SXin Li return;
877*67e74705SXin Li
878*67e74705SXin Li stats.NumVariablesAnalyzed = vals.getNumEntries();
879*67e74705SXin Li
880*67e74705SXin Li // Precompute which expressions are uses and which are initializations.
881*67e74705SXin Li ClassifyRefs classification(ac);
882*67e74705SXin Li cfg.VisitBlockStmts(classification);
883*67e74705SXin Li
884*67e74705SXin Li // Mark all variables uninitialized at the entry.
885*67e74705SXin Li const CFGBlock &entry = cfg.getEntry();
886*67e74705SXin Li ValueVector &vec = vals.getValueVector(&entry);
887*67e74705SXin Li const unsigned n = vals.getNumEntries();
888*67e74705SXin Li for (unsigned j = 0; j < n ; ++j) {
889*67e74705SXin Li vec[j] = Uninitialized;
890*67e74705SXin Li }
891*67e74705SXin Li
892*67e74705SXin Li // Proceed with the workist.
893*67e74705SXin Li DataflowWorklist worklist(cfg, *ac.getAnalysis<PostOrderCFGView>());
894*67e74705SXin Li llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
895*67e74705SXin Li worklist.enqueueSuccessors(&cfg.getEntry());
896*67e74705SXin Li llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
897*67e74705SXin Li wasAnalyzed[cfg.getEntry().getBlockID()] = true;
898*67e74705SXin Li PruneBlocksHandler PBH(cfg.getNumBlockIDs());
899*67e74705SXin Li
900*67e74705SXin Li while (const CFGBlock *block = worklist.dequeue()) {
901*67e74705SXin Li PBH.currentBlock = block->getBlockID();
902*67e74705SXin Li
903*67e74705SXin Li // Did the block change?
904*67e74705SXin Li bool changed = runOnBlock(block, cfg, ac, vals,
905*67e74705SXin Li classification, wasAnalyzed, PBH);
906*67e74705SXin Li ++stats.NumBlockVisits;
907*67e74705SXin Li if (changed || !previouslyVisited[block->getBlockID()])
908*67e74705SXin Li worklist.enqueueSuccessors(block);
909*67e74705SXin Li previouslyVisited[block->getBlockID()] = true;
910*67e74705SXin Li }
911*67e74705SXin Li
912*67e74705SXin Li if (!PBH.hadAnyUse)
913*67e74705SXin Li return;
914*67e74705SXin Li
915*67e74705SXin Li // Run through the blocks one more time, and report uninitialized variables.
916*67e74705SXin Li for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
917*67e74705SXin Li const CFGBlock *block = *BI;
918*67e74705SXin Li if (PBH.hadUse[block->getBlockID()]) {
919*67e74705SXin Li runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
920*67e74705SXin Li ++stats.NumBlockVisits;
921*67e74705SXin Li }
922*67e74705SXin Li }
923*67e74705SXin Li }
924*67e74705SXin Li
~UninitVariablesHandler()925*67e74705SXin Li UninitVariablesHandler::~UninitVariablesHandler() {}
926