Consumed.h revision 2d84f6b563e39c1e90e4d3d7e6846d46bc58ff5d
1//===- Consumed.h ----------------------------------------------*- 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// A intra-procedural analysis for checking consumed properties.  This is based,
11// in part, on research on linear types.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_CONSUMED_H
16#define LLVM_CLANG_CONSUMED_H
17
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/StmtCXX.h"
21#include "clang/Analysis/AnalysisContext.h"
22#include "clang/Analysis/Analyses/PostOrderCFGView.h"
23#include "clang/Basic/SourceLocation.h"
24
25namespace clang {
26namespace consumed {
27
28  typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
29  typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
30  typedef std::list<DelayedDiag> DiagList;
31
32  class ConsumedWarningsHandlerBase {
33
34  public:
35
36    virtual ~ConsumedWarningsHandlerBase();
37
38    /// \brief Emit the warnings and notes left by the analysis.
39    virtual void emitDiagnostics() {}
40
41    /// Warn about unnecessary-test errors.
42    /// \param VariableName -- The name of the variable that holds the unique
43    /// value.
44    ///
45    /// \param Loc -- The SourceLocation of the unnecessary test.
46    virtual void warnUnnecessaryTest(StringRef VariableName,
47                                     StringRef VariableState,
48                                     SourceLocation Loc) {}
49
50    /// Warn about use-while-consumed errors.
51    /// \param MethodName -- The name of the method that was incorrectly
52    /// invoked.
53    ///
54    /// \param VariableName -- The name of the variable that holds the unique
55    /// value.
56    ///
57    /// \param Loc -- The SourceLocation of the method invocation.
58    virtual void warnUseOfTempWhileConsumed(StringRef MethodName,
59                                            SourceLocation Loc) {}
60
61    /// Warn about use-in-unknown-state errors.
62    /// \param MethodName -- The name of the method that was incorrectly
63    /// invoked.
64    ///
65    /// \param VariableName -- The name of the variable that holds the unique
66    /// value.
67    ///
68    /// \param Loc -- The SourceLocation of the method invocation.
69    virtual void warnUseOfTempInUnknownState(StringRef MethodName,
70                                             SourceLocation Loc) {}
71
72    /// Warn about use-while-consumed errors.
73    /// \param MethodName -- The name of the method that was incorrectly
74    /// invoked.
75    ///
76    /// \param VariableName -- The name of the variable that holds the unique
77    /// value.
78    ///
79    /// \param Loc -- The SourceLocation of the method invocation.
80    virtual void warnUseWhileConsumed(StringRef MethodName,
81                                      StringRef VariableName,
82                                      SourceLocation Loc) {}
83
84    /// Warn about use-in-unknown-state errors.
85    /// \param MethodName -- The name of the method that was incorrectly
86    /// invoked.
87    ///
88    /// \param VariableName -- The name of the variable that holds the unique
89    /// value.
90    ///
91    /// \param Loc -- The SourceLocation of the method invocation.
92    virtual void warnUseInUnknownState(StringRef MethodName,
93                                       StringRef VariableName,
94                                       SourceLocation Loc) {}
95  };
96
97  enum ConsumedState {
98    // No state information for the given variable.
99    CS_None,
100
101    CS_Unknown,
102    CS_Unconsumed,
103    CS_Consumed
104  };
105
106  class ConsumedStateMap {
107
108    typedef llvm::DenseMap<const VarDecl *, ConsumedState> MapType;
109    typedef std::pair<const VarDecl *, ConsumedState> PairType;
110
111  protected:
112
113    MapType Map;
114
115  public:
116    /// \brief Get the consumed state of a given variable.
117    ConsumedState getState(const VarDecl *Var);
118
119    /// \brief Merge this state map with another map.
120    void intersect(const ConsumedStateMap *Other);
121
122    /// \brief Mark all variables as unknown.
123    void makeUnknown();
124
125    /// \brief Set the consumed state of a given variable.
126    void setState(const VarDecl *Var, ConsumedState State);
127  };
128
129  class ConsumedBlockInfo {
130
131    ConsumedStateMap **StateMapsArray;
132    PostOrderCFGView::CFGBlockSet VisitedBlocks;
133
134  public:
135
136    ConsumedBlockInfo() : StateMapsArray(NULL) {}
137
138    ConsumedBlockInfo(const CFG *CFGraph)
139      : StateMapsArray(new ConsumedStateMap*[CFGraph->getNumBlockIDs()]()),
140        VisitedBlocks(CFGraph) {}
141
142    void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
143                 bool &AlreadyOwned);
144    void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap);
145
146    ConsumedStateMap* getInfo(const CFGBlock *Block);
147
148    void markVisited(const CFGBlock *Block);
149  };
150
151  struct VarTestResult {
152    const VarDecl *Var;
153    SourceLocation Loc;
154    bool UnconsumedInTrueBranch;
155
156    VarTestResult() : Var(NULL), Loc(), UnconsumedInTrueBranch(true) {}
157
158    VarTestResult(const VarDecl *Var, SourceLocation Loc,
159                  bool UnconsumedInTrueBranch)
160      : Var(Var), Loc(Loc), UnconsumedInTrueBranch(UnconsumedInTrueBranch) {}
161  };
162
163  /// A class that handles the analysis of uniqueness violations.
164  class ConsumedAnalyzer {
165
166    typedef llvm::DenseMap<const CXXRecordDecl *, bool> CacheMapType;
167    typedef std::pair<const CXXRecordDecl *, bool> CachePairType;
168
169    ConsumedBlockInfo BlockInfo;
170    ConsumedStateMap *CurrStates;
171
172    CacheMapType ConsumableTypeCache;
173
174    bool hasConsumableAttributes(const CXXRecordDecl *RD);
175    void splitState(const CFGBlock *CurrBlock, const IfStmt *Terminator);
176
177  public:
178
179    ConsumedWarningsHandlerBase &WarningsHandler;
180
181    ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
182        : WarningsHandler(WarningsHandler) {}
183
184    /// \brief Check to see if the type is a consumable type.
185    bool isConsumableType(QualType Type);
186
187    /// \brief Check a function's CFG for consumed violations.
188    ///
189    /// We traverse the blocks in the CFG, keeping track of the state of each
190    /// value who's type has uniquness annotations.  If methods are invoked in
191    /// the wrong state a warning is issued.  Each block in the CFG is traversed
192    /// exactly once.
193    void run(AnalysisDeclContext &AC);
194  };
195
196  /// \brief Check to see if a function tests an object's validity.
197  bool isTestingFunction(const CXXMethodDecl *MethodDecl);
198
199}} // end namespace clang::consumed
200
201#endif
202