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>
105 /// \brief Convenience method to create a visitor given only the MemRegion.
106 /// Returns NULL if the visitor cannot be created. For example, when the
107 /// corresponding value is unknown.
108 static BugReporterVisitor *createVisitorObject(const ExplodedNode *N,
111 /// Creates a visitor for every VarDecl inside a Stmt and registers it with
113 static void registerStatementVarDecls(BugReport &BR, const Stmt *S);
115 FindLastStoreBRVisitor(SVal v, const MemRegion *r)
116 : R(r), V(v), satisfied(false) {
117 assert (!V.isUnknown() && "Cannot track unknown value.");
119 // TODO: Does it make sense to allow undef values here?
120 // (If not, also see UndefCapturedBlockVarChecker)?
123 void Profile(llvm::FoldingSetNodeID &ID) const;
125 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
126 const ExplodedNode *PrevN,
127 BugReporterContext &BRC,
131 class TrackConstraintBRVisitor
132 : public BugReporterVisitorImpl<TrackConstraintBRVisitor>
134 DefinedSVal Constraint;
135 const bool Assumption;
139 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
140 : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
142 void Profile(llvm::FoldingSetNodeID &ID) const;
144 /// Return the tag associated with this visitor. This tag will be used
145 /// to make all PathDiagnosticPieces created by this visitor.
146 static const char *getTag();
148 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
149 const ExplodedNode *PrevN,
150 BugReporterContext &BRC,
154 class NilReceiverBRVisitor
155 : public BugReporterVisitorImpl<NilReceiverBRVisitor>
158 void Profile(llvm::FoldingSetNodeID &ID) const {
163 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
164 const ExplodedNode *PrevN,
165 BugReporterContext &BRC,
169 /// Visitor that tries to report interesting diagnostics from conditions.
170 class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> {
172 void Profile(llvm::FoldingSetNodeID &ID) const {
177 /// Return the tag associated with this visitor. This tag will be used
178 /// to make all PathDiagnosticPieces created by this visitor.
179 static const char *getTag();
181 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
182 const ExplodedNode *Prev,
183 BugReporterContext &BRC,
186 PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N,
187 const ExplodedNode *Prev,
188 BugReporterContext &BRC,
191 PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
192 const ExplodedNode *N,
193 const CFGBlock *srcBlk,
194 const CFGBlock *dstBlk,
196 BugReporterContext &BRC);
198 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
200 BugReporterContext &BRC,
202 const ExplodedNode *N);
204 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
205 const DeclRefExpr *DR,
207 BugReporterContext &BRC,
209 const ExplodedNode *N);
211 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
212 const BinaryOperator *BExpr,
214 BugReporterContext &BRC,
216 const ExplodedNode *N);
218 PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString,
219 const Expr *CondVarExpr,
221 BugReporterContext &BRC,
223 const ExplodedNode *N);
225 bool patternMatch(const Expr *Ex,
226 llvm::raw_ostream &Out,
227 BugReporterContext &BRC,
229 const ExplodedNode *N,
230 llvm::Optional<bool> &prunable);
233 /// \brief When a region containing undefined value or '0' value is passed
234 /// as an argument in a call, marks the call as interesting.
236 /// As a result, BugReporter will not prune the path through the function even
237 /// if the region's contents are not modified/accessed by the call.
238 class UndefOrNullArgVisitor
239 : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
241 /// The interesting memory region this visitor is tracking.
245 UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
247 virtual void Profile(llvm::FoldingSetNodeID &ID) const {
253 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
254 const ExplodedNode *PrevN,
255 BugReporterContext &BRC,
259 namespace bugreporter {
261 /// Attempts to add visitors to trace a null or undefined value back to its
262 /// point of origin, whether it is a symbol constrained to null or an explicit
265 /// \param N A node "downstream" from the evaluation of the statement.
266 /// \param S The statement whose value is null or undefined.
267 /// \param R The bug report to which visitors should be attached.
268 /// \param IsArg Whether the statement is an argument to an inlined function.
269 /// If this is the case, \p N \em must be the CallEnter node for
272 /// \return Whether or not the function was able to add visitors for this
273 /// statement. Note that returning \c true does not actually imply
274 /// that any visitors were added.
275 bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R,
278 const Stmt *GetDerefExpr(const ExplodedNode *N);
279 const Stmt *GetDenomExpr(const ExplodedNode *N);
280 const Stmt *GetRetValExpr(const ExplodedNode *N);
281 bool isDeclRefExprToReference(const Expr *E);
284 } // end namespace clang
285 } // end namespace ento
286 } // end namespace bugreporter
289 #endif //LLVM_CLANG_GR__BUGREPORTERVISITOR