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
20namespace clang {
21
22class AnalysisDeclContext;
23class CFG;
24class DeclContext;
25class Expr;
26class Stmt;
27class VarDecl;
28
29/// A use of a variable, which might be uninitialized.
30class UninitUse {
31public:
32  struct Branch {
33    const Stmt *Terminator;
34    unsigned Output;
35  };
36
37private:
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
54public:
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
104class UninitVariablesHandler {
105public:
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
123struct UninitVariablesAnalysisStats {
124  unsigned NumVariablesAnalyzed;
125  unsigned NumBlockVisits;
126};
127
128void 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