clang API Documentation
00001 //= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines APIs for invoking and reported uninitialized values 00011 // warnings. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H 00016 #define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H 00017 00018 #include "clang/AST/Stmt.h" 00019 #include "llvm/ADT/SmallVector.h" 00020 00021 namespace clang { 00022 00023 class AnalysisDeclContext; 00024 class CFG; 00025 class DeclContext; 00026 class Expr; 00027 class VarDecl; 00028 00029 /// A use of a variable, which might be uninitialized. 00030 class UninitUse { 00031 public: 00032 struct Branch { 00033 const Stmt *Terminator; 00034 unsigned Output; 00035 }; 00036 00037 private: 00038 /// The expression which uses this variable. 00039 const Expr *User; 00040 00041 /// Is this use uninitialized whenever the function is called? 00042 bool UninitAfterCall; 00043 00044 /// Is this use uninitialized whenever the variable declaration is reached? 00045 bool UninitAfterDecl; 00046 00047 /// Does this use always see an uninitialized value? 00048 bool AlwaysUninit; 00049 00050 /// This use is always uninitialized if it occurs after any of these branches 00051 /// is taken. 00052 SmallVector<Branch, 2> UninitBranches; 00053 00054 public: 00055 UninitUse(const Expr *User, bool AlwaysUninit) 00056 : User(User), UninitAfterCall(false), UninitAfterDecl(false), 00057 AlwaysUninit(AlwaysUninit) {} 00058 00059 void addUninitBranch(Branch B) { 00060 UninitBranches.push_back(B); 00061 } 00062 00063 void setUninitAfterCall() { UninitAfterCall = true; } 00064 void setUninitAfterDecl() { UninitAfterDecl = true; } 00065 00066 /// Get the expression containing the uninitialized use. 00067 const Expr *getUser() const { return User; } 00068 00069 /// The kind of uninitialized use. 00070 enum Kind { 00071 /// The use might be uninitialized. 00072 Maybe, 00073 /// The use is uninitialized whenever a certain branch is taken. 00074 Sometimes, 00075 /// The use is uninitialized the first time it is reached after we reach 00076 /// the variable's declaration. 00077 AfterDecl, 00078 /// The use is uninitialized the first time it is reached after the function 00079 /// is called. 00080 AfterCall, 00081 /// The use is always uninitialized. 00082 Always 00083 }; 00084 00085 /// Get the kind of uninitialized use. 00086 Kind getKind() const { 00087 return AlwaysUninit ? Always : 00088 UninitAfterCall ? AfterCall : 00089 UninitAfterDecl ? AfterDecl : 00090 !branch_empty() ? Sometimes : Maybe; 00091 } 00092 00093 typedef SmallVectorImpl<Branch>::const_iterator branch_iterator; 00094 /// Branches which inevitably result in the variable being used uninitialized. 00095 branch_iterator branch_begin() const { return UninitBranches.begin(); } 00096 branch_iterator branch_end() const { return UninitBranches.end(); } 00097 bool branch_empty() const { return UninitBranches.empty(); } 00098 }; 00099 00100 class UninitVariablesHandler { 00101 public: 00102 UninitVariablesHandler() {} 00103 virtual ~UninitVariablesHandler(); 00104 00105 /// Called when the uninitialized variable is used at the given expression. 00106 virtual void handleUseOfUninitVariable(const VarDecl *vd, 00107 const UninitUse &use) {} 00108 00109 /// Called when the uninitialized variable analysis detects the 00110 /// idiom 'int x = x'. All other uses of 'x' within the initializer 00111 /// are handled by handleUseOfUninitVariable. 00112 virtual void handleSelfInit(const VarDecl *vd) {} 00113 }; 00114 00115 struct UninitVariablesAnalysisStats { 00116 unsigned NumVariablesAnalyzed; 00117 unsigned NumBlockVisits; 00118 }; 00119 00120 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, 00121 AnalysisDeclContext &ac, 00122 UninitVariablesHandler &handler, 00123 UninitVariablesAnalysisStats &stats); 00124 00125 } 00126 #endif