Consumed.h revision d4f0e1991f42c69111213699fb2d09dedee1cd36
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 enum ConsumedState { 29 // No state information for the given variable. 30 CS_None, 31 32 CS_Unknown, 33 CS_Unconsumed, 34 CS_Consumed 35 }; 36 37 class ConsumedStmtVisitor; 38 39 typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 40 typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 41 typedef std::list<DelayedDiag> DiagList; 42 43 class ConsumedWarningsHandlerBase { 44 45 public: 46 47 virtual ~ConsumedWarningsHandlerBase(); 48 49 /// \brief Emit the warnings and notes left by the analysis. 50 virtual void emitDiagnostics() {} 51 52 /// \brief Warn that a variable's state doesn't match at the entry and exit 53 /// of a loop. 54 /// 55 /// \param Loc -- The location of the end of the loop. 56 /// 57 /// \param VariableName -- The name of the variable that has a mismatched 58 /// state. 59 virtual void warnLoopStateMismatch(SourceLocation Loc, 60 StringRef VariableName) {} 61 62 /// \brief Warn about parameter typestate mismatches upon return. 63 /// 64 /// \param Loc -- The SourceLocation of the return statement. 65 /// 66 /// \param ExpectedState -- The state the return value was expected to be 67 /// in. 68 /// 69 /// \param ObservedState -- The state the return value was observed to be 70 /// in. 71 virtual void warnParamReturnTypestateMismatch(SourceLocation Loc, 72 StringRef VariableName, 73 StringRef ExpectedState, 74 StringRef ObservedState) {}; 75 76 // FIXME: Add documentation. 77 virtual void warnParamTypestateMismatch(SourceLocation LOC, 78 StringRef ExpectedState, 79 StringRef ObservedState) {} 80 81 // FIXME: This can be removed when the attr propagation fix for templated 82 // classes lands. 83 /// \brief Warn about return typestates set for unconsumable types. 84 /// 85 /// \param Loc -- The location of the attributes. 86 /// 87 /// \param TypeName -- The name of the unconsumable type. 88 virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc, 89 StringRef TypeName) {} 90 91 /// \brief Warn about return typestate mismatches. 92 /// 93 /// \param Loc -- The SourceLocation of the return statement. 94 /// 95 /// \param ExpectedState -- The state the return value was expected to be 96 /// in. 97 /// 98 /// \param ObservedState -- The state the return value was observed to be 99 /// in. 100 virtual void warnReturnTypestateMismatch(SourceLocation Loc, 101 StringRef ExpectedState, 102 StringRef ObservedState) {} 103 104 /// \brief Warn about use-while-consumed errors. 105 /// \param MethodName -- The name of the method that was incorrectly 106 /// invoked. 107 /// 108 /// \param State -- The state the object was used in. 109 /// 110 /// \param Loc -- The SourceLocation of the method invocation. 111 virtual void warnUseOfTempInInvalidState(StringRef MethodName, 112 StringRef State, 113 SourceLocation Loc) {} 114 115 /// \brief Warn about use-while-consumed errors. 116 /// \param MethodName -- The name of the method that was incorrectly 117 /// invoked. 118 /// 119 /// \param State -- The state the object was used in. 120 /// 121 /// \param VariableName -- The name of the variable that holds the unique 122 /// value. 123 /// 124 /// \param Loc -- The SourceLocation of the method invocation. 125 virtual void warnUseInInvalidState(StringRef MethodName, 126 StringRef VariableName, 127 StringRef State, 128 SourceLocation Loc) {} 129 }; 130 131 class ConsumedStateMap { 132 133 typedef llvm::DenseMap<const VarDecl *, ConsumedState> MapType; 134 typedef std::pair<const VarDecl *, ConsumedState> PairType; 135 136 protected: 137 138 bool Reachable; 139 const Stmt *From; 140 MapType Map; 141 142 public: 143 ConsumedStateMap() : Reachable(true), From(NULL) {} 144 ConsumedStateMap(const ConsumedStateMap &Other) 145 : Reachable(Other.Reachable), From(Other.From), Map(Other.Map) {} 146 147 /// \brief Warn if any of the parameters being tracked are not in the state 148 /// they were declared to be in upon return from a function. 149 void checkParamsForReturnTypestate(SourceLocation BlameLoc, 150 ConsumedWarningsHandlerBase &WarningsHandler) const; 151 152 /// \brief Get the consumed state of a given variable. 153 ConsumedState getState(const VarDecl *Var) const; 154 155 /// \brief Merge this state map with another map. 156 void intersect(const ConsumedStateMap *Other); 157 158 void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack, 159 const ConsumedStateMap *LoopBackStates, 160 ConsumedWarningsHandlerBase &WarningsHandler); 161 162 /// \brief Return true if this block is reachable. 163 bool isReachable() const { return Reachable; } 164 165 /// \brief Mark the block as unreachable. 166 void markUnreachable(); 167 168 /// \brief Set the source for a decision about the branching of states. 169 /// \param Source -- The statement that was the origin of a branching 170 /// decision. 171 void setSource(const Stmt *Source) { this->From = Source; } 172 173 /// \brief Set the consumed state of a given variable. 174 void setState(const VarDecl *Var, ConsumedState State); 175 176 /// \brief Remove the variable from our state map. 177 void remove(const VarDecl *Var); 178 179 /// \brief Tests to see if there is a mismatch in the states stored in two 180 /// maps. 181 /// 182 /// \param Other -- The second map to compare against. 183 bool operator!=(const ConsumedStateMap *Other) const; 184 }; 185 186 class ConsumedBlockInfo { 187 std::vector<ConsumedStateMap*> StateMapsArray; 188 std::vector<unsigned int> VisitOrder; 189 190 public: 191 ConsumedBlockInfo() { } 192 193 ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph) 194 : StateMapsArray(NumBlocks, 0), VisitOrder(NumBlocks, 0) { 195 unsigned int VisitOrderCounter = 0; 196 for (PostOrderCFGView::iterator BI = SortedGraph->begin(), 197 BE = SortedGraph->end(); BI != BE; ++BI) { 198 VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++; 199 } 200 } 201 202 bool allBackEdgesVisited(const CFGBlock *CurrBlock, 203 const CFGBlock *TargetBlock); 204 205 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap, 206 bool &AlreadyOwned); 207 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap); 208 209 ConsumedStateMap* borrowInfo(const CFGBlock *Block); 210 211 void discardInfo(const CFGBlock *Block); 212 213 ConsumedStateMap* getInfo(const CFGBlock *Block); 214 215 bool isBackEdge(const CFGBlock *From, const CFGBlock *To); 216 bool isBackEdgeTarget(const CFGBlock *Block); 217 }; 218 219 /// A class that handles the analysis of uniqueness violations. 220 class ConsumedAnalyzer { 221 222 ConsumedBlockInfo BlockInfo; 223 ConsumedStateMap *CurrStates; 224 225 ConsumedState ExpectedReturnState; 226 227 void determineExpectedReturnState(AnalysisDeclContext &AC, 228 const FunctionDecl *D); 229 bool hasConsumableAttributes(const CXXRecordDecl *RD); 230 bool splitState(const CFGBlock *CurrBlock, 231 const ConsumedStmtVisitor &Visitor); 232 233 public: 234 235 ConsumedWarningsHandlerBase &WarningsHandler; 236 237 ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler) 238 : WarningsHandler(WarningsHandler) {} 239 240 ConsumedState getExpectedReturnState() const { return ExpectedReturnState; } 241 242 /// \brief Check a function's CFG for consumed violations. 243 /// 244 /// We traverse the blocks in the CFG, keeping track of the state of each 245 /// value who's type has uniquness annotations. If methods are invoked in 246 /// the wrong state a warning is issued. Each block in the CFG is traversed 247 /// exactly once. 248 void run(AnalysisDeclContext &AC); 249 }; 250}} // end namespace clang::consumed 251 252#endif 253