clang API Documentation
00001 //===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- 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 // This file declares BugReporterVisitors, which are used to generate enhanced 00011 // diagnostic traces. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR 00016 #define LLVM_CLANG_GR_BUGREPORTERVISITOR 00017 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 00019 #include "llvm/ADT/FoldingSet.h" 00020 00021 namespace clang { 00022 00023 namespace ento { 00024 00025 class BugReport; 00026 class BugReporterContext; 00027 class ExplodedNode; 00028 class MemRegion; 00029 class PathDiagnosticPiece; 00030 00031 /// \brief BugReporterVisitors are used to add custom diagnostics along a path. 00032 /// 00033 /// Custom visitors should subclass the BugReporterVisitorImpl class for a 00034 /// default implementation of the clone() method. 00035 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 00036 /// default implementation of clone() will NOT do the right thing, and you 00037 /// will have to provide your own implementation.) 00038 class BugReporterVisitor : public llvm::FoldingSetNode { 00039 public: 00040 virtual ~BugReporterVisitor(); 00041 00042 /// \brief Returns a copy of this BugReporter. 00043 /// 00044 /// Custom BugReporterVisitors should not override this method directly. 00045 /// Instead, they should inherit from BugReporterVisitorImpl and provide 00046 /// a protected or public copy constructor. 00047 /// 00048 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 00049 /// default implementation of clone() will NOT do the right thing, and you 00050 /// will have to provide your own implementation.) 00051 virtual BugReporterVisitor *clone() const = 0; 00052 00053 /// \brief Return a diagnostic piece which should be associated with the 00054 /// given node. 00055 /// 00056 /// The last parameter can be used to register a new visitor with the given 00057 /// BugReport while processing a node. 00058 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00059 const ExplodedNode *PrevN, 00060 BugReporterContext &BRC, 00061 BugReport &BR) = 0; 00062 00063 /// \brief Provide custom definition for the final diagnostic piece on the 00064 /// path - the piece, which is displayed before the path is expanded. 00065 /// 00066 /// If returns NULL the default implementation will be used. 00067 /// Also note that at most one visitor of a BugReport should generate a 00068 /// non-NULL end of path diagnostic piece. 00069 virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, 00070 const ExplodedNode *N, 00071 BugReport &BR); 00072 00073 virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; 00074 00075 /// \brief Generates the default final diagnostic piece. 00076 static PathDiagnosticPiece *getDefaultEndPath(BugReporterContext &BRC, 00077 const ExplodedNode *N, 00078 BugReport &BR); 00079 00080 }; 00081 00082 /// This class provides a convenience implementation for clone() using the 00083 /// Curiously-Recurring Template Pattern. If you are implementing a custom 00084 /// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public 00085 /// or protected copy constructor. 00086 /// 00087 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 00088 /// default implementation of clone() will NOT do the right thing, and you 00089 /// will have to provide your own implementation.) 00090 template <class DERIVED> 00091 class BugReporterVisitorImpl : public BugReporterVisitor { 00092 virtual BugReporterVisitor *clone() const { 00093 return new DERIVED(*static_cast<const DERIVED *>(this)); 00094 } 00095 }; 00096 00097 class FindLastStoreBRVisitor 00098 : public BugReporterVisitorImpl<FindLastStoreBRVisitor> 00099 { 00100 const MemRegion *R; 00101 SVal V; 00102 bool satisfied; 00103 const ExplodedNode *StoreSite; 00104 00105 public: 00106 /// \brief Convenience method to create a visitor given only the MemRegion. 00107 /// Returns NULL if the visitor cannot be created. For example, when the 00108 /// corresponding value is unknown. 00109 static BugReporterVisitor *createVisitorObject(const ExplodedNode *N, 00110 const MemRegion *R); 00111 00112 /// Creates a visitor for every VarDecl inside a Stmt and registers it with 00113 /// the BugReport. 00114 static void registerStatementVarDecls(BugReport &BR, const Stmt *S); 00115 00116 FindLastStoreBRVisitor(SVal v, const MemRegion *r) 00117 : R(r), V(v), satisfied(false), StoreSite(0) { 00118 assert (!V.isUnknown() && "Cannot track unknown value."); 00119 00120 // TODO: Does it make sense to allow undef values here? 00121 // (If not, also see UndefCapturedBlockVarChecker)? 00122 } 00123 00124 void Profile(llvm::FoldingSetNodeID &ID) const; 00125 00126 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00127 const ExplodedNode *PrevN, 00128 BugReporterContext &BRC, 00129 BugReport &BR); 00130 }; 00131 00132 class TrackConstraintBRVisitor 00133 : public BugReporterVisitorImpl<TrackConstraintBRVisitor> 00134 { 00135 DefinedSVal Constraint; 00136 const bool Assumption; 00137 bool isSatisfied; 00138 00139 public: 00140 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) 00141 : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} 00142 00143 void Profile(llvm::FoldingSetNodeID &ID) const; 00144 00145 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00146 const ExplodedNode *PrevN, 00147 BugReporterContext &BRC, 00148 BugReport &BR); 00149 }; 00150 00151 class NilReceiverBRVisitor 00152 : public BugReporterVisitorImpl<NilReceiverBRVisitor> 00153 { 00154 public: 00155 void Profile(llvm::FoldingSetNodeID &ID) const { 00156 static int x = 0; 00157 ID.AddPointer(&x); 00158 } 00159 00160 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00161 const ExplodedNode *PrevN, 00162 BugReporterContext &BRC, 00163 BugReport &BR); 00164 }; 00165 00166 /// Visitor that tries to report interesting diagnostics from conditions. 00167 class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { 00168 public: 00169 void Profile(llvm::FoldingSetNodeID &ID) const { 00170 static int x = 0; 00171 ID.AddPointer(&x); 00172 } 00173 00174 00175 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00176 const ExplodedNode *Prev, 00177 BugReporterContext &BRC, 00178 BugReport &BR); 00179 00180 PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, 00181 const ExplodedNode *Prev, 00182 BugReporterContext &BRC, 00183 BugReport &BR); 00184 00185 PathDiagnosticPiece *VisitTerminator(const Stmt *Term, 00186 const ExplodedNode *N, 00187 const CFGBlock *srcBlk, 00188 const CFGBlock *dstBlk, 00189 BugReport &R, 00190 BugReporterContext &BRC); 00191 00192 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 00193 bool tookTrue, 00194 BugReporterContext &BRC, 00195 BugReport &R, 00196 const ExplodedNode *N); 00197 00198 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 00199 const DeclRefExpr *DR, 00200 const bool tookTrue, 00201 BugReporterContext &BRC, 00202 BugReport &R, 00203 const ExplodedNode *N); 00204 00205 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 00206 const BinaryOperator *BExpr, 00207 const bool tookTrue, 00208 BugReporterContext &BRC, 00209 BugReport &R, 00210 const ExplodedNode *N); 00211 00212 PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString, 00213 const Expr *CondVarExpr, 00214 const bool tookTrue, 00215 BugReporterContext &BRC, 00216 BugReport &R, 00217 const ExplodedNode *N); 00218 00219 bool patternMatch(const Expr *Ex, 00220 llvm::raw_ostream &Out, 00221 BugReporterContext &BRC, 00222 BugReport &R, 00223 const ExplodedNode *N, 00224 llvm::Optional<bool> &prunable); 00225 }; 00226 00227 namespace bugreporter { 00228 00229 BugReporterVisitor *getTrackNullOrUndefValueVisitor(const ExplodedNode *N, 00230 const Stmt *S, 00231 BugReport *R); 00232 00233 const Stmt *GetDerefExpr(const ExplodedNode *N); 00234 const Stmt *GetDenomExpr(const ExplodedNode *N); 00235 const Stmt *GetCalleeExpr(const ExplodedNode *N); 00236 const Stmt *GetRetValExpr(const ExplodedNode *N); 00237 00238 } // end namespace clang 00239 } // end namespace ento 00240 } // end namespace bugreporter 00241 00242 00243 #endif //LLVM_CLANG_GR__BUGREPORTERVISITOR