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