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 
17 #include "clang/Analysis/ProgramPoint.h"
18 #include "clang/Basic/LLVM.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
21 #include "llvm/ADT/FoldingSet.h"
22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/StringRef.h"
25 #include <list>
26 #include <memory>
27 #include <utility>
28 
29 namespace clang {
30 
31 class BinaryOperator;
32 class CFGBlock;
33 class DeclRefExpr;
34 class Expr;
35 class Stmt;
36 
37 namespace ento {
38 
39 class PathSensitiveBugReport;
40 class BugReporterContext;
41 class ExplodedNode;
42 class MemRegion;
43 class PathDiagnosticPiece;
44 using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
45 
46 /// BugReporterVisitors are used to add custom diagnostics along a path.
47 class BugReporterVisitor : public llvm::FoldingSetNode {
48 public:
49   BugReporterVisitor() = default;
50   BugReporterVisitor(const BugReporterVisitor &) = default;
BugReporterVisitor(BugReporterVisitor &&)51   BugReporterVisitor(BugReporterVisitor &&) {}
52   virtual ~BugReporterVisitor();
53 
54   /// Return a diagnostic piece which should be associated with the
55   /// given node.
56   /// Note that this function does *not* get run on the very last node
57   /// of the report, as the PathDiagnosticPiece associated with the
58   /// last node should be unique.
59   /// Use \ref getEndPath to customize the note associated with the report
60   /// end instead.
61   ///
62   /// The last parameter can be used to register a new visitor with the given
63   /// BugReport while processing a node.
64   virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
65                                            BugReporterContext &BRC,
66                                            PathSensitiveBugReport &BR) = 0;
67 
68   /// Last function called on the visitor, no further calls to VisitNode
69   /// would follow.
70   virtual void finalizeVisitor(BugReporterContext &BRC,
71                                const ExplodedNode *EndPathNode,
72                                PathSensitiveBugReport &BR);
73 
74   /// Provide custom definition for the final diagnostic piece on the
75   /// path - the piece, which is displayed before the path is expanded.
76   ///
77   /// NOTE that this function can be implemented on at most one used visitor,
78   /// and otherwise it crahes at runtime.
79   virtual PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
80                                             const ExplodedNode *N,
81                                             PathSensitiveBugReport &BR);
82 
83   virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
84 
85   /// Generates the default final diagnostic piece.
86   static PathDiagnosticPieceRef
87   getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N,
88                     const PathSensitiveBugReport &BR);
89 };
90 
91 namespace bugreporter {
92 
93 /// Specifies the type of tracking for an expression.
94 enum class TrackingKind {
95   /// Default tracking kind -- specifies that as much information should be
96   /// gathered about the tracked expression value as possible.
97   Thorough,
98   /// Specifies that a more moderate tracking should be used for the expression
99   /// value. This will essentially make sure that functions relevant to it
100   /// aren't pruned, but otherwise relies on the user reading the code or
101   /// following the arrows.
102   Condition
103 };
104 
105 /// Defines a set of options altering tracking behavior.
106 struct TrackingOptions {
107   /// Specifies the kind of tracking.
108   TrackingKind Kind = TrackingKind::Thorough;
109   /// Specifies whether we should employ false positive suppression
110   /// (inlined defensive checks, returned null).
111   bool EnableNullFPSuppression = true;
112 };
113 
114 /// Describes an event when the value got stored into a memory region.
115 ///
116 /// As opposed to checker checkBind API, it reacts also to binds
117 /// generated by the checker as well.  It can be useful when the binding
118 /// happened as a result of evalCall, for example.
119 struct StoreInfo {
120   enum Kind {
121     /// The value got stored into the region during initialization:
122     ///   int x = 42;
123     Initialization,
124     /// The value got stored into the region during assignment:
125     ///   int x;
126     ///   x = 42;
127     Assignment,
128     /// The value got stored into the parameter region as the result
129     /// of a call.
130     CallArgument,
131     /// The value got stored into the region as block capture.
132     /// Block data is modeled as a separate region, thus whenever
133     /// the analyzer sees a captured variable, its value is copied
134     /// into a special block region.
135     BlockCapture
136   };
137 
138   /// The type of store operation.
139   Kind StoreKind;
140   /// The node where the store happened.
141   const ExplodedNode *StoreSite;
142   /// The expression where the value comes from.
143   /// NOTE: might be null.
144   const Expr *SourceOfTheValue;
145   /// Symbolic value that is being stored.
146   SVal Value;
147   /// Memory regions involved in the store operation.
148   ///   Dest <- Origin
149   /// NOTE: Origin might be null, when the stored value doesn't come
150   ///       from another region.
151   const MemRegion *Dest, *Origin;
152 };
153 
154 class Tracker;
155 using TrackerRef = llvm::IntrusiveRefCntPtr<Tracker>;
156 
157 class ExpressionHandler;
158 class StoreHandler;
159 
160 /// A generalized component for tracking expressions, values, and stores.
161 ///
162 /// Tracker aimes at providing a sensible set of default behaviors that can be
163 /// used by any checker, while providing mechanisms to hook into any part of the
164 /// tracking process and insert checker-specific logic.
165 class Tracker : public llvm::RefCountedBase<Tracker> {
166 private:
167   using ExpressionHandlerPtr = std::unique_ptr<ExpressionHandler>;
168   using StoreHandlerPtr = std::unique_ptr<StoreHandler>;
169 
170   PathSensitiveBugReport &Report;
171   std::list<ExpressionHandlerPtr> ExpressionHandlers;
172   std::list<StoreHandlerPtr> StoreHandlers;
173 
174 protected:
175   /// \param Report The bug report to which visitors should be attached.
176   Tracker(PathSensitiveBugReport &Report);
177 
178 public:
179   virtual ~Tracker() = default;
180 
create(PathSensitiveBugReport & Report)181   static TrackerRef create(PathSensitiveBugReport &Report) {
182     return new Tracker(Report);
183   }
184 
getReport()185   PathSensitiveBugReport &getReport() { return Report; }
186 
187   /// Describes a tracking result with the most basic information of what was
188   /// actually done (or not done).
189   struct Result {
190     /// Usually it means that the tracker added visitors.
191     bool FoundSomethingToTrack = false;
192     /// Signifies that the tracking was interrupted at some point.
193     /// Usually this information is important only for sub-trackers.
194     bool WasInterrupted = false;
195 
196     /// Combines the current result with the given result.
combineWithResult197     void combineWith(const Result &Other) {
198       // If we found something in one of the cases, we can
199       // say we found something overall.
200       FoundSomethingToTrack |= Other.FoundSomethingToTrack;
201       // The same goes to the interruption.
202       WasInterrupted |= Other.WasInterrupted;
203     }
204   };
205 
206   /// Track expression value back to its point of origin.
207   ///
208   /// \param E The expression value which we are tracking
209   /// \param N A node "downstream" from the evaluation of the statement.
210   /// \param Opts Tracking options specifying how we want to track the value.
211   virtual Result track(const Expr *E, const ExplodedNode *N,
212                        TrackingOptions Opts = {});
213 
214   /// Track how the value got stored into the given region and where it came
215   /// from.
216   ///
217   /// \param V We're searching for the store where \c R received this value.
218   /// \param R The region we're tracking.
219   /// \param Opts Tracking options specifying how we want to track the value.
220   /// \param Origin Only adds notes when the last store happened in a
221   ///        different stackframe to this one. Disregarded if the tracking kind
222   ///        is thorough.
223   ///        This is useful, because for non-tracked regions, notes about
224   ///        changes to its value in a nested stackframe could be pruned, and
225   ///        this visitor can prevent that without polluting the bugpath too
226   ///        much.
227   virtual Result track(SVal V, const MemRegion *R, TrackingOptions Opts = {},
228                        const StackFrameContext *Origin = nullptr);
229 
230   /// Handle the store operation and produce the note.
231   ///
232   /// \param SI The information fully describing the store.
233   /// \param Opts Tracking options specifying how we got to it.
234   ///
235   /// NOTE: this method is designed for sub-trackers and visitors.
236   virtual PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
237                                         TrackingOptions Opts);
238 
239   /// Add custom expression handler with the highest priority.
240   ///
241   /// It means that it will be asked for handling first, and can prevent
242   /// other handlers from running if decides to interrupt.
addHighPriorityHandler(ExpressionHandlerPtr SH)243   void addHighPriorityHandler(ExpressionHandlerPtr SH) {
244     ExpressionHandlers.push_front(std::move(SH));
245   }
246 
247   /// Add custom expression handler with the lowest priority.
248   ///
249   /// It means that it will be asked for handling last, and other handlers can
250   /// prevent it from running if any of them decides to interrupt.
addLowPriorityHandler(ExpressionHandlerPtr SH)251   void addLowPriorityHandler(ExpressionHandlerPtr SH) {
252     ExpressionHandlers.push_back(std::move(SH));
253   }
254 
255   /// Add custom store handler with the highest priority.
256   ///
257   /// It means that it will be asked for handling first, and will prevent
258   /// other handlers from running if it produces non-null note.
addHighPriorityHandler(StoreHandlerPtr SH)259   void addHighPriorityHandler(StoreHandlerPtr SH) {
260     StoreHandlers.push_front(std::move(SH));
261   }
262 
263   /// Add custom store handler with the lowest priority.
264   ///
265   /// It means that it will be asked for handling last, only
266   /// if all other handlers failed to produce the note.
addLowPriorityHandler(StoreHandlerPtr SH)267   void addLowPriorityHandler(StoreHandlerPtr SH) {
268     StoreHandlers.push_back(std::move(SH));
269   }
270 
271   /// Add custom expression/store handler with the highest priority
272   ///
273   /// See other overloads for explanation.
274   template <class HandlerType, class... Args>
addHighPriorityHandler(Args &&...ConstructorArgs)275   void addHighPriorityHandler(Args &&... ConstructorArgs) {
276     addHighPriorityHandler(std::make_unique<HandlerType>(
277         *this, std::forward<Args>(ConstructorArgs)...));
278   }
279 
280   /// Add custom expression/store handler with the lowest priority
281   ///
282   /// See other overloads for explanation.
283   template <class HandlerType, class... Args>
addLowPriorityHandler(Args &&...ConstructorArgs)284   void addLowPriorityHandler(Args &&... ConstructorArgs) {
285     addLowPriorityHandler(std::make_unique<HandlerType>(
286         *this, std::forward<Args>(ConstructorArgs)...));
287   }
288 };
289 
290 /// Handles expressions during the tracking.
291 class ExpressionHandler {
292 private:
293   Tracker &ParentTracker;
294 
295 public:
ExpressionHandler(Tracker & ParentTracker)296   ExpressionHandler(Tracker &ParentTracker) : ParentTracker(ParentTracker) {}
~ExpressionHandler()297   virtual ~ExpressionHandler() {}
298 
299   /// Handle the given expression from the given node.
300   ///
301   /// \param E The expression value which we are tracking
302   /// \param Original A node "downstream" where the tracking started.
303   /// \param ExprNode A node where the evaluation of \c E actually happens.
304   /// \param Opts Tracking options specifying how we are tracking the value.
305   virtual Tracker::Result handle(const Expr *E, const ExplodedNode *Original,
306                                  const ExplodedNode *ExprNode,
307                                  TrackingOptions Opts) = 0;
308 
309   /// \Return the tracker that initiated the process.
getParentTracker()310   Tracker &getParentTracker() { return ParentTracker; }
311 };
312 
313 /// Handles stores during the tracking.
314 class StoreHandler {
315 private:
316   Tracker &ParentTracker;
317 
318 public:
StoreHandler(Tracker & ParentTracker)319   StoreHandler(Tracker &ParentTracker) : ParentTracker(ParentTracker) {}
~StoreHandler()320   virtual ~StoreHandler() {}
321 
322   /// Handle the given store and produce the node.
323   ///
324   /// \param SI The information fully describing the store.
325   /// \param Opts Tracking options specifying how we are tracking the value.
326   ///
327   /// \return the produced note, null if the handler doesn't support this kind
328   ///         of stores.
329   virtual PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
330                                         TrackingOptions Opts) = 0;
331 
getParentTracker()332   Tracker &getParentTracker() { return ParentTracker; }
333 
334 protected:
335   PathDiagnosticPieceRef constructNote(StoreInfo SI, BugReporterContext &BRC,
336                                        StringRef NodeText);
337 };
338 
339 /// Visitor that tracks expressions and values.
340 class TrackingBugReporterVisitor : public BugReporterVisitor {
341 private:
342   TrackerRef ParentTracker;
343 
344 public:
TrackingBugReporterVisitor(TrackerRef ParentTracker)345   TrackingBugReporterVisitor(TrackerRef ParentTracker)
346       : ParentTracker(ParentTracker) {}
347 
getParentTracker()348   Tracker &getParentTracker() { return *ParentTracker; }
349 };
350 
351 /// Attempts to add visitors to track expression value back to its point of
352 /// origin.
353 ///
354 /// \param N A node "downstream" from the evaluation of the statement.
355 /// \param E The expression value which we are tracking
356 /// \param R The bug report to which visitors should be attached.
357 /// \param Opts Tracking options specifying how we are tracking the value.
358 ///
359 /// \return Whether or not the function was able to add visitors for this
360 ///         statement. Note that returning \c true does not actually imply
361 ///         that any visitors were added.
362 bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
363                           PathSensitiveBugReport &R, TrackingOptions Opts = {});
364 
365 /// Track how the value got stored into the given region and where it came
366 /// from.
367 ///
368 /// \param V We're searching for the store where \c R received this value.
369 /// \param R The region we're tracking.
370 /// \param Opts Tracking options specifying how we want to track the value.
371 /// \param Origin Only adds notes when the last store happened in a
372 ///        different stackframe to this one. Disregarded if the tracking kind
373 ///        is thorough.
374 ///        This is useful, because for non-tracked regions, notes about
375 ///        changes to its value in a nested stackframe could be pruned, and
376 ///        this visitor can prevent that without polluting the bugpath too
377 ///        much.
378 void trackStoredValue(KnownSVal V, const MemRegion *R,
379                       PathSensitiveBugReport &Report, TrackingOptions Opts = {},
380                       const StackFrameContext *Origin = nullptr);
381 
382 const Expr *getDerefExpr(const Stmt *S);
383 
384 } // namespace bugreporter
385 
386 class TrackConstraintBRVisitor final : public BugReporterVisitor {
387   DefinedSVal Constraint;
388   bool Assumption;
389   bool IsSatisfied = false;
390   bool IsZeroCheck;
391 
392   /// We should start tracking from the last node along the path in which the
393   /// value is constrained.
394   bool IsTrackingTurnedOn = false;
395 
396 public:
TrackConstraintBRVisitor(DefinedSVal constraint,bool assumption)397   TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
398       : Constraint(constraint), Assumption(assumption),
399         IsZeroCheck(!Assumption && Constraint.getAs<Loc>()) {}
400 
401   void Profile(llvm::FoldingSetNodeID &ID) const override;
402 
403   /// Return the tag associated with this visitor.  This tag will be used
404   /// to make all PathDiagnosticPieces created by this visitor.
405   static const char *getTag();
406 
407   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
408                                    BugReporterContext &BRC,
409                                    PathSensitiveBugReport &BR) override;
410 
411 private:
412   /// Checks if the constraint is valid in the current state.
413   bool isUnderconstrained(const ExplodedNode *N) const;
414 };
415 
416 /// \class NilReceiverBRVisitor
417 /// Prints path notes when a message is sent to a nil receiver.
418 class NilReceiverBRVisitor final : public BugReporterVisitor {
419 public:
Profile(llvm::FoldingSetNodeID & ID)420   void Profile(llvm::FoldingSetNodeID &ID) const override {
421     static int x = 0;
422     ID.AddPointer(&x);
423   }
424 
425   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
426                                    BugReporterContext &BRC,
427                                    PathSensitiveBugReport &BR) override;
428 
429   /// If the statement is a message send expression with nil receiver, returns
430   /// the receiver expression. Returns NULL otherwise.
431   static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N);
432 };
433 
434 /// Visitor that tries to report interesting diagnostics from conditions.
435 class ConditionBRVisitor final : public BugReporterVisitor {
436   // FIXME: constexpr initialization isn't supported by MSVC2013.
437   constexpr static llvm::StringLiteral GenericTrueMessage =
438       "Assuming the condition is true";
439   constexpr static llvm::StringLiteral GenericFalseMessage =
440       "Assuming the condition is false";
441 
442 public:
Profile(llvm::FoldingSetNodeID & ID)443   void Profile(llvm::FoldingSetNodeID &ID) const override {
444     static int x = 0;
445     ID.AddPointer(&x);
446   }
447 
448   /// Return the tag associated with this visitor.  This tag will be used
449   /// to make all PathDiagnosticPieces created by this visitor.
450   static const char *getTag();
451 
452   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
453                                    BugReporterContext &BRC,
454                                    PathSensitiveBugReport &BR) override;
455 
456   PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N,
457                                        BugReporterContext &BRC,
458                                        PathSensitiveBugReport &BR);
459 
460   PathDiagnosticPieceRef
461   VisitTerminator(const Stmt *Term, const ExplodedNode *N,
462                   const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
463                   PathSensitiveBugReport &R, BugReporterContext &BRC);
464 
465   PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond,
466                                        BugReporterContext &BRC,
467                                        PathSensitiveBugReport &R,
468                                        const ExplodedNode *N, bool TookTrue);
469 
470   PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
471                                        BugReporterContext &BRC,
472                                        PathSensitiveBugReport &R,
473                                        const ExplodedNode *N, bool TookTrue,
474                                        bool IsAssuming);
475 
476   PathDiagnosticPieceRef
477   VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
478                 BugReporterContext &BRC, PathSensitiveBugReport &R,
479                 const ExplodedNode *N, bool TookTrue, bool IsAssuming);
480 
481   PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const MemberExpr *ME,
482                                        BugReporterContext &BRC,
483                                        PathSensitiveBugReport &R,
484                                        const ExplodedNode *N, bool TookTrue,
485                                        bool IsAssuming);
486 
487   PathDiagnosticPieceRef
488   VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr,
489                          BugReporterContext &BRC, PathSensitiveBugReport &R,
490                          const ExplodedNode *N, bool TookTrue);
491 
492   /// Tries to print the value of the given expression.
493   ///
494   /// \param CondVarExpr The expression to print its value.
495   /// \param Out The stream to print.
496   /// \param N The node where we encountered the condition.
497   /// \param TookTrue Whether we took the \c true branch of the condition.
498   ///
499   /// \return Whether the print was successful. (The printing is successful if
500   ///         we model the value and we could obtain it.)
501   bool printValue(const Expr *CondVarExpr, raw_ostream &Out,
502                   const ExplodedNode *N, bool TookTrue, bool IsAssuming);
503 
504   bool patternMatch(const Expr *Ex,
505                     const Expr *ParentEx,
506                     raw_ostream &Out,
507                     BugReporterContext &BRC,
508                     PathSensitiveBugReport &R,
509                     const ExplodedNode *N,
510                     Optional<bool> &prunable,
511                     bool IsSameFieldName);
512 
513   static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece);
514 };
515 
516 /// Suppress reports that might lead to known false positives.
517 ///
518 /// Currently this suppresses reports based on locations of bugs.
519 class LikelyFalsePositiveSuppressionBRVisitor final
520     : public BugReporterVisitor {
521 public:
getTag()522   static void *getTag() {
523     static int Tag = 0;
524     return static_cast<void *>(&Tag);
525   }
526 
Profile(llvm::FoldingSetNodeID & ID)527   void Profile(llvm::FoldingSetNodeID &ID) const override {
528     ID.AddPointer(getTag());
529   }
530 
VisitNode(const ExplodedNode *,BugReporterContext &,PathSensitiveBugReport &)531   PathDiagnosticPieceRef VisitNode(const ExplodedNode *, BugReporterContext &,
532                                    PathSensitiveBugReport &) override {
533     return nullptr;
534   }
535 
536   void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
537                        PathSensitiveBugReport &BR) override;
538 };
539 
540 /// When a region containing undefined value or '0' value is passed
541 /// as an argument in a call, marks the call as interesting.
542 ///
543 /// As a result, BugReporter will not prune the path through the function even
544 /// if the region's contents are not modified/accessed by the call.
545 class UndefOrNullArgVisitor final : public BugReporterVisitor {
546   /// The interesting memory region this visitor is tracking.
547   const MemRegion *R;
548 
549 public:
UndefOrNullArgVisitor(const MemRegion * InR)550   UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
551 
Profile(llvm::FoldingSetNodeID & ID)552   void Profile(llvm::FoldingSetNodeID &ID) const override {
553     static int Tag = 0;
554     ID.AddPointer(&Tag);
555     ID.AddPointer(R);
556   }
557 
558   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
559                                    BugReporterContext &BRC,
560                                    PathSensitiveBugReport &BR) override;
561 };
562 
563 class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor {
564   /// The symbolic value for which we are tracking constraints.
565   /// This value is constrained to null in the end of path.
566   DefinedSVal V;
567 
568   /// Track if we found the node where the constraint was first added.
569   bool IsSatisfied = false;
570 
571   /// Since the visitors can be registered on nodes previous to the last
572   /// node in the BugReport, but the path traversal always starts with the last
573   /// node, the visitor invariant (that we start with a node in which V is null)
574   /// might not hold when node visitation starts. We are going to start tracking
575   /// from the last node in which the value is null.
576   bool IsTrackingTurnedOn = false;
577 
578 public:
579   SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N);
580 
581   void Profile(llvm::FoldingSetNodeID &ID) const override;
582 
583   /// Return the tag associated with this visitor.  This tag will be used
584   /// to make all PathDiagnosticPieces created by this visitor.
585   static const char *getTag();
586 
587   PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
588                                    BugReporterContext &BRC,
589                                    PathSensitiveBugReport &BR) override;
590 };
591 
592 /// The bug visitor will walk all the nodes in a path and collect all the
593 /// constraints. When it reaches the root node, will create a refutation
594 /// manager and check if the constraints are satisfiable
595 class FalsePositiveRefutationBRVisitor final : public BugReporterVisitor {
596 private:
597   /// Holds the constraints in a given path
598   ConstraintMap Constraints;
599 
600 public:
601   FalsePositiveRefutationBRVisitor();
602 
603   void Profile(llvm::FoldingSetNodeID &ID) const override;
604 
605   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
606                                    BugReporterContext &BRC,
607                                    PathSensitiveBugReport &BR) override;
608 
609   void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
610                        PathSensitiveBugReport &BR) override;
611   void addConstraints(const ExplodedNode *N,
612                       bool OverwriteConstraintsOnExistingSyms);
613 };
614 
615 /// The visitor detects NoteTags and displays the event notes they contain.
616 class TagVisitor : public BugReporterVisitor {
617 public:
618   void Profile(llvm::FoldingSetNodeID &ID) const override;
619 
620   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
621                                    BugReporterContext &BRC,
622                                    PathSensitiveBugReport &R) override;
623 };
624 
625 } // namespace ento
626 
627 } // namespace clang
628 
629 #endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
630