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