clang 19.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/// It may be either defined or undefined, but should not be unknown.
378/// \param R The region we're tracking.
379/// \param Opts Tracking options specifying how we want to track the value.
380/// \param Origin Only adds notes when the last store happened in a
381/// different stackframe to this one. Disregarded if the tracking kind
382/// is thorough.
383/// This is useful, because for non-tracked regions, notes about
384/// changes to its value in a nested stackframe could be pruned, and
385/// this visitor can prevent that without polluting the bugpath too
386/// much.
387void trackStoredValue(SVal V, const MemRegion *R,
388 PathSensitiveBugReport &Report, TrackingOptions Opts = {},
389 const StackFrameContext *Origin = nullptr);
390
391const Expr *getDerefExpr(const Stmt *S);
392
393} // namespace bugreporter
394
396 const SmallString<64> Message;
397 const DefinedSVal Constraint;
398 const bool Assumption;
399 bool IsSatisfied = false;
400
401 /// We should start tracking from the last node along the path in which the
402 /// value is constrained.
403 bool IsTrackingTurnedOn = false;
404
405public:
406 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption,
407 StringRef Message)
408 : Message(Message), Constraint(constraint), Assumption(assumption) {}
409
410 void Profile(llvm::FoldingSetNodeID &ID) const override;
411
412 /// Return the tag associated with this visitor. This tag will be used
413 /// to make all PathDiagnosticPieces created by this visitor.
414 static const char *getTag();
415
418 PathSensitiveBugReport &BR) override;
419
420private:
421 /// Checks if the constraint refers to a null-location.
422 bool isZeroCheck() const;
423
424 /// Checks if the constraint is valid in the current state.
425 bool isUnderconstrained(const ExplodedNode *N) const;
426};
427
428/// \class NilReceiverBRVisitor
429/// Prints path notes when a message is sent to a nil receiver.
431public:
432 void Profile(llvm::FoldingSetNodeID &ID) const override {
433 static int x = 0;
434 ID.AddPointer(&x);
435 }
436
439 PathSensitiveBugReport &BR) override;
440
441 /// If the statement is a message send expression with nil receiver, returns
442 /// the receiver expression. Returns NULL otherwise.
443 static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N);
444};
445
446/// Visitor that tries to report interesting diagnostics from conditions.
448 // FIXME: constexpr initialization isn't supported by MSVC2013.
449 constexpr static llvm::StringLiteral GenericTrueMessage =
450 "Assuming the condition is true";
451 constexpr static llvm::StringLiteral GenericFalseMessage =
452 "Assuming the condition is false";
453
454public:
455 void Profile(llvm::FoldingSetNodeID &ID) const override {
456 static int x = 0;
457 ID.AddPointer(&x);
458 }
459
460 /// Return the tag associated with this visitor. This tag will be used
461 /// to make all PathDiagnosticPieces created by this visitor.
462 static const char *getTag();
463
466 PathSensitiveBugReport &BR) override;
467
471
473 VisitTerminator(const Stmt *Term, const ExplodedNode *N,
474 const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
476
480 const ExplodedNode *N, bool TookTrue);
481
485 const ExplodedNode *N, bool TookTrue,
486 bool IsAssuming);
487
489 VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
491 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
492
496 const ExplodedNode *N, bool TookTrue,
497 bool IsAssuming);
498
500 VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr,
502 const ExplodedNode *N, bool TookTrue);
503
504 /// Tries to print the value of the given expression.
505 ///
506 /// \param CondVarExpr The expression to print its value.
507 /// \param Out The stream to print.
508 /// \param N The node where we encountered the condition.
509 /// \param TookTrue Whether we took the \c true branch of the condition.
510 ///
511 /// \return Whether the print was successful. (The printing is successful if
512 /// we model the value and we could obtain it.)
513 bool printValue(const Expr *CondVarExpr, raw_ostream &Out,
514 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
515
516 bool patternMatch(const Expr *Ex, const Expr *ParentEx, raw_ostream &Out,
518 const ExplodedNode *N, std::optional<bool> &prunable,
519 bool IsSameFieldName);
520
521 static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece);
522};
523
524/// Suppress reports that might lead to known false positives.
525///
526/// Currently this suppresses reports based on locations of bugs.
528 : public BugReporterVisitor {
529public:
530 static void *getTag() {
531 static int Tag = 0;
532 return static_cast<void *>(&Tag);
533 }
534
535 void Profile(llvm::FoldingSetNodeID &ID) const override {
536 ID.AddPointer(getTag());
537 }
538
540 PathSensitiveBugReport &) override {
541 return nullptr;
542 }
543
545 PathSensitiveBugReport &BR) override;
546};
547
548/// When a region containing undefined value or '0' value is passed
549/// as an argument in a call, marks the call as interesting.
550///
551/// As a result, BugReporter will not prune the path through the function even
552/// if the region's contents are not modified/accessed by the call.
554 /// The interesting memory region this visitor is tracking.
555 const MemRegion *R;
556
557public:
558 UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
559
560 void Profile(llvm::FoldingSetNodeID &ID) const override {
561 static int Tag = 0;
562 ID.AddPointer(&Tag);
563 ID.AddPointer(R);
564 }
565
568 PathSensitiveBugReport &BR) override;
569};
570
572 /// The symbolic value for which we are tracking constraints.
573 /// This value is constrained to null in the end of path.
574 DefinedSVal V;
575
576 /// Track if we found the node where the constraint was first added.
577 bool IsSatisfied = false;
578
579 /// Since the visitors can be registered on nodes previous to the last
580 /// node in the BugReport, but the path traversal always starts with the last
581 /// node, the visitor invariant (that we start with a node in which V is null)
582 /// might not hold when node visitation starts. We are going to start tracking
583 /// from the last node in which the value is null.
584 bool IsTrackingTurnedOn = false;
585
586public:
588
589 void Profile(llvm::FoldingSetNodeID &ID) const override;
590
591 /// Return the tag associated with this visitor. This tag will be used
592 /// to make all PathDiagnosticPieces created by this visitor.
593 static const char *getTag();
594
597 PathSensitiveBugReport &BR) override;
598};
599
600/// The bug visitor will walk all the nodes in a path and collect all the
601/// constraints. When it reaches the root node, will create a refutation
602/// manager and check if the constraints are satisfiable
604private:
605 /// Holds the constraints in a given path
606 ConstraintMap Constraints;
607
608public:
610
611 void Profile(llvm::FoldingSetNodeID &ID) const override;
612
615 PathSensitiveBugReport &BR) override;
616
617 void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
618 PathSensitiveBugReport &BR) override;
619 void addConstraints(const ExplodedNode *N,
620 bool OverwriteConstraintsOnExistingSyms);
621};
622
623/// The visitor detects NoteTags and displays the event notes they contain.
625public:
626 void Profile(llvm::FoldingSetNodeID &ID) const override;
627
630 PathSensitiveBugReport &R) override;
631};
632
633class ObjCMethodCall;
635
636/// Put a diagnostic on return statement (or on } in its absence) of all inlined
637/// functions for which some property remained unchanged.
638/// Resulting diagnostics may read such as "Returning without writing to X".
639///
640/// Descendants can define what a "state change is", like a change of value
641/// to a memory region, liveness, etc. For function calls where the state did
642/// not change as defined, a custom note may be constructed.
643///
644/// For a minimal example, check out
645/// clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp.
647private:
648 /// Frames modifying the state as defined in \c wasModifiedBeforeCallExit.
649 /// This visitor generates a note only if a function does *not* change the
650 /// state that way. This information is not immediately available
651 /// by looking at the node associated with the exit from the function
652 /// (usually the return statement). To avoid recomputing the same information
653 /// many times (going up the path for each node and checking whether the
654 /// region was written into) we instead lazily compute the stack frames
655 /// along the path.
656 // TODO: Can't we just use a map instead? This is likely not as cheap as it
657 // makes the code difficult to read.
659 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
660
661 /// Check and lazily calculate whether the state is modified in the stack
662 /// frame to which \p CallExitBeginN belongs.
663 /// The calculation is cached in FramesModifying.
664 bool isModifiedInFrame(const ExplodedNode *CallExitBeginN);
665
666 void markFrameAsModifying(const StackFrameContext *SCtx);
667
668 /// Write to \c FramesModifying all stack frames along the path in the current
669 /// stack frame which modifies the state.
670 void findModifyingFrames(const ExplodedNode *const CallExitBeginN);
671
672protected:
674
675 /// \return Whether the state was modified from the current node, \p CurrN, to
676 /// the end of the stack frame, at \p CallExitBeginN. \p CurrN and
677 /// \p CallExitBeginN are always in the same stack frame.
678 /// Clients should override this callback when a state change is important
679 /// not only on the entire function call, but inside of it as well.
680 /// Example: we may want to leave a note about the lack of locking/unlocking
681 /// on a particular mutex, but not if inside the function its state was
682 /// changed, but also restored. wasModifiedInFunction() wouldn't know of this
683 /// change.
684 virtual bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN,
685 const ExplodedNode *CallExitBeginN) {
686 return false;
687 }
688
689 /// \return Whether the state was modified in the inlined function call in
690 /// between \p CallEnterN and \p CallExitEndN. Mind that the stack frame
691 /// retrieved from a CallEnterN and CallExitEndN is the *caller's* stack
692 /// frame! The inlined function's stack should be retrieved from either the
693 /// immediate successor to \p CallEnterN or immediate predecessor to
694 /// \p CallExitEndN.
695 /// Clients should override this function if a state changes local to the
696 /// inlined function are not interesting, only the change occuring as a
697 /// result of it.
698 /// Example: we want to leave a not about a leaked resource object not being
699 /// deallocated / its ownership changed inside a function, and we don't care
700 /// if it was assigned to a local variable (its change in ownership is
701 /// inconsequential).
702 virtual bool wasModifiedInFunction(const ExplodedNode *CallEnterN,
703 const ExplodedNode *CallExitEndN) {
704 return false;
705 }
706
707 /// Consume the information on the non-modifying stack frame in order to
708 /// either emit a note or not. May suppress the report entirely.
709 /// \return Diagnostics piece for the unmodified state in the current
710 /// function, if it decides to emit one. A good description might start with
711 /// "Returning without...".
714 const ObjCMethodCall &Call,
715 const ExplodedNode *N) = 0;
716
717 /// Consume the information on the non-modifying stack frame in order to
718 /// either emit a note or not. May suppress the report entirely.
719 /// \return Diagnostics piece for the unmodified state in the current
720 /// function, if it decides to emit one. A good description might start with
721 /// "Returning without...".
725 const ExplodedNode *N) = 0;
726
727 /// Consume the information on the non-modifying stack frame in order to
728 /// either emit a note or not. May suppress the report entirely.
729 /// \return Diagnostics piece for the unmodified state in the current
730 /// function, if it decides to emit one. A good description might start with
731 /// "Returning without...".
734 const ExplodedNode *N) = 0;
735
736public:
738
741 PathSensitiveBugReport &R) final;
742};
743
744} // namespace ento
745} // namespace clang
746
747#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#define V(N, I)
Definition: ASTContext.h:3273
static char ID
Definition: Arena.cpp:183
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:3840
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:1260
This represents one expression.
Definition: Expr.h:110
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3172
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
Definition: Stmt.h:84
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:979
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:1243
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:55
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.
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.
void trackStoredValue(SVal 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.
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
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
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.