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