clang 18.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 const SmallString<64> Message;
396 const DefinedSVal Constraint;
397 const bool Assumption;
398 bool IsSatisfied = false;
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 StringRef Message)
407 : Message(Message), Constraint(constraint), Assumption(assumption) {}
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 refers to a null-location.
421 bool isZeroCheck() const;
422
423 /// Checks if the constraint is valid in the current state.
424 bool isUnderconstrained(const ExplodedNode *N) const;
425};
426
427/// \class NilReceiverBRVisitor
428/// Prints path notes when a message is sent to a nil receiver.
430public:
431 void Profile(llvm::FoldingSetNodeID &ID) const override {
432 static int x = 0;
433 ID.AddPointer(&x);
434 }
435
438 PathSensitiveBugReport &BR) override;
439
440 /// If the statement is a message send expression with nil receiver, returns
441 /// the receiver expression. Returns NULL otherwise.
442 static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N);
443};
444
445/// Visitor that tries to report interesting diagnostics from conditions.
447 // FIXME: constexpr initialization isn't supported by MSVC2013.
448 constexpr static llvm::StringLiteral GenericTrueMessage =
449 "Assuming the condition is true";
450 constexpr static llvm::StringLiteral GenericFalseMessage =
451 "Assuming the condition is false";
452
453public:
454 void Profile(llvm::FoldingSetNodeID &ID) const override {
455 static int x = 0;
456 ID.AddPointer(&x);
457 }
458
459 /// Return the tag associated with this visitor. This tag will be used
460 /// to make all PathDiagnosticPieces created by this visitor.
461 static const char *getTag();
462
465 PathSensitiveBugReport &BR) override;
466
470
472 VisitTerminator(const Stmt *Term, const ExplodedNode *N,
473 const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
475
479 const ExplodedNode *N, bool TookTrue);
480
484 const ExplodedNode *N, bool TookTrue,
485 bool IsAssuming);
486
488 VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
490 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
491
495 const ExplodedNode *N, bool TookTrue,
496 bool IsAssuming);
497
499 VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr,
501 const ExplodedNode *N, bool TookTrue);
502
503 /// Tries to print the value of the given expression.
504 ///
505 /// \param CondVarExpr The expression to print its value.
506 /// \param Out The stream to print.
507 /// \param N The node where we encountered the condition.
508 /// \param TookTrue Whether we took the \c true branch of the condition.
509 ///
510 /// \return Whether the print was successful. (The printing is successful if
511 /// we model the value and we could obtain it.)
512 bool printValue(const Expr *CondVarExpr, raw_ostream &Out,
513 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
514
515 bool patternMatch(const Expr *Ex, const Expr *ParentEx, raw_ostream &Out,
517 const ExplodedNode *N, std::optional<bool> &prunable,
518 bool IsSameFieldName);
519
520 static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece);
521};
522
523/// Suppress reports that might lead to known false positives.
524///
525/// Currently this suppresses reports based on locations of bugs.
527 : public BugReporterVisitor {
528public:
529 static void *getTag() {
530 static int Tag = 0;
531 return static_cast<void *>(&Tag);
532 }
533
534 void Profile(llvm::FoldingSetNodeID &ID) const override {
535 ID.AddPointer(getTag());
536 }
537
539 PathSensitiveBugReport &) override {
540 return nullptr;
541 }
542
544 PathSensitiveBugReport &BR) override;
545};
546
547/// When a region containing undefined value or '0' value is passed
548/// as an argument in a call, marks the call as interesting.
549///
550/// As a result, BugReporter will not prune the path through the function even
551/// if the region's contents are not modified/accessed by the call.
553 /// The interesting memory region this visitor is tracking.
554 const MemRegion *R;
555
556public:
557 UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
558
559 void Profile(llvm::FoldingSetNodeID &ID) const override {
560 static int Tag = 0;
561 ID.AddPointer(&Tag);
562 ID.AddPointer(R);
563 }
564
567 PathSensitiveBugReport &BR) override;
568};
569
571 /// The symbolic value for which we are tracking constraints.
572 /// This value is constrained to null in the end of path.
573 DefinedSVal V;
574
575 /// Track if we found the node where the constraint was first added.
576 bool IsSatisfied = false;
577
578 /// Since the visitors can be registered on nodes previous to the last
579 /// node in the BugReport, but the path traversal always starts with the last
580 /// node, the visitor invariant (that we start with a node in which V is null)
581 /// might not hold when node visitation starts. We are going to start tracking
582 /// from the last node in which the value is null.
583 bool IsTrackingTurnedOn = false;
584
585public:
587
588 void Profile(llvm::FoldingSetNodeID &ID) const override;
589
590 /// Return the tag associated with this visitor. This tag will be used
591 /// to make all PathDiagnosticPieces created by this visitor.
592 static const char *getTag();
593
596 PathSensitiveBugReport &BR) override;
597};
598
599/// The bug visitor will walk all the nodes in a path and collect all the
600/// constraints. When it reaches the root node, will create a refutation
601/// manager and check if the constraints are satisfiable
603private:
604 /// Holds the constraints in a given path
605 ConstraintMap Constraints;
606
607public:
609
610 void Profile(llvm::FoldingSetNodeID &ID) const override;
611
614 PathSensitiveBugReport &BR) override;
615
616 void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
617 PathSensitiveBugReport &BR) override;
618 void addConstraints(const ExplodedNode *N,
619 bool OverwriteConstraintsOnExistingSyms);
620};
621
622/// The visitor detects NoteTags and displays the event notes they contain.
624public:
625 void Profile(llvm::FoldingSetNodeID &ID) const override;
626
629 PathSensitiveBugReport &R) override;
630};
631
632class ObjCMethodCall;
634
635/// Put a diagnostic on return statement (or on } in its absence) of all inlined
636/// functions for which some property remained unchanged.
637/// Resulting diagnostics may read such as "Returning without writing to X".
638///
639/// Descendants can define what a "state change is", like a change of value
640/// to a memory region, liveness, etc. For function calls where the state did
641/// not change as defined, a custom note may be constructed.
642///
643/// For a minimal example, check out
644/// clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp.
646private:
647 /// Frames modifying the state as defined in \c wasModifiedBeforeCallExit.
648 /// This visitor generates a note only if a function does *not* change the
649 /// state that way. This information is not immediately available
650 /// by looking at the node associated with the exit from the function
651 /// (usually the return statement). To avoid recomputing the same information
652 /// many times (going up the path for each node and checking whether the
653 /// region was written into) we instead lazily compute the stack frames
654 /// along the path.
655 // TODO: Can't we just use a map instead? This is likely not as cheap as it
656 // makes the code difficult to read.
658 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
659
660 /// Check and lazily calculate whether the state is modified in the stack
661 /// frame to which \p CallExitBeginN belongs.
662 /// The calculation is cached in FramesModifying.
663 bool isModifiedInFrame(const ExplodedNode *CallExitBeginN);
664
665 void markFrameAsModifying(const StackFrameContext *SCtx);
666
667 /// Write to \c FramesModifying all stack frames along the path in the current
668 /// stack frame which modifies the state.
669 void findModifyingFrames(const ExplodedNode *const CallExitBeginN);
670
671protected:
673
674 /// \return Whether the state was modified from the current node, \p CurrN, to
675 /// the end of the stack frame, at \p CallExitBeginN. \p CurrN and
676 /// \p CallExitBeginN are always in the same stack frame.
677 /// Clients should override this callback when a state change is important
678 /// not only on the entire function call, but inside of it as well.
679 /// Example: we may want to leave a note about the lack of locking/unlocking
680 /// on a particular mutex, but not if inside the function its state was
681 /// changed, but also restored. wasModifiedInFunction() wouldn't know of this
682 /// change.
683 virtual bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN,
684 const ExplodedNode *CallExitBeginN) {
685 return false;
686 }
687
688 /// \return Whether the state was modified in the inlined function call in
689 /// between \p CallEnterN and \p CallExitEndN. Mind that the stack frame
690 /// retrieved from a CallEnterN and CallExitEndN is the *caller's* stack
691 /// frame! The inlined function's stack should be retrieved from either the
692 /// immediate successor to \p CallEnterN or immediate predecessor to
693 /// \p CallExitEndN.
694 /// Clients should override this function if a state changes local to the
695 /// inlined function are not interesting, only the change occuring as a
696 /// result of it.
697 /// Example: we want to leave a not about a leaked resource object not being
698 /// deallocated / its ownership changed inside a function, and we don't care
699 /// if it was assigned to a local variable (its change in ownership is
700 /// inconsequential).
701 virtual bool wasModifiedInFunction(const ExplodedNode *CallEnterN,
702 const ExplodedNode *CallExitEndN) {
703 return false;
704 }
705
706 /// Consume the information on the non-modifying stack frame in order to
707 /// either emit a note or not. May suppress the report entirely.
708 /// \return Diagnostics piece for the unmodified state in the current
709 /// function, if it decides to emit one. A good description might start with
710 /// "Returning without...".
713 const ObjCMethodCall &Call,
714 const ExplodedNode *N) = 0;
715
716 /// Consume the information on the non-modifying stack frame in order to
717 /// either emit a note or not. May suppress the report entirely.
718 /// \return Diagnostics piece for the unmodified state in the current
719 /// function, if it decides to emit one. A good description might start with
720 /// "Returning without...".
723 const CXXConstructorCall &Call,
724 const ExplodedNode *N) = 0;
725
726 /// Consume the information on the non-modifying stack frame in order to
727 /// either emit a note or not. May suppress the report entirely.
728 /// \return Diagnostics piece for the unmodified state in the current
729 /// function, if it decides to emit one. A good description might start with
730 /// "Returning without...".
733 const ExplodedNode *N) = 0;
734
735public:
737
740 PathSensitiveBugReport &R) final;
741};
742
743} // namespace ento
744} // namespace clang
745
746#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#define V(N, I)
Definition: ASTContext.h:3233
static char ID
Definition: Arena.cpp:163
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:3847
Represents a single basic block in a source-level CFG.
Definition: CFG.h:604
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1242
This represents one expression.
Definition: Expr.h:110
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3195
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:902
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:153
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:96
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:1166
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:73
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.
TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption, StringRef Message)
PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override
Return a diagnostic piece which should be associated with the given node.
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
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.