clang API Documentation

UninitializedValues.h
Go to the documentation of this file.
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