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_UNINIT_VALS_H 16 #define LLVM_CLANG_UNINIT_VALS_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 /// Does this use always see an uninitialized value? 42 bool AlwaysUninit; 43 44 /// This use is always uninitialized if it occurs after any of these branches 45 /// is taken. 46 SmallVector<Branch, 2> UninitBranches; 47 48 public: 49 UninitUse(const Expr *User, bool AlwaysUninit) : 50 User(User), AlwaysUninit(AlwaysUninit) {} 51 52 void addUninitBranch(Branch B) { 53 UninitBranches.push_back(B); 54 } 55 56 /// Get the expression containing the uninitialized use. 57 const Expr *getUser() const { return User; } 58 59 /// The kind of uninitialized use. 60 enum Kind { 61 /// The use might be uninitialized. 62 Maybe, 63 /// The use is uninitialized whenever a certain branch is taken. 64 Sometimes, 65 /// The use is always uninitialized. 66 Always 67 }; 68 69 /// Get the kind of uninitialized use. 70 Kind getKind() const { 71 return AlwaysUninit ? Always : 72 !branch_empty() ? Sometimes : Maybe; 73 } 74 75 typedef SmallVectorImpl<Branch>::const_iterator branch_iterator; 76 /// Branches which inevitably result in the variable being used uninitialized. 77 branch_iterator branch_begin() const { return UninitBranches.begin(); } 78 branch_iterator branch_end() const { return UninitBranches.end(); } 79 bool branch_empty() const { return UninitBranches.empty(); } 80 }; 81 82 class UninitVariablesHandler { 83 public: 84 UninitVariablesHandler() {} 85 virtual ~UninitVariablesHandler(); 86 87 /// Called when the uninitialized variable is used at the given expression. 88 virtual void handleUseOfUninitVariable(const VarDecl *vd, 89 const UninitUse &use) {} 90 91 /// Called when the uninitialized variable analysis detects the 92 /// idiom 'int x = x'. All other uses of 'x' within the initializer 93 /// are handled by handleUseOfUninitVariable. 94 virtual void handleSelfInit(const VarDecl *vd) {} 95 }; 96 97 struct UninitVariablesAnalysisStats { 98 unsigned NumVariablesAnalyzed; 99 unsigned NumBlockVisits; 100 }; 101 102 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, 103 AnalysisDeclContext &ac, 104 UninitVariablesHandler &handler, 105 UninitVariablesAnalysisStats &stats); 106 107 } 108 #endif 109