1289177Speter//= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==// 2289177Speter// 3289177Speter// The LLVM Compiler Infrastructure 4289177Speter// 5289177Speter// This file is distributed under the University of Illinois Open Source 6289177Speter// License. See LICENSE.TXT for details. 7289177Speter// 8289177Speter//===----------------------------------------------------------------------===// 9289177Speter// 10289177Speter// This file defines APIs for invoking and reported uninitialized values 11289177Speter// warnings. 12289177Speter// 13289177Speter//===----------------------------------------------------------------------===// 14289177Speter 15289177Speter#ifndef LLVM_CLANG_UNINIT_VALS_H 16289177Speter#define LLVM_CLANG_UNINIT_VALS_H 17289177Speter 18289177Speter#include "clang/AST/Stmt.h" 19289177Speter#include "llvm/ADT/SmallVector.h" 20289177Speter 21289177Speternamespace clang { 22289177Speter 23289177Speterclass AnalysisDeclContext; 24289177Speterclass CFG; 25289177Speterclass DeclContext; 26289177Speterclass Expr; 27289177Speterclass VarDecl; 28289177Speter 29289177Speter/// A use of a variable, which might be uninitialized. 30289177Speterclass UninitUse { 31289177Speterpublic: 32289177Speter struct Branch { 33289177Speter const Stmt *Terminator; 34289177Speter unsigned Output; 35289177Speter }; 36289177Speter 37289177Speterprivate: 38289177Speter /// The expression which uses this variable. 39289177Speter const Expr *User; 40289177Speter 41289177Speter /// Is this use uninitialized whenever the function is called? 42289177Speter bool UninitAfterCall; 43289177Speter 44289177Speter /// Is this use uninitialized whenever the variable declaration is reached? 45289177Speter bool UninitAfterDecl; 46289177Speter 47289177Speter /// Does this use always see an uninitialized value? 48289177Speter bool AlwaysUninit; 49289177Speter 50289177Speter /// This use is always uninitialized if it occurs after any of these branches 51289177Speter /// is taken. 52289177Speter SmallVector<Branch, 2> UninitBranches; 53289177Speter 54289177Speterpublic: 55289177Speter UninitUse(const Expr *User, bool AlwaysUninit) 56289177Speter : User(User), UninitAfterCall(false), UninitAfterDecl(false), 57289177Speter AlwaysUninit(AlwaysUninit) {} 58289177Speter 59289177Speter void addUninitBranch(Branch B) { 60289177Speter UninitBranches.push_back(B); 61289177Speter } 62289177Speter 63289177Speter void setUninitAfterCall() { UninitAfterCall = true; } 64289177Speter void setUninitAfterDecl() { UninitAfterDecl = true; } 65289177Speter 66289177Speter /// Get the expression containing the uninitialized use. 67289177Speter const Expr *getUser() const { return User; } 68289177Speter 69289177Speter /// The kind of uninitialized use. 70289177Speter enum Kind { 71289177Speter /// The use might be uninitialized. 72289177Speter Maybe, 73289177Speter /// The use is uninitialized whenever a certain branch is taken. 74289177Speter Sometimes, 75289177Speter /// The use is uninitialized the first time it is reached after we reach 76289177Speter /// the variable's declaration. 77289177Speter AfterDecl, 78289177Speter /// The use is uninitialized the first time it is reached after the function 79289177Speter /// is called. 80289177Speter AfterCall, 81289177Speter /// The use is always uninitialized. 82289177Speter Always 83289177Speter }; 84289177Speter 85289177Speter /// Get the kind of uninitialized use. 86289177Speter Kind getKind() const { 87289177Speter return AlwaysUninit ? Always : 88289177Speter UninitAfterCall ? AfterCall : 89289177Speter UninitAfterDecl ? AfterDecl : 90289177Speter !branch_empty() ? Sometimes : Maybe; 91289177Speter } 92289177Speter 93289177Speter typedef SmallVectorImpl<Branch>::const_iterator branch_iterator; 94289177Speter /// Branches which inevitably result in the variable being used uninitialized. 95289177Speter branch_iterator branch_begin() const { return UninitBranches.begin(); } 96289177Speter branch_iterator branch_end() const { return UninitBranches.end(); } 97289177Speter bool branch_empty() const { return UninitBranches.empty(); } 98289177Speter}; 99289177Speter 100289177Speterclass UninitVariablesHandler { 101289177Speterpublic: 102289177Speter UninitVariablesHandler() {} 103289177Speter virtual ~UninitVariablesHandler(); 104289177Speter 105289177Speter /// Called when the uninitialized variable is used at the given expression. 106289177Speter virtual void handleUseOfUninitVariable(const VarDecl *vd, 107289177Speter const UninitUse &use) {} 108289177Speter 109289177Speter /// Called when the uninitialized variable analysis detects the 110289177Speter /// idiom 'int x = x'. All other uses of 'x' within the initializer 111289177Speter /// are handled by handleUseOfUninitVariable. 112289177Speter virtual void handleSelfInit(const VarDecl *vd) {} 113289177Speter}; 114289177Speter 115289177Speterstruct UninitVariablesAnalysisStats { 116289177Speter unsigned NumVariablesAnalyzed; 117289177Speter unsigned NumBlockVisits; 118289177Speter}; 119289177Speter 120289177Spetervoid runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, 121289177Speter AnalysisDeclContext &ac, 122289177Speter UninitVariablesHandler &handler, 123289177Speter UninitVariablesAnalysisStats &stats); 124289177Speter 125289177Speter} 126289177Speter#endif 127289177Speter