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 /// Is this use a const reference to this variable? 51 bool ConstRefUse = false; 52 53 /// Is this use a const pointer to this variable? 54 bool ConstPtrUse = false; 55 56 /// This use is always uninitialized if it occurs after any of these branches 57 /// is taken. 58 SmallVector<Branch, 2> UninitBranches; 59 60 public: UninitUse(const Expr * User,bool AlwaysUninit)61 UninitUse(const Expr *User, bool AlwaysUninit) 62 : User(User), AlwaysUninit(AlwaysUninit) {} 63 addUninitBranch(Branch B)64 void addUninitBranch(Branch B) { 65 UninitBranches.push_back(B); 66 } 67 setUninitAfterCall()68 void setUninitAfterCall() { UninitAfterCall = true; } setUninitAfterDecl()69 void setUninitAfterDecl() { UninitAfterDecl = true; } setConstRefUse()70 void setConstRefUse() { ConstRefUse = true; } setConstPtrUse()71 void setConstPtrUse() { ConstPtrUse = true; } 72 73 /// Get the expression containing the uninitialized use. getUser()74 const Expr *getUser() const { return User; } 75 isConstRefUse()76 bool isConstRefUse() const { return ConstRefUse; } isConstPtrUse()77 bool isConstPtrUse() const { return ConstPtrUse; } isConstRefOrPtrUse()78 bool isConstRefOrPtrUse() const { return ConstRefUse || ConstPtrUse; } 79 80 /// The kind of uninitialized use. 81 enum Kind { 82 /// The use might be uninitialized. 83 Maybe, 84 85 /// The use is uninitialized whenever a certain branch is taken. 86 Sometimes, 87 88 /// The use is uninitialized the first time it is reached after we reach 89 /// the variable's declaration. 90 AfterDecl, 91 92 /// The use is uninitialized the first time it is reached after the function 93 /// is called. 94 AfterCall, 95 96 /// The use is always uninitialized. 97 Always 98 }; 99 100 /// Get the kind of uninitialized use. getKind()101 Kind getKind() const { 102 return AlwaysUninit ? Always : 103 UninitAfterCall ? AfterCall : 104 UninitAfterDecl ? AfterDecl : 105 !branch_empty() ? Sometimes : Maybe; 106 } 107 108 using branch_iterator = SmallVectorImpl<Branch>::const_iterator; 109 110 /// Branches which inevitably result in the variable being used uninitialized. branch_begin()111 branch_iterator branch_begin() const { return UninitBranches.begin(); } branch_end()112 branch_iterator branch_end() const { return UninitBranches.end(); } branch_empty()113 bool branch_empty() const { return UninitBranches.empty(); } 114 }; 115 116 class UninitVariablesHandler { 117 public: 118 UninitVariablesHandler() = default; 119 virtual ~UninitVariablesHandler(); 120 121 /// Called when the uninitialized variable is used at the given expression. handleUseOfUninitVariable(const VarDecl * vd,const UninitUse & use)122 virtual void handleUseOfUninitVariable(const VarDecl *vd, 123 const UninitUse &use) {} 124 125 /// Called when the uninitialized variable analysis detects the 126 /// idiom 'int x = x'. All other uses of 'x' within the initializer 127 /// are handled by handleUseOfUninitVariable. handleSelfInit(const VarDecl * vd)128 virtual void handleSelfInit(const VarDecl *vd) {} 129 }; 130 131 struct UninitVariablesAnalysisStats { 132 unsigned NumVariablesAnalyzed; 133 unsigned NumBlockVisits; 134 }; 135 136 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, 137 AnalysisDeclContext &ac, 138 UninitVariablesHandler &handler, 139 UninitVariablesAnalysisStats &stats); 140 141 } // namespace clang 142 143 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H 144