xref: /aosp_15_r20/external/clang/lib/Analysis/UninitializedValues.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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 &ac;
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