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/Basic/LLVM.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 Stmt;
28 class VarDecl;
29 
30 /// A use of a variable, which might be uninitialized.
31 class UninitUse {
32 public:
33   struct Branch {
34     const Stmt *Terminator;
35     unsigned Output;
36   };
37 
38 private:
39   /// The expression which uses this variable.
40   const Expr *User;
41 
42   /// Is this use uninitialized whenever the function is called?
43   bool UninitAfterCall = false;
44 
45   /// Is this use uninitialized whenever the variable declaration is reached?
46   bool UninitAfterDecl = false;
47 
48   /// Does this use always see an uninitialized value?
49   bool AlwaysUninit;
50 
51   /// This use is always uninitialized if it occurs after any of these branches
52   /// is taken.
53   SmallVector<Branch, 2> UninitBranches;
54 
55 public:
UninitUse(const Expr * User,bool AlwaysUninit)56   UninitUse(const Expr *User, bool AlwaysUninit)
57       : User(User), 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 
74     /// The use is uninitialized whenever a certain branch is taken.
75     Sometimes,
76 
77     /// The use is uninitialized the first time it is reached after we reach
78     /// the variable's declaration.
79     AfterDecl,
80 
81     /// The use is uninitialized the first time it is reached after the function
82     /// is called.
83     AfterCall,
84 
85     /// The use is always uninitialized.
86     Always
87   };
88 
89   /// Get the kind of uninitialized use.
getKind()90   Kind getKind() const {
91     return AlwaysUninit ? Always :
92            UninitAfterCall ? AfterCall :
93            UninitAfterDecl ? AfterDecl :
94            !branch_empty() ? Sometimes : Maybe;
95   }
96 
97   using branch_iterator = SmallVectorImpl<Branch>::const_iterator;
98 
99   /// Branches which inevitably result in the variable being used uninitialized.
branch_begin()100   branch_iterator branch_begin() const { return UninitBranches.begin(); }
branch_end()101   branch_iterator branch_end() const { return UninitBranches.end(); }
branch_empty()102   bool branch_empty() const { return UninitBranches.empty(); }
103 };
104 
105 class UninitVariablesHandler {
106 public:
107   UninitVariablesHandler() = default;
108   virtual ~UninitVariablesHandler();
109 
110   /// Called when the uninitialized variable is used at the given expression.
handleUseOfUninitVariable(const VarDecl * vd,const UninitUse & use)111   virtual void handleUseOfUninitVariable(const VarDecl *vd,
112                                          const UninitUse &use) {}
113 
114   /// Called when the uninitialized variable analysis detects the
115   /// idiom 'int x = x'.  All other uses of 'x' within the initializer
116   /// are handled by handleUseOfUninitVariable.
handleSelfInit(const VarDecl * vd)117   virtual void handleSelfInit(const VarDecl *vd) {}
118 };
119 
120 struct UninitVariablesAnalysisStats {
121   unsigned NumVariablesAnalyzed;
122   unsigned NumBlockVisits;
123 };
124 
125 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
126                                        AnalysisDeclContext &ac,
127                                        UninitVariablesHandler &handler,
128                                        UninitVariablesAnalysisStats &stats);
129 
130 } // namespace clang
131 
132 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
133