1 //= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines APIs for invoking and reported uninitialized values
11 // warnings.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
16 #define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
17 
18 #include "clang/AST/Stmt.h"
19 #include "llvm/ADT/SmallVector.h"
20 
21 namespace clang {
22 
23 class AnalysisDeclContext;
24 class CFG;
25 class DeclContext;
26 class Expr;
27 class VarDecl;
28 
29 /// A use of a variable, which might be uninitialized.
30 class UninitUse {
31 public:
32   struct Branch {
33     const Stmt *Terminator;
34     unsigned Output;
35   };
36 
37 private:
38   /// The expression which uses this variable.
39   const Expr *User;
40 
41   /// Is this use uninitialized whenever the function is called?
42   bool UninitAfterCall;
43 
44   /// Is this use uninitialized whenever the variable declaration is reached?
45   bool UninitAfterDecl;
46 
47   /// Does this use always see an uninitialized value?
48   bool AlwaysUninit;
49 
50   /// This use is always uninitialized if it occurs after any of these branches
51   /// is taken.
52   SmallVector<Branch, 2> UninitBranches;
53 
54 public:
UninitUse(const Expr * User,bool AlwaysUninit)55   UninitUse(const Expr *User, bool AlwaysUninit)
56       : User(User), UninitAfterCall(false), UninitAfterDecl(false),
57         AlwaysUninit(AlwaysUninit) {}
58 
addUninitBranch(Branch B)59   void addUninitBranch(Branch B) {
60     UninitBranches.push_back(B);
61   }
62 
setUninitAfterCall()63   void setUninitAfterCall() { UninitAfterCall = true; }
setUninitAfterDecl()64   void setUninitAfterDecl() { UninitAfterDecl = true; }
65 
66   /// Get the expression containing the uninitialized use.
getUser()67   const Expr *getUser() const { return User; }
68 
69   /// The kind of uninitialized use.
70   enum Kind {
71     /// The use might be uninitialized.
72     Maybe,
73     /// The use is uninitialized whenever a certain branch is taken.
74     Sometimes,
75     /// The use is uninitialized the first time it is reached after we reach
76     /// the variable's declaration.
77     AfterDecl,
78     /// The use is uninitialized the first time it is reached after the function
79     /// is called.
80     AfterCall,
81     /// The use is always uninitialized.
82     Always
83   };
84 
85   /// Get the kind of uninitialized use.
getKind()86   Kind getKind() const {
87     return AlwaysUninit ? Always :
88            UninitAfterCall ? AfterCall :
89            UninitAfterDecl ? AfterDecl :
90            !branch_empty() ? Sometimes : Maybe;
91   }
92 
93   typedef SmallVectorImpl<Branch>::const_iterator branch_iterator;
94   /// Branches which inevitably result in the variable being used uninitialized.
branch_begin()95   branch_iterator branch_begin() const { return UninitBranches.begin(); }
branch_end()96   branch_iterator branch_end() const { return UninitBranches.end(); }
branch_empty()97   bool branch_empty() const { return UninitBranches.empty(); }
98 };
99 
100 class UninitVariablesHandler {
101 public:
UninitVariablesHandler()102   UninitVariablesHandler() {}
103   virtual ~UninitVariablesHandler();
104 
105   /// Called when the uninitialized variable is used at the given expression.
handleUseOfUninitVariable(const VarDecl * vd,const UninitUse & use)106   virtual void handleUseOfUninitVariable(const VarDecl *vd,
107                                          const UninitUse &use) {}
108 
109   /// Called when the uninitialized variable analysis detects the
110   /// idiom 'int x = x'.  All other uses of 'x' within the initializer
111   /// are handled by handleUseOfUninitVariable.
handleSelfInit(const VarDecl * vd)112   virtual void handleSelfInit(const VarDecl *vd) {}
113 };
114 
115 struct UninitVariablesAnalysisStats {
116   unsigned NumVariablesAnalyzed;
117   unsigned NumBlockVisits;
118 };
119 
120 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
121                                        AnalysisDeclContext &ac,
122                                        UninitVariablesHandler &handler,
123                                        UninitVariablesAnalysisStats &stats);
124 
125 }
126 #endif
127