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 
31 namespace clang {
32 
33 class BinaryOperator;
34 class CFGBlock;
35 class DeclRefExpr;
36 class Expr;
37 class Stmt;
38 
39 namespace ento {
40 
41 class PathSensitiveBugReport;
42 class BugReporterContext;
43 class ExplodedNode;
44 class MemRegion;
45 class PathDiagnosticPiece;
46 using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
47 
48 /// BugReporterVisitors are used to add custom diagnostics along a path.
49 class BugReporterVisitor : public llvm::FoldingSetNode {
50 public:
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.
73  BugReporterContext &BRC,
74  PathSensitiveBugReport &BR) = 0;
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 
99 namespace bugreporter {
100 
101 /// Specifies the type of tracking for an expression.
102 enum 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.
110  Condition
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.
127 struct 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 
162 class Tracker;
164 
165 class ExpressionHandler;
166 class 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.
173 class Tracker : public llvm::RefCountedBase<Tracker> {
174 private:
175  using ExpressionHandlerPtr = std::unique_ptr<ExpressionHandler>;
176  using StoreHandlerPtr = std::unique_ptr<StoreHandler>;
177 
178  PathSensitiveBugReport &Report;
179  std::list<ExpressionHandlerPtr> ExpressionHandlers;
180  std::list<StoreHandlerPtr> StoreHandlers;
181 
182 protected:
183  /// \param Report The bug report to which visitors should be attached.
185 
186 public:
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.
199  bool FoundSomethingToTrack = false;
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.
300 private:
301  Tracker &ParentTracker;
302 
303 public:
304  ExpressionHandler(Tracker &ParentTracker) : ParentTracker(ParentTracker) {}
305  virtual ~ExpressionHandler() {}
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.
323 private:
324  Tracker &ParentTracker;
325 
326 public:
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 
342 protected:
344  StringRef NodeText);
345 };
346 
347 /// Visitor that tracks expressions and values.
349 private:
350  TrackerRef ParentTracker;
351 
352 public:
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.
370 bool 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.
387 void trackStoredValue(SVal V, const MemRegion *R,
388  PathSensitiveBugReport &Report, TrackingOptions Opts = {},
389  const StackFrameContext *Origin = nullptr);
390 
391 const 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 
405 public:
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 
417  BugReporterContext &BRC,
418  PathSensitiveBugReport &BR) override;
419 
420 private:
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.
431 public:
432  void Profile(llvm::FoldingSetNodeID &ID) const override {
433  static int x = 0;
434  ID.AddPointer(&x);
435  }
436 
438  BugReporterContext &BRC,
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 
454 public:
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 
465  BugReporterContext &BRC,
466  PathSensitiveBugReport &BR) override;
467 
469  BugReporterContext &BRC,
471 
473  VisitTerminator(const Stmt *Term, const ExplodedNode *N,
474  const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
476 
478  BugReporterContext &BRC,
480  const ExplodedNode *N, bool TookTrue);
481 
482  PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
483  BugReporterContext &BRC,
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 
493  PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const MemberExpr *ME,
494  BugReporterContext &BRC,
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 {
529 public:
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 
544  void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
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 
557 public:
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 
567  BugReporterContext &BRC,
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 
586 public:
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 
596  BugReporterContext &BRC,
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
604 private:
605  /// Holds the constraints in a given path
606  ConstraintMap Constraints;
607 
608 public:
610 
611  void Profile(llvm::FoldingSetNodeID &ID) const override;
612 
614  BugReporterContext &BRC,
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.
625 public:
626  void Profile(llvm::FoldingSetNodeID &ID) const override;
627 
629  BugReporterContext &BRC,
630  PathSensitiveBugReport &R) override;
631 };
632 
633 class ObjCMethodCall;
634 class CXXConstructorCall;
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.
647 private:
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 
672 protected:
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...".
712  virtual PathDiagnosticPieceRef
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...".
722  virtual PathDiagnosticPieceRef
724  const CXXConstructorCall &Call,
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...".
732  virtual PathDiagnosticPieceRef
734  const ExplodedNode *N) = 0;
735 
736 public:
738 
740  BugReporterContext &BR,
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:3299
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:3892
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:3224
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 &&)
BugReporterVisitor & operator=(BugReporterVisitor &&)=delete
virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR)=0
Return a diagnostic piece which should be associated with the given node.
BugReporterVisitor(const BugReporterVisitor &)=default
BugReporterVisitor & operator=(const BugReporterVisitor &)=delete
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 ...
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.
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N)
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.
Tracker & getParentTracker()
\Return the tracker that initiated the process.
virtual Tracker::Result handle(const Expr *E, const ExplodedNode *Original, const ExplodedNode *ExprNode, TrackingOptions Opts)=0
Handle the given expression from the given node.
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)
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.
PathSensitiveBugReport & getReport()
void addLowPriorityHandler(StoreHandlerPtr SH)
Add custom store handler with the lowest priority.
Tracker(PathSensitiveBugReport &Report)
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.