clang 17.0.0git
BugReporterVisitors.h
Go to the documentation of this file.
1//===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file declares BugReporterVisitors, which are used to generate enhanced
10// diagnostic traces.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
15#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
16
18#include "clang/Basic/LLVM.h"
21#include "llvm/ADT/FoldingSet.h"
22#include "llvm/ADT/IntrusiveRefCntPtr.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include "llvm/ADT/StringRef.h"
26#include <list>
27#include <memory>
28#include <optional>
29#include <utility>
30
31namespace clang {
32
33class BinaryOperator;
34class CFGBlock;
35class DeclRefExpr;
36class Expr;
37class Stmt;
38
39namespace ento {
40
41class PathSensitiveBugReport;
42class BugReporterContext;
43class ExplodedNode;
44class MemRegion;
45class PathDiagnosticPiece;
46using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
47
48/// BugReporterVisitors are used to add custom diagnostics along a path.
49class BugReporterVisitor : public llvm::FoldingSetNode {
50public:
51 BugReporterVisitor() = default;
54
55 // The copy and move assignment operator is defined as deleted pending further
56 // motivation.
59
61
62 /// Return a diagnostic piece which should be associated with the
63 /// given node.
64 /// Note that this function does *not* get run on the very last node
65 /// of the report, as the PathDiagnosticPiece associated with the
66 /// last node should be unique.
67 /// Use \ref getEndPath to customize the note associated with the report
68 /// end instead.
69 ///
70 /// The last parameter can be used to register a new visitor with the given
71 /// BugReport while processing a node.
75
76 /// Last function called on the visitor, no further calls to VisitNode
77 /// would follow.
78 virtual void finalizeVisitor(BugReporterContext &BRC,
79 const ExplodedNode *EndPathNode,
81
82 /// Provide custom definition for the final diagnostic piece on the
83 /// path - the piece, which is displayed before the path is expanded.
84 ///
85 /// NOTE that this function can be implemented on at most one used visitor,
86 /// and otherwise it crahes at runtime.
88 const ExplodedNode *N,
90
91 virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
92
93 /// Generates the default final diagnostic piece.
96 const PathSensitiveBugReport &BR);
97};
98
99namespace bugreporter {
100
101/// Specifies the type of tracking for an expression.
102enum class TrackingKind {
103 /// Default tracking kind -- specifies that as much information should be
104 /// gathered about the tracked expression value as possible.
105 Thorough,
106 /// Specifies that a more moderate tracking should be used for the expression
107 /// value. This will essentially make sure that functions relevant to it
108 /// aren't pruned, but otherwise relies on the user reading the code or
109 /// following the arrows.
111};
112
113/// Defines a set of options altering tracking behavior.
115 /// Specifies the kind of tracking.
117 /// Specifies whether we should employ false positive suppression
118 /// (inlined defensive checks, returned null).
120};
121
122/// Describes an event when the value got stored into a memory region.
123///
124/// As opposed to checker checkBind API, it reacts also to binds
125/// generated by the checker as well. It can be useful when the binding
126/// happened as a result of evalCall, for example.
127struct StoreInfo {
128 enum Kind {
129 /// The value got stored into the region during initialization:
130 /// int x = 42;
132 /// The value got stored into the region during assignment:
133 /// int x;
134 /// x = 42;
136 /// The value got stored into the parameter region as the result
137 /// of a call.
139 /// The value got stored into the region as block capture.
140 /// Block data is modeled as a separate region, thus whenever
141 /// the analyzer sees a captured variable, its value is copied
142 /// into a special block region.
144 };
145
146 /// The type of store operation.
148 /// The node where the store happened.
150 /// The expression where the value comes from.
151 /// NOTE: might be null.
153 /// Symbolic value that is being stored.
155 /// Memory regions involved in the store operation.
156 /// Dest <- Origin
157 /// NOTE: Origin might be null, when the stored value doesn't come
158 /// from another region.
160};
161
162class Tracker;
164
166class StoreHandler;
167
168/// A generalized component for tracking expressions, values, and stores.
169///
170/// Tracker aimes at providing a sensible set of default behaviors that can be
171/// used by any checker, while providing mechanisms to hook into any part of the
172/// tracking process and insert checker-specific logic.
173class Tracker : public llvm::RefCountedBase<Tracker> {
174private:
175 using ExpressionHandlerPtr = std::unique_ptr<ExpressionHandler>;
176 using StoreHandlerPtr = std::unique_ptr<StoreHandler>;
177
179 std::list<ExpressionHandlerPtr> ExpressionHandlers;
180 std::list<StoreHandlerPtr> StoreHandlers;
181
182protected:
183 /// \param Report The bug report to which visitors should be attached.
185
186public:
187 virtual ~Tracker() = default;
188
190 return new Tracker(Report);
191 }
192
193 PathSensitiveBugReport &getReport() { return Report; }
194
195 /// Describes a tracking result with the most basic information of what was
196 /// actually done (or not done).
197 struct Result {
198 /// Usually it means that the tracker added visitors.
200 /// Signifies that the tracking was interrupted at some point.
201 /// Usually this information is important only for sub-trackers.
202 bool WasInterrupted = false;
203
204 /// Combines the current result with the given result.
205 void combineWith(const Result &Other) {
206 // If we found something in one of the cases, we can
207 // say we found something overall.
208 FoundSomethingToTrack |= Other.FoundSomethingToTrack;
209 // The same goes to the interruption.
210 WasInterrupted |= Other.WasInterrupted;
211 }
212 };
213
214 /// Track expression value back to its point of origin.
215 ///
216 /// \param E The expression value which we are tracking
217 /// \param N A node "downstream" from the evaluation of the statement.
218 /// \param Opts Tracking options specifying how we want to track the value.
219 virtual Result track(const Expr *E, const ExplodedNode *N,
220 TrackingOptions Opts = {});
221
222 /// Track how the value got stored into the given region and where it came
223 /// from.
224 ///
225 /// \param V We're searching for the store where \c R received this value.
226 /// \param R The region we're tracking.
227 /// \param Opts Tracking options specifying how we want to track the value.
228 /// \param Origin Only adds notes when the last store happened in a
229 /// different stackframe to this one. Disregarded if the tracking kind
230 /// is thorough.
231 /// This is useful, because for non-tracked regions, notes about
232 /// changes to its value in a nested stackframe could be pruned, and
233 /// this visitor can prevent that without polluting the bugpath too
234 /// much.
235 virtual Result track(SVal V, const MemRegion *R, TrackingOptions Opts = {},
236 const StackFrameContext *Origin = nullptr);
237
238 /// Handle the store operation and produce the note.
239 ///
240 /// \param SI The information fully describing the store.
241 /// \param Opts Tracking options specifying how we got to it.
242 ///
243 /// NOTE: this method is designed for sub-trackers and visitors.
244 virtual PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
245 TrackingOptions Opts);
246
247 /// Add custom expression handler with the highest priority.
248 ///
249 /// It means that it will be asked for handling first, and can prevent
250 /// other handlers from running if decides to interrupt.
251 void addHighPriorityHandler(ExpressionHandlerPtr SH) {
252 ExpressionHandlers.push_front(std::move(SH));
253 }
254
255 /// Add custom expression handler with the lowest priority.
256 ///
257 /// It means that it will be asked for handling last, and other handlers can
258 /// prevent it from running if any of them decides to interrupt.
259 void addLowPriorityHandler(ExpressionHandlerPtr SH) {
260 ExpressionHandlers.push_back(std::move(SH));
261 }
262
263 /// Add custom store handler with the highest priority.
264 ///
265 /// It means that it will be asked for handling first, and will prevent
266 /// other handlers from running if it produces non-null note.
267 void addHighPriorityHandler(StoreHandlerPtr SH) {
268 StoreHandlers.push_front(std::move(SH));
269 }
270
271 /// Add custom store handler with the lowest priority.
272 ///
273 /// It means that it will be asked for handling last, only
274 /// if all other handlers failed to produce the note.
275 void addLowPriorityHandler(StoreHandlerPtr SH) {
276 StoreHandlers.push_back(std::move(SH));
277 }
278
279 /// Add custom expression/store handler with the highest priority
280 ///
281 /// See other overloads for explanation.
282 template <class HandlerType, class... Args>
283 void addHighPriorityHandler(Args &&... ConstructorArgs) {
284 addHighPriorityHandler(std::make_unique<HandlerType>(
285 *this, std::forward<Args>(ConstructorArgs)...));
286 }
287
288 /// Add custom expression/store handler with the lowest priority
289 ///
290 /// See other overloads for explanation.
291 template <class HandlerType, class... Args>
292 void addLowPriorityHandler(Args &&... ConstructorArgs) {
293 addLowPriorityHandler(std::make_unique<HandlerType>(
294 *this, std::forward<Args>(ConstructorArgs)...));
295 }
296};
297
298/// Handles expressions during the tracking.
300private:
301 Tracker &ParentTracker;
302
303public:
304 ExpressionHandler(Tracker &ParentTracker) : ParentTracker(ParentTracker) {}
306
307 /// Handle the given expression from the given node.
308 ///
309 /// \param E The expression value which we are tracking
310 /// \param Original A node "downstream" where the tracking started.
311 /// \param ExprNode A node where the evaluation of \c E actually happens.
312 /// \param Opts Tracking options specifying how we are tracking the value.
313 virtual Tracker::Result handle(const Expr *E, const ExplodedNode *Original,
314 const ExplodedNode *ExprNode,
315 TrackingOptions Opts) = 0;
316
317 /// \Return the tracker that initiated the process.
318 Tracker &getParentTracker() { return ParentTracker; }
319};
320
321/// Handles stores during the tracking.
323private:
324 Tracker &ParentTracker;
325
326public:
327 StoreHandler(Tracker &ParentTracker) : ParentTracker(ParentTracker) {}
328 virtual ~StoreHandler() {}
329
330 /// Handle the given store and produce the node.
331 ///
332 /// \param SI The information fully describing the store.
333 /// \param Opts Tracking options specifying how we are tracking the value.
334 ///
335 /// \return the produced note, null if the handler doesn't support this kind
336 /// of stores.
338 TrackingOptions Opts) = 0;
339
340 Tracker &getParentTracker() { return ParentTracker; }
341
342protected:
344 StringRef NodeText);
345};
346
347/// Visitor that tracks expressions and values.
349private:
350 TrackerRef ParentTracker;
351
352public:
354 : ParentTracker(ParentTracker) {}
355
356 Tracker &getParentTracker() { return *ParentTracker; }
357};
358
359/// Attempts to add visitors to track expression value back to its point of
360/// origin.
361///
362/// \param N A node "downstream" from the evaluation of the statement.
363/// \param E The expression value which we are tracking
364/// \param R The bug report to which visitors should be attached.
365/// \param Opts Tracking options specifying how we are tracking the value.
366///
367/// \return Whether or not the function was able to add visitors for this
368/// statement. Note that returning \c true does not actually imply
369/// that any visitors were added.
370bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
371 PathSensitiveBugReport &R, TrackingOptions Opts = {});
372
373/// Track how the value got stored into the given region and where it came
374/// from.
375///
376/// \param V We're searching for the store where \c R received this value.
377/// \param R The region we're tracking.
378/// \param Opts Tracking options specifying how we want to track the value.
379/// \param Origin Only adds notes when the last store happened in a
380/// different stackframe to this one. Disregarded if the tracking kind
381/// is thorough.
382/// This is useful, because for non-tracked regions, notes about
383/// changes to its value in a nested stackframe could be pruned, and
384/// this visitor can prevent that without polluting the bugpath too
385/// much.
386void trackStoredValue(KnownSVal V, const MemRegion *R,
387 PathSensitiveBugReport &Report, TrackingOptions Opts = {},
388 const StackFrameContext *Origin = nullptr);
389
390const Expr *getDerefExpr(const Stmt *S);
391
392} // namespace bugreporter
393
395 DefinedSVal Constraint;
396 bool Assumption;
397 bool IsSatisfied = false;
398 bool IsZeroCheck;
399
400 /// We should start tracking from the last node along the path in which the
401 /// value is constrained.
402 bool IsTrackingTurnedOn = false;
403
404public:
405 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
406 : Constraint(constraint), Assumption(assumption),
407 IsZeroCheck(!Assumption && isa<Loc>(Constraint)) {}
408
409 void Profile(llvm::FoldingSetNodeID &ID) const override;
410
411 /// Return the tag associated with this visitor. This tag will be used
412 /// to make all PathDiagnosticPieces created by this visitor.
413 static const char *getTag();
414
417 PathSensitiveBugReport &BR) override;
418
419private:
420 /// Checks if the constraint is valid in the current state.
421 bool isUnderconstrained(const ExplodedNode *N) const;
422};
423
424/// \class NilReceiverBRVisitor
425/// Prints path notes when a message is sent to a nil receiver.
427public:
428 void Profile(llvm::FoldingSetNodeID &ID) const override {
429 static int x = 0;
430 ID.AddPointer(&x);
431 }
432
435 PathSensitiveBugReport &BR) override;
436
437 /// If the statement is a message send expression with nil receiver, returns
438 /// the receiver expression. Returns NULL otherwise.
439 static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N);
440};
441
442/// Visitor that tries to report interesting diagnostics from conditions.
444 // FIXME: constexpr initialization isn't supported by MSVC2013.
445 constexpr static llvm::StringLiteral GenericTrueMessage =
446 "Assuming the condition is true";
447 constexpr static llvm::StringLiteral GenericFalseMessage =
448 "Assuming the condition is false";
449
450public:
451 void Profile(llvm::FoldingSetNodeID &ID) const override {
452 static int x = 0;
453 ID.AddPointer(&x);
454 }
455
456 /// Return the tag associated with this visitor. This tag will be used
457 /// to make all PathDiagnosticPieces created by this visitor.
458 static const char *getTag();
459
462 PathSensitiveBugReport &BR) override;
463
467
469 VisitTerminator(const Stmt *Term, const ExplodedNode *N,
470 const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
472
476 const ExplodedNode *N, bool TookTrue);
477
481 const ExplodedNode *N, bool TookTrue,
482 bool IsAssuming);
483
485 VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
487 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
488
492 const ExplodedNode *N, bool TookTrue,
493 bool IsAssuming);
494
496 VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr,
498 const ExplodedNode *N, bool TookTrue);
499
500 /// Tries to print the value of the given expression.
501 ///
502 /// \param CondVarExpr The expression to print its value.
503 /// \param Out The stream to print.
504 /// \param N The node where we encountered the condition.
505 /// \param TookTrue Whether we took the \c true branch of the condition.
506 ///
507 /// \return Whether the print was successful. (The printing is successful if
508 /// we model the value and we could obtain it.)
509 bool printValue(const Expr *CondVarExpr, raw_ostream &Out,
510 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
511
512 bool patternMatch(const Expr *Ex, const Expr *ParentEx, raw_ostream &Out,
514 const ExplodedNode *N, std::optional<bool> &prunable,
515 bool IsSameFieldName);
516
517 static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece);
518};
519
520/// Suppress reports that might lead to known false positives.
521///
522/// Currently this suppresses reports based on locations of bugs.
524 : public BugReporterVisitor {
525public:
526 static void *getTag() {
527 static int Tag = 0;
528 return static_cast<void *>(&Tag);
529 }
530
531 void Profile(llvm::FoldingSetNodeID &ID) const override {
532 ID.AddPointer(getTag());
533 }
534
536 PathSensitiveBugReport &) override {
537 return nullptr;
538 }
539
541 PathSensitiveBugReport &BR) override;
542};
543
544/// When a region containing undefined value or '0' value is passed
545/// as an argument in a call, marks the call as interesting.
546///
547/// As a result, BugReporter will not prune the path through the function even
548/// if the region's contents are not modified/accessed by the call.
550 /// The interesting memory region this visitor is tracking.
551 const MemRegion *R;
552
553public:
554 UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
555
556 void Profile(llvm::FoldingSetNodeID &ID) const override {
557 static int Tag = 0;
558 ID.AddPointer(&Tag);
559 ID.AddPointer(R);
560 }
561
564 PathSensitiveBugReport &BR) override;
565};
566
568 /// The symbolic value for which we are tracking constraints.
569 /// This value is constrained to null in the end of path.
570 DefinedSVal V;
571
572 /// Track if we found the node where the constraint was first added.
573 bool IsSatisfied = false;
574
575 /// Since the visitors can be registered on nodes previous to the last
576 /// node in the BugReport, but the path traversal always starts with the last
577 /// node, the visitor invariant (that we start with a node in which V is null)
578 /// might not hold when node visitation starts. We are going to start tracking
579 /// from the last node in which the value is null.
580 bool IsTrackingTurnedOn = false;
581
582public:
584
585 void Profile(llvm::FoldingSetNodeID &ID) const override;
586
587 /// Return the tag associated with this visitor. This tag will be used
588 /// to make all PathDiagnosticPieces created by this visitor.
589 static const char *getTag();
590
593 PathSensitiveBugReport &BR) override;
594};
595
596/// The bug visitor will walk all the nodes in a path and collect all the
597/// constraints. When it reaches the root node, will create a refutation
598/// manager and check if the constraints are satisfiable
600private:
601 /// Holds the constraints in a given path
602 ConstraintMap Constraints;
603
604public:
606
607 void Profile(llvm::FoldingSetNodeID &ID) const override;
608
611 PathSensitiveBugReport &BR) override;
612
613 void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
614 PathSensitiveBugReport &BR) override;
615 void addConstraints(const ExplodedNode *N,
616 bool OverwriteConstraintsOnExistingSyms);
617};
618
619/// The visitor detects NoteTags and displays the event notes they contain.
621public:
622 void Profile(llvm::FoldingSetNodeID &ID) const override;
623
626 PathSensitiveBugReport &R) override;
627};
628
629class ObjCMethodCall;
631
632/// Put a diagnostic on return statement (or on } in its absence) of all inlined
633/// functions for which some property remained unchanged.
634/// Resulting diagnostics may read such as "Returning without writing to X".
635///
636/// Descendants can define what a "state change is", like a change of value
637/// to a memory region, liveness, etc. For function calls where the state did
638/// not change as defined, a custom note may be constructed.
639///
640/// For a minimal example, check out
641/// clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp.
643private:
644 /// Frames modifying the state as defined in \c wasModifiedBeforeCallExit.
645 /// This visitor generates a note only if a function does *not* change the
646 /// state that way. This information is not immediately available
647 /// by looking at the node associated with the exit from the function
648 /// (usually the return statement). To avoid recomputing the same information
649 /// many times (going up the path for each node and checking whether the
650 /// region was written into) we instead lazily compute the stack frames
651 /// along the path.
652 // TODO: Can't we just use a map instead? This is likely not as cheap as it
653 // makes the code difficult to read.
655 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
656
657 /// Check and lazily calculate whether the state is modified in the stack
658 /// frame to which \p CallExitBeginN belongs.
659 /// The calculation is cached in FramesModifying.
660 bool isModifiedInFrame(const ExplodedNode *CallExitBeginN);
661
662 void markFrameAsModifying(const StackFrameContext *SCtx);
663
664 /// Write to \c FramesModifying all stack frames along the path in the current
665 /// stack frame which modifies the state.
666 void findModifyingFrames(const ExplodedNode *const CallExitBeginN);
667
668protected:
670
671 /// \return Whether the state was modified from the current node, \p CurrN, to
672 /// the end of the stack frame, at \p CallExitBeginN. \p CurrN and
673 /// \p CallExitBeginN are always in the same stack frame.
674 /// Clients should override this callback when a state change is important
675 /// not only on the entire function call, but inside of it as well.
676 /// Example: we may want to leave a note about the lack of locking/unlocking
677 /// on a particular mutex, but not if inside the function its state was
678 /// changed, but also restored. wasModifiedInFunction() wouldn't know of this
679 /// change.
680 virtual bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN,
681 const ExplodedNode *CallExitBeginN) {
682 return false;
683 }
684
685 /// \return Whether the state was modified in the inlined function call in
686 /// between \p CallEnterN and \p CallExitEndN. Mind that the stack frame
687 /// retrieved from a CallEnterN and CallExitEndN is the *caller's* stack
688 /// frame! The inlined function's stack should be retrieved from either the
689 /// immediate successor to \p CallEnterN or immediate predecessor to
690 /// \p CallExitEndN.
691 /// Clients should override this function if a state changes local to the
692 /// inlined function are not interesting, only the change occuring as a
693 /// result of it.
694 /// Example: we want to leave a not about a leaked resource object not being
695 /// deallocated / its ownership changed inside a function, and we don't care
696 /// if it was assigned to a local variable (its change in ownership is
697 /// inconsequential).
698 virtual bool wasModifiedInFunction(const ExplodedNode *CallEnterN,
699 const ExplodedNode *CallExitEndN) {
700 return false;
701 }
702
703 /// Consume the information on the non-modifying stack frame in order to
704 /// either emit a note or not. May suppress the report entirely.
705 /// \return Diagnostics piece for the unmodified state in the current
706 /// function, if it decides to emit one. A good description might start with
707 /// "Returning without...".
710 const ObjCMethodCall &Call,
711 const ExplodedNode *N) = 0;
712
713 /// Consume the information on the non-modifying stack frame in order to
714 /// either emit a note or not. May suppress the report entirely.
715 /// \return Diagnostics piece for the unmodified state in the current
716 /// function, if it decides to emit one. A good description might start with
717 /// "Returning without...".
720 const CXXConstructorCall &Call,
721 const ExplodedNode *N) = 0;
722
723 /// Consume the information on the non-modifying stack frame in order to
724 /// either emit a note or not. May suppress the report entirely.
725 /// \return Diagnostics piece for the unmodified state in the current
726 /// function, if it decides to emit one. A good description might start with
727 /// "Returning without...".
730 const ExplodedNode *N) = 0;
731
732public:
734
737 PathSensitiveBugReport &R) final;
738};
739
740} // namespace ento
741} // namespace clang
742
743#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#define V(N, I)
Definition: ASTContext.h:3230
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3819
Represents a single basic block in a source-level CFG.
Definition: CFG.h:576
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1237
This represents one expression.
Definition: Expr.h:110
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3180
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
Definition: Stmt.h:72
BugReporterVisitors are used to add custom diagnostics along a path.
virtual void Profile(llvm::FoldingSetNodeID &ID) const =0
BugReporterVisitor(BugReporterVisitor &&)
virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR)=0
Return a diagnostic piece which should be associated with the given node.
BugReporterVisitor & operator=(BugReporterVisitor &&)=delete
BugReporterVisitor(const BugReporterVisitor &)=default
static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N, const PathSensitiveBugReport &BR)
Generates the default final diagnostic piece.
virtual PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR)
Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...
BugReporterVisitor & operator=(const BugReporterVisitor &)=delete
virtual void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, PathSensitiveBugReport &BR)
Last function called on the visitor, no further calls to VisitNode would follow.
Represents a call to a C++ constructor.
Definition: CallEvent.h:899
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:149
Visitor that tries to report interesting diagnostics from conditions.
PathDiagnosticPieceRef VisitTerminator(const Stmt *Term, const ExplodedNode *N, const CFGBlock *SrcBlk, const CFGBlock *DstBlk, PathSensitiveBugReport &R, BugReporterContext &BRC)
bool printValue(const Expr *CondVarExpr, raw_ostream &Out, const ExplodedNode *N, bool TookTrue, bool IsAssuming)
Tries to print the value of the given expression.
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
bool patternMatch(const Expr *Ex, const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, std::optional< bool > &prunable, bool IsSameFieldName)
static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece)
PathDiagnosticPieceRef VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue)
PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue)
static const char * getTag()
Return the tag associated with this visitor.
PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR)
void Profile(llvm::FoldingSetNodeID &ID) const override
The bug visitor will walk all the nodes in a path and collect all the constraints.
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
void addConstraints(const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms)
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, PathSensitiveBugReport &BR) override
Last function called on the visitor, no further calls to VisitNode would follow.
void Profile(llvm::FoldingSetNodeID &ID) const override
Suppress reports that might lead to known false positives.
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR) override
Last function called on the visitor, no further calls to VisitNode would follow.
void Profile(llvm::FoldingSetNodeID &ID) const override
PathDiagnosticPieceRef VisitNode(const ExplodedNode *, BugReporterContext &, PathSensitiveBugReport &) override
Return a diagnostic piece which should be associated with the given node.
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:95
Prints path notes when a message is sent to a nil receiver.
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
void Profile(llvm::FoldingSetNodeID &ID) const override
static const Expr * getNilReceiver(const Stmt *S, const ExplodedNode *N)
If the statement is a message send expression with nil receiver, returns the receiver expression.
Put a diagnostic on return statement (or on } in its absence) of all inlined functions for which some...
virtual bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN, const ExplodedNode *CallExitBeginN)
virtual PathDiagnosticPieceRef maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R, const ObjCMethodCall &Call, const ExplodedNode *N)=0
Consume the information on the non-modifying stack frame in order to either emit a note or not.
virtual PathDiagnosticPieceRef maybeEmitNoteForCXXThis(PathSensitiveBugReport &R, const CXXConstructorCall &Call, const ExplodedNode *N)=0
Consume the information on the non-modifying stack frame in order to either emit a note or not.
NoStateChangeFuncVisitor(bugreporter::TrackingKind TKind)
virtual bool wasModifiedInFunction(const ExplodedNode *CallEnterN, const ExplodedNode *CallExitEndN)
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BR, PathSensitiveBugReport &R) final
Return a diagnostic piece which should be associated with the given node.
virtual PathDiagnosticPieceRef maybeEmitNoteForParameters(PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N)=0
Consume the information on the non-modifying stack frame in order to either emit a note or not.
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:1163
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:72
PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
static const char * getTag()
Return the tag associated with this visitor.
void Profile(llvm::FoldingSetNodeID &ID) const override
The visitor detects NoteTags and displays the event notes they contain.
void Profile(llvm::FoldingSetNodeID &ID) const override
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &R) override
Return a diagnostic piece which should be associated with the given node.
void Profile(llvm::FoldingSetNodeID &ID) const override
static const char * getTag()
Return the tag associated with this visitor.
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
When a region containing undefined value or '0' value is passed as an argument in a call,...
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
void Profile(llvm::FoldingSetNodeID &ID) const override
UndefOrNullArgVisitor(const MemRegion *InR)
Handles expressions during the tracking.
virtual Tracker::Result handle(const Expr *E, const ExplodedNode *Original, const ExplodedNode *ExprNode, TrackingOptions Opts)=0
Handle the given expression from the given node.
Tracker & getParentTracker()
\Return the tracker that initiated the process.
Handles stores during the tracking.
virtual PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC, TrackingOptions Opts)=0
Handle the given store and produce the node.
PathDiagnosticPieceRef constructNote(StoreInfo SI, BugReporterContext &BRC, StringRef NodeText)
A generalized component for tracking expressions, values, and stores.
void addLowPriorityHandler(ExpressionHandlerPtr SH)
Add custom expression handler with the lowest priority.
static TrackerRef create(PathSensitiveBugReport &Report)
PathSensitiveBugReport & getReport()
void addHighPriorityHandler(Args &&... ConstructorArgs)
Add custom expression/store handler with the highest priority.
virtual PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC, TrackingOptions Opts)
Handle the store operation and produce the note.
void addHighPriorityHandler(StoreHandlerPtr SH)
Add custom store handler with the highest priority.
void addHighPriorityHandler(ExpressionHandlerPtr SH)
Add custom expression handler with the highest priority.
void addLowPriorityHandler(Args &&... ConstructorArgs)
Add custom expression/store handler with the lowest priority.
void addLowPriorityHandler(StoreHandlerPtr SH)
Add custom store handler with the lowest priority.
virtual Result track(const Expr *E, const ExplodedNode *N, TrackingOptions Opts={})
Track expression value back to its point of origin.
Visitor that tracks expressions and values.
void trackStoredValue(KnownSVal V, const MemRegion *R, PathSensitiveBugReport &Report, TrackingOptions Opts={}, const StackFrameContext *Origin=nullptr)
Track how the value got stored into the given region and where it came from.
const Expr * getDerefExpr(const Stmt *S)
Given that expression S represents a pointer that would be dereferenced, try to find a sub-expression...
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
TrackingKind
Specifies the type of tracking for an expression.
@ Thorough
Default tracking kind – specifies that as much information should be gathered about the tracked expre...
@ Condition
Specifies that a more moderate tracking should be used for the expression value.
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintMap
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
bool isa(CodeGen::Address addr)
Definition: Address.h:154
Describes an event when the value got stored into a memory region.
@ Assignment
The value got stored into the region during assignment: int x; x = 42;.
@ CallArgument
The value got stored into the parameter region as the result of a call.
@ BlockCapture
The value got stored into the region as block capture.
@ Initialization
The value got stored into the region during initialization: int x = 42;.
const Expr * SourceOfTheValue
The expression where the value comes from.
const ExplodedNode * StoreSite
The node where the store happened.
Kind StoreKind
The type of store operation.
SVal Value
Symbolic value that is being stored.
const MemRegion * Dest
Memory regions involved in the store operation.
Describes a tracking result with the most basic information of what was actually done (or not done).
bool FoundSomethingToTrack
Usually it means that the tracker added visitors.
void combineWith(const Result &Other)
Combines the current result with the given result.
bool WasInterrupted
Signifies that the tracking was interrupted at some point.
Defines a set of options altering tracking behavior.
bool EnableNullFPSuppression
Specifies whether we should employ false positive suppression (inlined defensive checks,...
TrackingKind Kind
Specifies the kind of tracking.