1 //=- UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-=// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines APIs for invoking and reported uninitialized values 10 // warnings. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H 15 #define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H 16 17 #include "clang/Basic/LLVM.h" 18 #include "llvm/ADT/SmallVector.h" 19 20 namespace clang { 21 22 class AnalysisDeclContext; 23 class CFG; 24 class DeclContext; 25 class Expr; 26 class Stmt; 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 = false; 43 44 /// Is this use uninitialized whenever the variable declaration is reached? 45 bool UninitAfterDecl = false; 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), AlwaysUninit(AlwaysUninit) {} 57 addUninitBranch(Branch B)58 void addUninitBranch(Branch B) { 59 UninitBranches.push_back(B); 60 } 61 setUninitAfterCall()62 void setUninitAfterCall() { UninitAfterCall = true; } setUninitAfterDecl()63 void setUninitAfterDecl() { UninitAfterDecl = true; } 64 65 /// Get the expression containing the uninitialized use. getUser()66 const Expr *getUser() const { return User; } 67 68 /// The kind of uninitialized use. 69 enum Kind { 70 /// The use might be uninitialized. 71 Maybe, 72 73 /// The use is uninitialized whenever a certain branch is taken. 74 Sometimes, 75 76 /// The use is uninitialized the first time it is reached after we reach 77 /// the variable's declaration. 78 AfterDecl, 79 80 /// The use is uninitialized the first time it is reached after the function 81 /// is called. 82 AfterCall, 83 84 /// The use is always uninitialized. 85 Always 86 }; 87 88 /// Get the kind of uninitialized use. getKind()89 Kind getKind() const { 90 return AlwaysUninit ? Always : 91 UninitAfterCall ? AfterCall : 92 UninitAfterDecl ? AfterDecl : 93 !branch_empty() ? Sometimes : Maybe; 94 } 95 96 using branch_iterator = SmallVectorImpl<Branch>::const_iterator; 97 98 /// Branches which inevitably result in the variable being used uninitialized. branch_begin()99 branch_iterator branch_begin() const { return UninitBranches.begin(); } branch_end()100 branch_iterator branch_end() const { return UninitBranches.end(); } branch_empty()101 bool branch_empty() const { return UninitBranches.empty(); } 102 }; 103 104 class UninitVariablesHandler { 105 public: 106 UninitVariablesHandler() = default; 107 virtual ~UninitVariablesHandler(); 108 109 /// Called when the uninitialized variable is used at the given expression. handleUseOfUninitVariable(const VarDecl * vd,const UninitUse & use)110 virtual void handleUseOfUninitVariable(const VarDecl *vd, 111 const UninitUse &use) {} 112 113 /// Called when the uninitialized variable analysis detects the 114 /// idiom 'int x = x'. All other uses of 'x' within the initializer 115 /// are handled by handleUseOfUninitVariable. handleSelfInit(const VarDecl * vd)116 virtual void handleSelfInit(const VarDecl *vd) {} 117 }; 118 119 struct UninitVariablesAnalysisStats { 120 unsigned NumVariablesAnalyzed; 121 unsigned NumBlockVisits; 122 }; 123 124 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, 125 AnalysisDeclContext &ac, 126 UninitVariablesHandler &handler, 127 UninitVariablesAnalysisStats &stats); 128 129 } // namespace clang 130 131 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H 132