BugReporterVisitor.h revision 685379965c1b105ce89cf4f6c60810932b7f4d0d
1//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- 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// This file declares BugReporterVisitors, which are used to generate enhanced 11// diagnostic traces. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR 16#define LLVM_CLANG_GR_BUGREPORTERVISITOR 17 18#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 19#include "llvm/ADT/FoldingSet.h" 20 21namespace clang { 22 23namespace ento { 24 25class BugReport; 26class BugReporterContext; 27class ExplodedNode; 28class MemRegion; 29class PathDiagnosticPiece; 30 31/// \brief BugReporterVisitors are used to add custom diagnostics along a path. 32/// 33/// Custom visitors should subclass the BugReporterVisitorImpl class for a 34/// default implementation of the clone() method. 35/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 36/// default implementation of clone() will NOT do the right thing, and you 37/// will have to provide your own implementation.) 38class BugReporterVisitor : public llvm::FoldingSetNode { 39public: 40 virtual ~BugReporterVisitor(); 41 42 /// \brief Returns a copy of this BugReporter. 43 /// 44 /// Custom BugReporterVisitors should not override this method directly. 45 /// Instead, they should inherit from BugReporterVisitorImpl and provide 46 /// a protected or public copy constructor. 47 /// 48 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 49 /// default implementation of clone() will NOT do the right thing, and you 50 /// will have to provide your own implementation.) 51 virtual BugReporterVisitor *clone() const = 0; 52 53 /// \brief Return a diagnostic piece which should be associated with the 54 /// given node. 55 /// 56 /// The last parameter can be used to register a new visitor with the given 57 /// BugReport while processing a node. 58 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 59 const ExplodedNode *PrevN, 60 BugReporterContext &BRC, 61 BugReport &BR) = 0; 62 63 /// \brief Provide custom definition for the final diagnostic piece on the 64 /// path - the piece, which is displayed before the path is expanded. 65 /// 66 /// If returns NULL the default implementation will be used. 67 /// Also note that at most one visitor of a BugReport should generate a 68 /// non-NULL end of path diagnostic piece. 69 virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, 70 const ExplodedNode *N, 71 BugReport &BR); 72 73 virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; 74 75 /// \brief Generates the default final diagnostic piece. 76 static PathDiagnosticPiece *getDefaultEndPath(BugReporterContext &BRC, 77 const ExplodedNode *N, 78 BugReport &BR); 79 80}; 81 82/// This class provides a convenience implementation for clone() using the 83/// Curiously-Recurring Template Pattern. If you are implementing a custom 84/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public 85/// or protected copy constructor. 86/// 87/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 88/// default implementation of clone() will NOT do the right thing, and you 89/// will have to provide your own implementation.) 90template <class DERIVED> 91class BugReporterVisitorImpl : public BugReporterVisitor { 92 virtual BugReporterVisitor *clone() const { 93 return new DERIVED(*static_cast<const DERIVED *>(this)); 94 } 95}; 96 97class FindLastStoreBRVisitor 98 : public BugReporterVisitorImpl<FindLastStoreBRVisitor> 99{ 100 const MemRegion *R; 101 SVal V; 102 bool satisfied; 103 const ExplodedNode *StoreSite; 104 105public: 106 /// \brief Convenience method to create a visitor given only the MemRegion. 107 /// Returns NULL if the visitor cannot be created. For example, when the 108 /// corresponding value is unknown. 109 static BugReporterVisitor *createVisitorObject(const ExplodedNode *N, 110 const MemRegion *R); 111 112 /// Creates a visitor for every VarDecl inside a Stmt and registers it with 113 /// the BugReport. 114 static void registerStatementVarDecls(BugReport &BR, const Stmt *S); 115 116 FindLastStoreBRVisitor(SVal v, const MemRegion *r) 117 : R(r), V(v), satisfied(false), StoreSite(0) { 118 assert (!V.isUnknown() && "Cannot track unknown value."); 119 120 // TODO: Does it make sense to allow undef values here? 121 // (If not, also see UndefCapturedBlockVarChecker)? 122 } 123 124 void Profile(llvm::FoldingSetNodeID &ID) const; 125 126 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 127 const ExplodedNode *PrevN, 128 BugReporterContext &BRC, 129 BugReport &BR); 130}; 131 132class TrackConstraintBRVisitor 133 : public BugReporterVisitorImpl<TrackConstraintBRVisitor> 134{ 135 DefinedSVal Constraint; 136 const bool Assumption; 137 bool isSatisfied; 138 139public: 140 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) 141 : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} 142 143 void Profile(llvm::FoldingSetNodeID &ID) const; 144 145 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 146 const ExplodedNode *PrevN, 147 BugReporterContext &BRC, 148 BugReport &BR); 149}; 150 151class NilReceiverBRVisitor 152 : public BugReporterVisitorImpl<NilReceiverBRVisitor> 153{ 154public: 155 void Profile(llvm::FoldingSetNodeID &ID) const { 156 static int x = 0; 157 ID.AddPointer(&x); 158 } 159 160 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 161 const ExplodedNode *PrevN, 162 BugReporterContext &BRC, 163 BugReport &BR); 164}; 165 166/// Visitor that tries to report interesting diagnostics from conditions. 167class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { 168public: 169 void Profile(llvm::FoldingSetNodeID &ID) const { 170 static int x = 0; 171 ID.AddPointer(&x); 172 } 173 174 175 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 176 const ExplodedNode *Prev, 177 BugReporterContext &BRC, 178 BugReport &BR); 179 180 PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, 181 const ExplodedNode *Prev, 182 BugReporterContext &BRC, 183 BugReport &BR); 184 185 PathDiagnosticPiece *VisitTerminator(const Stmt *Term, 186 const ExplodedNode *N, 187 const CFGBlock *srcBlk, 188 const CFGBlock *dstBlk, 189 BugReport &R, 190 BugReporterContext &BRC); 191 192 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 193 bool tookTrue, 194 BugReporterContext &BRC, 195 BugReport &R, 196 const ExplodedNode *N); 197 198 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 199 const DeclRefExpr *DR, 200 const bool tookTrue, 201 BugReporterContext &BRC, 202 BugReport &R, 203 const ExplodedNode *N); 204 205 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 206 const BinaryOperator *BExpr, 207 const bool tookTrue, 208 BugReporterContext &BRC, 209 BugReport &R, 210 const ExplodedNode *N); 211 212 PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString, 213 const Expr *CondVarExpr, 214 const bool tookTrue, 215 BugReporterContext &BRC, 216 BugReport &R, 217 const ExplodedNode *N); 218 219 bool patternMatch(const Expr *Ex, 220 llvm::raw_ostream &Out, 221 BugReporterContext &BRC, 222 BugReport &R, 223 const ExplodedNode *N, 224 llvm::Optional<bool> &prunable); 225}; 226 227namespace bugreporter { 228 229void addTrackNullOrUndefValueVisitor(const ExplodedNode *N, const Stmt *S, 230 BugReport *R); 231 232const Stmt *GetDerefExpr(const ExplodedNode *N); 233const Stmt *GetDenomExpr(const ExplodedNode *N); 234const Stmt *GetRetValExpr(const ExplodedNode *N); 235 236} // end namespace clang 237} // end namespace ento 238} // end namespace bugreporter 239 240 241#endif //LLVM_CLANG_GR__BUGREPORTERVISITOR 242