1df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===- Consumed.h ----------------------------------------------*- C++ --*-===//
2df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
3df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//                     The LLVM Compiler Infrastructure
4df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
5df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// This file is distributed under the University of Illinois Open Source
6df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// License. See LICENSE.TXT for details.
7df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
8df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===//
9df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
10df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// A intra-procedural analysis for checking consumed properties.  This is based,
11df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// in part, on research on linear types.
12df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
13df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===//
14df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
15df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#ifndef LLVM_CLANG_CONSUMED_H
16df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#define LLVM_CLANG_CONSUMED_H
17df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
18df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/DeclCXX.h"
19df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/ExprCXX.h"
20df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/StmtCXX.h"
21df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/Analyses/PostOrderCFGView.h"
22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Analysis/AnalysisContext.h"
23df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Basic/SourceLocation.h"
24df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
25df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace clang {
26df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace consumed {
27b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
2866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  enum ConsumedState {
2966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    // No state information for the given variable.
3066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    CS_None,
3166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
3266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    CS_Unknown,
3366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    CS_Unconsumed,
3466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    CS_Consumed
3566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  };
3666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
37b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  class ConsumedStmtVisitor;
38b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
392d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
402d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
412d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  typedef std::list<DelayedDiag> DiagList;
422d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
432d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  class ConsumedWarningsHandlerBase {
442d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
452d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  public:
462d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
472d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    virtual ~ConsumedWarningsHandlerBase();
482d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
492d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// \brief Emit the warnings and notes left by the analysis.
502d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    virtual void emitDiagnostics() {}
510e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
527385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// \brief Warn that a variable's state doesn't match at the entry and exit
537385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// of a loop.
547385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    ///
557385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// \param Loc -- The location of the end of the loop.
567385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    ///
577385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// \param VariableName -- The name of the variable that has a mismatched
587385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// state.
597385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    virtual void warnLoopStateMismatch(SourceLocation Loc,
607385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                       StringRef VariableName) {}
617385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
62cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \brief Warn about parameter typestate mismatches upon return.
63cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    ///
64cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \param Loc -- The SourceLocation of the return statement.
65cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    ///
66cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \param ExpectedState -- The state the return value was expected to be
67cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// in.
68cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    ///
69cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \param ObservedState -- The state the return value was observed to be
70cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// in.
71cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
72cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins                                                  StringRef VariableName,
73cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins                                                  StringRef ExpectedState,
74cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins                                                  StringRef ObservedState) {};
75cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
76d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins    // FIXME: Add documentation.
77d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins    virtual void warnParamTypestateMismatch(SourceLocation LOC,
78d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins                                            StringRef ExpectedState,
79d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins                                            StringRef ObservedState) {}
80d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins
810e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    // FIXME: This can be removed when the attr propagation fix for templated
820e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    //        classes lands.
830e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    /// \brief Warn about return typestates set for unconsumable types.
840e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    ///
850e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    /// \param Loc -- The location of the attributes.
860e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    ///
870e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    /// \param TypeName -- The name of the unconsumable type.
880e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
890e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins                                                        StringRef TypeName) {}
900e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
910e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    /// \brief Warn about return typestate mismatches.
92cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    ///
930e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    /// \param Loc -- The SourceLocation of the return statement.
94cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    ///
95cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \param ExpectedState -- The state the return value was expected to be
96cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// in.
97cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    ///
98cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \param ObservedState -- The state the return value was observed to be
99cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// in.
1000e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    virtual void warnReturnTypestateMismatch(SourceLocation Loc,
1010e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins                                             StringRef ExpectedState,
1020e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins                                             StringRef ObservedState) {}
1032d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
104b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// \brief Warn about use-while-consumed errors.
1052d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// \param MethodName -- The name of the method that was incorrectly
1062d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// invoked.
1072d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    ///
10866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    /// \param State -- The state the object was used in.
1092d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    ///
1102d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// \param Loc -- The SourceLocation of the method invocation.
11166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    virtual void warnUseOfTempInInvalidState(StringRef MethodName,
11266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins                                             StringRef State,
1132d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner                                             SourceLocation Loc) {}
1142d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
115b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// \brief Warn about use-while-consumed errors.
1162d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// \param MethodName -- The name of the method that was incorrectly
1172d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// invoked.
1182d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    ///
11966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    /// \param State -- The state the object was used in.
1202d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    ///
1212d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// \param VariableName -- The name of the variable that holds the unique
1222d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// value.
1232d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    ///
1242d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    /// \param Loc -- The SourceLocation of the method invocation.
12566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    virtual void warnUseInInvalidState(StringRef MethodName,
1262d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner                                       StringRef VariableName,
12766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins                                       StringRef State,
1282d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner                                       SourceLocation Loc) {}
1292d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  };
1302d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
131df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  class ConsumedStateMap {
132df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1334c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType;
1344c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>
1354c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins            TmpMapType;
136df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
137df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  protected:
138df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
139b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    bool Reachable;
140b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    const Stmt *From;
1414c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    VarMapType VarMap;
1424c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    TmpMapType TmpMap;
143df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
144df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  public:
1456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ConsumedStateMap() : Reachable(true), From(nullptr) {}
146b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ConsumedStateMap(const ConsumedStateMap &Other)
1474c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
1484c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins        TmpMap() {}
149b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
150cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// \brief Warn if any of the parameters being tracked are not in the state
151cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    /// they were declared to be in upon return from a function.
152cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    void checkParamsForReturnTypestate(SourceLocation BlameLoc,
153cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins      ConsumedWarningsHandlerBase &WarningsHandler) const;
154cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
1554c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    /// \brief Clear the TmpMap.
1564c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    void clearTemporaries();
1574c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
158df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// \brief Get the consumed state of a given variable.
1597385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    ConsumedState getState(const VarDecl *Var) const;
160df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1614c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    /// \brief Get the consumed state of a given temporary value.
1624c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
1634c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
164df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// \brief Merge this state map with another map.
165df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    void intersect(const ConsumedStateMap *Other);
166df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1677385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
1687385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      const ConsumedStateMap *LoopBackStates,
1697385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      ConsumedWarningsHandlerBase &WarningsHandler);
1707385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
171b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// \brief Return true if this block is reachable.
172b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    bool isReachable() const { return Reachable; }
173b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
174b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// \brief Mark the block as unreachable.
175b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    void markUnreachable();
176b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
177b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// \brief Set the source for a decision about the branching of states.
178b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// \param Source -- The statement that was the origin of a branching
179b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    /// decision.
180b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    void setSource(const Stmt *Source) { this->From = Source; }
181b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
182df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// \brief Set the consumed state of a given variable.
183df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    void setState(const VarDecl *Var, ConsumedState State);
1845fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
1854c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    /// \brief Set the consumed state of a given temporary value.
1864c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
1874c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
1886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    /// \brief Remove the temporary value from our state map.
1896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    void remove(const CXXBindTemporaryExpr *Tmp);
1907385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1917385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// \brief Tests to see if there is a mismatch in the states stored in two
1927385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// maps.
1937385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    ///
1947385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    /// \param Other -- The second map to compare against.
1957385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    bool operator!=(const ConsumedStateMap *Other) const;
196df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  };
197df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
198df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  class ConsumedBlockInfo {
1997385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    std::vector<ConsumedStateMap*> StateMapsArray;
20053fe3f55887cddc777d0aff09143483c6b29baa0DeLesley Hutchins    std::vector<unsigned int> VisitOrder;
201df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
202df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  public:
20353fe3f55887cddc777d0aff09143483c6b29baa0DeLesley Hutchins    ConsumedBlockInfo() { }
2046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); }
2056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2067385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
2076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        : StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) {
2087385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      unsigned int VisitOrderCounter = 0;
2097385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
2107385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins           BE = SortedGraph->end(); BI != BE; ++BI) {
2117385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins        VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++;
2127385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      }
2137385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    }
2147385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
2157385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    bool allBackEdgesVisited(const CFGBlock *CurrBlock,
2167385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                             const CFGBlock *TargetBlock);
217df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
218df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
219df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                 bool &AlreadyOwned);
220df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap);
221df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
2227385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    ConsumedStateMap* borrowInfo(const CFGBlock *Block);
2237385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
2247385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    void discardInfo(const CFGBlock *Block);
2257385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
226df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedStateMap* getInfo(const CFGBlock *Block);
227df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
2287385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
2297385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    bool isBackEdgeTarget(const CFGBlock *Block);
230df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  };
231df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
232df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  /// A class that handles the analysis of uniqueness violations.
233df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  class ConsumedAnalyzer {
234df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
235df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedBlockInfo BlockInfo;
236df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedStateMap *CurrStates;
237df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
2380e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    ConsumedState ExpectedReturnState;
2390e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
240a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    void determineExpectedReturnState(AnalysisDeclContext &AC,
241a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie                                      const FunctionDecl *D);
242df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    bool hasConsumableAttributes(const CXXRecordDecl *RD);
243b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    bool splitState(const CFGBlock *CurrBlock,
244b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                    const ConsumedStmtVisitor &Visitor);
245df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
246df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  public:
247df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
248df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedWarningsHandlerBase &WarningsHandler;
2492d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
2502d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner    ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
2512d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner        : WarningsHandler(WarningsHandler) {}
2522d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
2530e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
2540e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
255df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// \brief Check a function's CFG for consumed violations.
256df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ///
257df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// We traverse the blocks in the CFG, keeping track of the state of each
258df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// value who's type has uniquness annotations.  If methods are invoked in
259df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// the wrong state a warning is issued.  Each block in the CFG is traversed
260df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    /// exactly once.
261df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    void run(AnalysisDeclContext &AC);
262df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  };
263df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}} // end namespace clang::consumed
264df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
265df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#endif
266