clang API Documentation
00001 //===- Consumed.h ----------------------------------------------*- C++ --*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // A intra-procedural analysis for checking consumed properties. This is based, 00011 // in part, on research on linear types. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H 00016 #define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H 00017 00018 #include "clang/AST/DeclCXX.h" 00019 #include "clang/AST/ExprCXX.h" 00020 #include "clang/AST/StmtCXX.h" 00021 #include "clang/Analysis/Analyses/PostOrderCFGView.h" 00022 #include "clang/Analysis/AnalysisContext.h" 00023 #include "clang/Basic/SourceLocation.h" 00024 00025 namespace clang { 00026 namespace consumed { 00027 00028 enum ConsumedState { 00029 // No state information for the given variable. 00030 CS_None, 00031 00032 CS_Unknown, 00033 CS_Unconsumed, 00034 CS_Consumed 00035 }; 00036 00037 class ConsumedStmtVisitor; 00038 00039 typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 00040 typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 00041 typedef std::list<DelayedDiag> DiagList; 00042 00043 class ConsumedWarningsHandlerBase { 00044 00045 public: 00046 00047 virtual ~ConsumedWarningsHandlerBase(); 00048 00049 /// \brief Emit the warnings and notes left by the analysis. 00050 virtual void emitDiagnostics() {} 00051 00052 /// \brief Warn that a variable's state doesn't match at the entry and exit 00053 /// of a loop. 00054 /// 00055 /// \param Loc -- The location of the end of the loop. 00056 /// 00057 /// \param VariableName -- The name of the variable that has a mismatched 00058 /// state. 00059 virtual void warnLoopStateMismatch(SourceLocation Loc, 00060 StringRef VariableName) {} 00061 00062 /// \brief Warn about parameter typestate mismatches upon return. 00063 /// 00064 /// \param Loc -- The SourceLocation of the return statement. 00065 /// 00066 /// \param ExpectedState -- The state the return value was expected to be 00067 /// in. 00068 /// 00069 /// \param ObservedState -- The state the return value was observed to be 00070 /// in. 00071 virtual void warnParamReturnTypestateMismatch(SourceLocation Loc, 00072 StringRef VariableName, 00073 StringRef ExpectedState, 00074 StringRef ObservedState) {}; 00075 00076 // FIXME: Add documentation. 00077 virtual void warnParamTypestateMismatch(SourceLocation LOC, 00078 StringRef ExpectedState, 00079 StringRef ObservedState) {} 00080 00081 // FIXME: This can be removed when the attr propagation fix for templated 00082 // classes lands. 00083 /// \brief Warn about return typestates set for unconsumable types. 00084 /// 00085 /// \param Loc -- The location of the attributes. 00086 /// 00087 /// \param TypeName -- The name of the unconsumable type. 00088 virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc, 00089 StringRef TypeName) {} 00090 00091 /// \brief Warn about return typestate mismatches. 00092 /// 00093 /// \param Loc -- The SourceLocation of the return statement. 00094 /// 00095 /// \param ExpectedState -- The state the return value was expected to be 00096 /// in. 00097 /// 00098 /// \param ObservedState -- The state the return value was observed to be 00099 /// in. 00100 virtual void warnReturnTypestateMismatch(SourceLocation Loc, 00101 StringRef ExpectedState, 00102 StringRef ObservedState) {} 00103 00104 /// \brief Warn about use-while-consumed errors. 00105 /// \param MethodName -- The name of the method that was incorrectly 00106 /// invoked. 00107 /// 00108 /// \param State -- The state the object was used in. 00109 /// 00110 /// \param Loc -- The SourceLocation of the method invocation. 00111 virtual void warnUseOfTempInInvalidState(StringRef MethodName, 00112 StringRef State, 00113 SourceLocation Loc) {} 00114 00115 /// \brief Warn about use-while-consumed errors. 00116 /// \param MethodName -- The name of the method that was incorrectly 00117 /// invoked. 00118 /// 00119 /// \param State -- The state the object was used in. 00120 /// 00121 /// \param VariableName -- The name of the variable that holds the unique 00122 /// value. 00123 /// 00124 /// \param Loc -- The SourceLocation of the method invocation. 00125 virtual void warnUseInInvalidState(StringRef MethodName, 00126 StringRef VariableName, 00127 StringRef State, 00128 SourceLocation Loc) {} 00129 }; 00130 00131 class ConsumedStateMap { 00132 00133 typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType; 00134 typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState> 00135 TmpMapType; 00136 00137 protected: 00138 00139 bool Reachable; 00140 const Stmt *From; 00141 VarMapType VarMap; 00142 TmpMapType TmpMap; 00143 00144 public: 00145 ConsumedStateMap() : Reachable(true), From(nullptr) {} 00146 ConsumedStateMap(const ConsumedStateMap &Other) 00147 : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap), 00148 TmpMap() {} 00149 00150 /// \brief Warn if any of the parameters being tracked are not in the state 00151 /// they were declared to be in upon return from a function. 00152 void checkParamsForReturnTypestate(SourceLocation BlameLoc, 00153 ConsumedWarningsHandlerBase &WarningsHandler) const; 00154 00155 /// \brief Clear the TmpMap. 00156 void clearTemporaries(); 00157 00158 /// \brief Get the consumed state of a given variable. 00159 ConsumedState getState(const VarDecl *Var) const; 00160 00161 /// \brief Get the consumed state of a given temporary value. 00162 ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const; 00163 00164 /// \brief Merge this state map with another map. 00165 void intersect(const ConsumedStateMap *Other); 00166 00167 void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack, 00168 const ConsumedStateMap *LoopBackStates, 00169 ConsumedWarningsHandlerBase &WarningsHandler); 00170 00171 /// \brief Return true if this block is reachable. 00172 bool isReachable() const { return Reachable; } 00173 00174 /// \brief Mark the block as unreachable. 00175 void markUnreachable(); 00176 00177 /// \brief Set the source for a decision about the branching of states. 00178 /// \param Source -- The statement that was the origin of a branching 00179 /// decision. 00180 void setSource(const Stmt *Source) { this->From = Source; } 00181 00182 /// \brief Set the consumed state of a given variable. 00183 void setState(const VarDecl *Var, ConsumedState State); 00184 00185 /// \brief Set the consumed state of a given temporary value. 00186 void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State); 00187 00188 /// \brief Remove the temporary value from our state map. 00189 void remove(const CXXBindTemporaryExpr *Tmp); 00190 00191 /// \brief Tests to see if there is a mismatch in the states stored in two 00192 /// maps. 00193 /// 00194 /// \param Other -- The second map to compare against. 00195 bool operator!=(const ConsumedStateMap *Other) const; 00196 }; 00197 00198 class ConsumedBlockInfo { 00199 std::vector<ConsumedStateMap*> StateMapsArray; 00200 std::vector<unsigned int> VisitOrder; 00201 00202 public: 00203 ConsumedBlockInfo() { } 00204 ~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); } 00205 00206 ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph) 00207 : StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) { 00208 unsigned int VisitOrderCounter = 0; 00209 for (PostOrderCFGView::iterator BI = SortedGraph->begin(), 00210 BE = SortedGraph->end(); BI != BE; ++BI) { 00211 VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++; 00212 } 00213 } 00214 00215 bool allBackEdgesVisited(const CFGBlock *CurrBlock, 00216 const CFGBlock *TargetBlock); 00217 00218 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap, 00219 bool &AlreadyOwned); 00220 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap); 00221 00222 ConsumedStateMap* borrowInfo(const CFGBlock *Block); 00223 00224 void discardInfo(const CFGBlock *Block); 00225 00226 ConsumedStateMap* getInfo(const CFGBlock *Block); 00227 00228 bool isBackEdge(const CFGBlock *From, const CFGBlock *To); 00229 bool isBackEdgeTarget(const CFGBlock *Block); 00230 }; 00231 00232 /// A class that handles the analysis of uniqueness violations. 00233 class ConsumedAnalyzer { 00234 00235 ConsumedBlockInfo BlockInfo; 00236 ConsumedStateMap *CurrStates; 00237 00238 ConsumedState ExpectedReturnState; 00239 00240 void determineExpectedReturnState(AnalysisDeclContext &AC, 00241 const FunctionDecl *D); 00242 bool hasConsumableAttributes(const CXXRecordDecl *RD); 00243 bool splitState(const CFGBlock *CurrBlock, 00244 const ConsumedStmtVisitor &Visitor); 00245 00246 public: 00247 00248 ConsumedWarningsHandlerBase &WarningsHandler; 00249 00250 ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler) 00251 : WarningsHandler(WarningsHandler) {} 00252 00253 ConsumedState getExpectedReturnState() const { return ExpectedReturnState; } 00254 00255 /// \brief Check a function's CFG for consumed violations. 00256 /// 00257 /// We traverse the blocks in the CFG, keeping track of the state of each 00258 /// value who's type has uniquness annotations. If methods are invoked in 00259 /// the wrong state a warning is issued. Each block in the CFG is traversed 00260 /// exactly once. 00261 void run(AnalysisDeclContext &AC); 00262 }; 00263 }} // end namespace clang::consumed 00264 00265 #endif