1 //===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file declares BugReporterVisitors, which are used to generate enhanced
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR
16 #define LLVM_CLANG_GR_BUGREPORTERVISITOR
18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
19 #include "llvm/ADT/FoldingSet.h"
26 class BugReporterContext;
29 class PathDiagnosticPiece;
31 /// \brief BugReporterVisitors are used to add custom diagnostics along a path.
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.)
38 class BugReporterVisitor : public llvm::FoldingSetNode {
40 virtual ~BugReporterVisitor();
42 /// \brief Returns a copy of this BugReporter.
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.
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;
53 /// \brief Return a diagnostic piece which should be associated with the
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,
63 /// \brief Provide custom definition for the final diagnostic piece on the
64 /// path - the piece, which is displayed before the path is expanded.
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,
73 virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
75 /// \brief Generates the default final diagnostic piece.
76 static PathDiagnosticPiece *getDefaultEndPath(BugReporterContext &BRC,
77 const ExplodedNode *N,
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.
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.)
90 template <class DERIVED>
91 class BugReporterVisitorImpl : public BugReporterVisitor {
92 virtual BugReporterVisitor *clone() const {
93 return new DERIVED(*static_cast<const DERIVED *>(this));
97 class FindLastStoreBRVisitor
98 : public BugReporterVisitorImpl<FindLastStoreBRVisitor>
103 const ExplodedNode *StoreSite;
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,
112 /// Creates a visitor for every VarDecl inside a Stmt and registers it with
114 static void registerStatementVarDecls(BugReport &BR, const Stmt *S);
116 FindLastStoreBRVisitor(SVal v, const MemRegion *r)
117 : R(r), V(v), satisfied(false), StoreSite(0) {
118 assert (!V.isUnknown() && "Cannot track unknown value.");
120 // TODO: Does it make sense to allow undef values here?
121 // (If not, also see UndefCapturedBlockVarChecker)?
124 void Profile(llvm::FoldingSetNodeID &ID) const;
126 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
127 const ExplodedNode *PrevN,
128 BugReporterContext &BRC,
132 class TrackConstraintBRVisitor
133 : public BugReporterVisitorImpl<TrackConstraintBRVisitor>
135 DefinedSVal Constraint;
136 const bool Assumption;
140 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
141 : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
143 void Profile(llvm::FoldingSetNodeID &ID) const;
145 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
146 const ExplodedNode *PrevN,
147 BugReporterContext &BRC,
151 class NilReceiverBRVisitor
152 : public BugReporterVisitorImpl<NilReceiverBRVisitor>
155 void Profile(llvm::FoldingSetNodeID &ID) const {
160 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
161 const ExplodedNode *PrevN,
162 BugReporterContext &BRC,
166 /// Visitor that tries to report interesting diagnostics from conditions.
167 class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> {
169 void Profile(llvm::FoldingSetNodeID &ID) const {
175 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
176 const ExplodedNode *Prev,
177 BugReporterContext &BRC,
180 PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N,
181 const ExplodedNode *Prev,
182 BugReporterContext &BRC,
185 PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
186 const ExplodedNode *N,
187 const CFGBlock *srcBlk,
188 const CFGBlock *dstBlk,
190 BugReporterContext &BRC);
192 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
194 BugReporterContext &BRC,
196 const ExplodedNode *N);
198 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
199 const DeclRefExpr *DR,
201 BugReporterContext &BRC,
203 const ExplodedNode *N);
205 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
206 const BinaryOperator *BExpr,
208 BugReporterContext &BRC,
210 const ExplodedNode *N);
212 PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString,
213 const Expr *CondVarExpr,
215 BugReporterContext &BRC,
217 const ExplodedNode *N);
219 bool patternMatch(const Expr *Ex,
220 llvm::raw_ostream &Out,
221 BugReporterContext &BRC,
223 const ExplodedNode *N,
224 llvm::Optional<bool> &prunable);
227 namespace bugreporter {
229 void addTrackNullOrUndefValueVisitor(const ExplodedNode *N, const Stmt *S,
232 const Stmt *GetDerefExpr(const ExplodedNode *N);
233 const Stmt *GetDenomExpr(const ExplodedNode *N);
234 const Stmt *GetRetValExpr(const ExplodedNode *N);
236 } // end namespace clang
237 } // end namespace ento
238 } // end namespace bugreporter
241 #endif //LLVM_CLANG_GR__BUGREPORTERVISITOR