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