1289177Speter//= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==//
2289177Speter//
3289177Speter//                     The LLVM Compiler Infrastructure
4289177Speter//
5289177Speter// This file is distributed under the University of Illinois Open Source
6289177Speter// License. See LICENSE.TXT for details.
7289177Speter//
8289177Speter//===----------------------------------------------------------------------===//
9289177Speter//
10289177Speter// This file defines APIs for invoking and reported uninitialized values
11289177Speter// warnings.
12289177Speter//
13289177Speter//===----------------------------------------------------------------------===//
14289177Speter
15289177Speter#ifndef LLVM_CLANG_UNINIT_VALS_H
16289177Speter#define LLVM_CLANG_UNINIT_VALS_H
17289177Speter
18289177Speter#include "clang/AST/Stmt.h"
19289177Speter#include "llvm/ADT/SmallVector.h"
20289177Speter
21289177Speternamespace clang {
22289177Speter
23289177Speterclass AnalysisDeclContext;
24289177Speterclass CFG;
25289177Speterclass DeclContext;
26289177Speterclass Expr;
27289177Speterclass VarDecl;
28289177Speter
29289177Speter/// A use of a variable, which might be uninitialized.
30289177Speterclass UninitUse {
31289177Speterpublic:
32289177Speter  struct Branch {
33289177Speter    const Stmt *Terminator;
34289177Speter    unsigned Output;
35289177Speter  };
36289177Speter
37289177Speterprivate:
38289177Speter  /// The expression which uses this variable.
39289177Speter  const Expr *User;
40289177Speter
41289177Speter  /// Is this use uninitialized whenever the function is called?
42289177Speter  bool UninitAfterCall;
43289177Speter
44289177Speter  /// Is this use uninitialized whenever the variable declaration is reached?
45289177Speter  bool UninitAfterDecl;
46289177Speter
47289177Speter  /// Does this use always see an uninitialized value?
48289177Speter  bool AlwaysUninit;
49289177Speter
50289177Speter  /// This use is always uninitialized if it occurs after any of these branches
51289177Speter  /// is taken.
52289177Speter  SmallVector<Branch, 2> UninitBranches;
53289177Speter
54289177Speterpublic:
55289177Speter  UninitUse(const Expr *User, bool AlwaysUninit)
56289177Speter      : User(User), UninitAfterCall(false), UninitAfterDecl(false),
57289177Speter        AlwaysUninit(AlwaysUninit) {}
58289177Speter
59289177Speter  void addUninitBranch(Branch B) {
60289177Speter    UninitBranches.push_back(B);
61289177Speter  }
62289177Speter
63289177Speter  void setUninitAfterCall() { UninitAfterCall = true; }
64289177Speter  void setUninitAfterDecl() { UninitAfterDecl = true; }
65289177Speter
66289177Speter  /// Get the expression containing the uninitialized use.
67289177Speter  const Expr *getUser() const { return User; }
68289177Speter
69289177Speter  /// The kind of uninitialized use.
70289177Speter  enum Kind {
71289177Speter    /// The use might be uninitialized.
72289177Speter    Maybe,
73289177Speter    /// The use is uninitialized whenever a certain branch is taken.
74289177Speter    Sometimes,
75289177Speter    /// The use is uninitialized the first time it is reached after we reach
76289177Speter    /// the variable's declaration.
77289177Speter    AfterDecl,
78289177Speter    /// The use is uninitialized the first time it is reached after the function
79289177Speter    /// is called.
80289177Speter    AfterCall,
81289177Speter    /// The use is always uninitialized.
82289177Speter    Always
83289177Speter  };
84289177Speter
85289177Speter  /// Get the kind of uninitialized use.
86289177Speter  Kind getKind() const {
87289177Speter    return AlwaysUninit ? Always :
88289177Speter           UninitAfterCall ? AfterCall :
89289177Speter           UninitAfterDecl ? AfterDecl :
90289177Speter           !branch_empty() ? Sometimes : Maybe;
91289177Speter  }
92289177Speter
93289177Speter  typedef SmallVectorImpl<Branch>::const_iterator branch_iterator;
94289177Speter  /// Branches which inevitably result in the variable being used uninitialized.
95289177Speter  branch_iterator branch_begin() const { return UninitBranches.begin(); }
96289177Speter  branch_iterator branch_end() const { return UninitBranches.end(); }
97289177Speter  bool branch_empty() const { return UninitBranches.empty(); }
98289177Speter};
99289177Speter
100289177Speterclass UninitVariablesHandler {
101289177Speterpublic:
102289177Speter  UninitVariablesHandler() {}
103289177Speter  virtual ~UninitVariablesHandler();
104289177Speter
105289177Speter  /// Called when the uninitialized variable is used at the given expression.
106289177Speter  virtual void handleUseOfUninitVariable(const VarDecl *vd,
107289177Speter                                         const UninitUse &use) {}
108289177Speter
109289177Speter  /// Called when the uninitialized variable analysis detects the
110289177Speter  /// idiom 'int x = x'.  All other uses of 'x' within the initializer
111289177Speter  /// are handled by handleUseOfUninitVariable.
112289177Speter  virtual void handleSelfInit(const VarDecl *vd) {}
113289177Speter};
114289177Speter
115289177Speterstruct UninitVariablesAnalysisStats {
116289177Speter  unsigned NumVariablesAnalyzed;
117289177Speter  unsigned NumBlockVisits;
118289177Speter};
119289177Speter
120289177Spetervoid runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
121289177Speter                                       AnalysisDeclContext &ac,
122289177Speter                                       UninitVariablesHandler &handler,
123289177Speter                                       UninitVariablesAnalysisStats &stats);
124289177Speter
125289177Speter}
126289177Speter#endif
127289177Speter