Consumed.h revision 53fe3f55887cddc777d0aff09143483c6b29baa0
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 // FIXME: This can be removed when the attr propagation fix for templated 63 // classes lands. 64 /// \brief Warn about return typestates set for unconsumable types. 65 /// 66 /// \param Loc -- The location of the attributes. 67 /// 68 /// \param TypeName -- The name of the unconsumable type. 69 virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc, 70 StringRef TypeName) {} 71 72 /// \brief Warn about return typestate mismatches. 73 /// \param Loc -- The SourceLocation of the return statement. 74 virtual void warnReturnTypestateMismatch(SourceLocation Loc, 75 StringRef ExpectedState, 76 StringRef ObservedState) {} 77 78 /// \brief Warn about unnecessary-test errors. 79 /// \param VariableName -- The name of the variable that holds the unique 80 /// value. 81 /// 82 /// \param VariableState -- The known state of the value. 83 /// 84 /// \param Loc -- The SourceLocation of the unnecessary test. 85 virtual void warnUnnecessaryTest(StringRef VariableName, 86 StringRef VariableState, 87 SourceLocation Loc) {} 88 89 /// \brief Warn about use-while-consumed errors. 90 /// \param MethodName -- The name of the method that was incorrectly 91 /// invoked. 92 /// 93 /// \param State -- The state the object was used in. 94 /// 95 /// \param Loc -- The SourceLocation of the method invocation. 96 virtual void warnUseOfTempInInvalidState(StringRef MethodName, 97 StringRef State, 98 SourceLocation Loc) {} 99 100 /// \brief Warn about use-while-consumed errors. 101 /// \param MethodName -- The name of the method that was incorrectly 102 /// invoked. 103 /// 104 /// \param State -- The state the object was used in. 105 /// 106 /// \param VariableName -- The name of the variable that holds the unique 107 /// value. 108 /// 109 /// \param Loc -- The SourceLocation of the method invocation. 110 virtual void warnUseInInvalidState(StringRef MethodName, 111 StringRef VariableName, 112 StringRef State, 113 SourceLocation Loc) {} 114 }; 115 116 class ConsumedStateMap { 117 118 typedef llvm::DenseMap<const VarDecl *, ConsumedState> MapType; 119 typedef std::pair<const VarDecl *, ConsumedState> PairType; 120 121 protected: 122 123 bool Reachable; 124 const Stmt *From; 125 MapType Map; 126 127 public: 128 ConsumedStateMap() : Reachable(true), From(NULL) {} 129 ConsumedStateMap(const ConsumedStateMap &Other) 130 : Reachable(Other.Reachable), From(Other.From), Map(Other.Map) {} 131 132 /// \brief Get the consumed state of a given variable. 133 ConsumedState getState(const VarDecl *Var) const; 134 135 /// \brief Merge this state map with another map. 136 void intersect(const ConsumedStateMap *Other); 137 138 void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack, 139 const ConsumedStateMap *LoopBackStates, 140 ConsumedWarningsHandlerBase &WarningsHandler); 141 142 /// \brief Return true if this block is reachable. 143 bool isReachable() const { return Reachable; } 144 145 /// \brief Mark the block as unreachable. 146 void markUnreachable(); 147 148 /// \brief Set the source for a decision about the branching of states. 149 /// \param Source -- The statement that was the origin of a branching 150 /// decision. 151 void setSource(const Stmt *Source) { this->From = Source; } 152 153 /// \brief Set the consumed state of a given variable. 154 void setState(const VarDecl *Var, ConsumedState State); 155 156 /// \brief Remove the variable from our state map. 157 void remove(const VarDecl *Var); 158 159 /// \brief Tests to see if there is a mismatch in the states stored in two 160 /// maps. 161 /// 162 /// \param Other -- The second map to compare against. 163 bool operator!=(const ConsumedStateMap *Other) const; 164 }; 165 166 class ConsumedBlockInfo { 167 std::vector<ConsumedStateMap*> StateMapsArray; 168 std::vector<unsigned int> VisitOrder; 169 170 public: 171 ConsumedBlockInfo() { } 172 173 ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph) 174 : StateMapsArray(NumBlocks, 0), VisitOrder(NumBlocks, 0) { 175 unsigned int VisitOrderCounter = 0; 176 for (PostOrderCFGView::iterator BI = SortedGraph->begin(), 177 BE = SortedGraph->end(); BI != BE; ++BI) { 178 VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++; 179 } 180 } 181 182 bool allBackEdgesVisited(const CFGBlock *CurrBlock, 183 const CFGBlock *TargetBlock); 184 185 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap, 186 bool &AlreadyOwned); 187 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap); 188 189 ConsumedStateMap* borrowInfo(const CFGBlock *Block); 190 191 void discardInfo(const CFGBlock *Block); 192 193 ConsumedStateMap* getInfo(const CFGBlock *Block); 194 195 bool isBackEdge(const CFGBlock *From, const CFGBlock *To); 196 bool isBackEdgeTarget(const CFGBlock *Block); 197 }; 198 199 /// A class that handles the analysis of uniqueness violations. 200 class ConsumedAnalyzer { 201 202 ConsumedBlockInfo BlockInfo; 203 ConsumedStateMap *CurrStates; 204 205 ConsumedState ExpectedReturnState; 206 207 void determineExpectedReturnState(AnalysisDeclContext &AC, 208 const FunctionDecl *D); 209 bool hasConsumableAttributes(const CXXRecordDecl *RD); 210 bool splitState(const CFGBlock *CurrBlock, 211 const ConsumedStmtVisitor &Visitor); 212 213 public: 214 215 ConsumedWarningsHandlerBase &WarningsHandler; 216 217 ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler) 218 : WarningsHandler(WarningsHandler) {} 219 220 ConsumedState getExpectedReturnState() const { return ExpectedReturnState; } 221 222 /// \brief Check a function's CFG for consumed violations. 223 /// 224 /// We traverse the blocks in the CFG, keeping track of the state of each 225 /// value who's type has uniquness annotations. If methods are invoked in 226 /// the wrong state a warning is issued. Each block in the CFG is traversed 227 /// exactly once. 228 void run(AnalysisDeclContext &AC); 229 }; 230}} // end namespace clang::consumed 231 232#endif 233