Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:07

0001 //===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines BugReporter, a utility class for generating
0010 //  PathDiagnostics for analyses based on ProgramState.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
0015 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
0016 
0017 #include "clang/Analysis/PathDiagnostic.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "clang/Basic/SourceLocation.h"
0020 #include "clang/Lex/Preprocessor.h"
0021 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
0022 #include "clang/StaticAnalyzer/Core/BugReporter/BugSuppression.h"
0023 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
0024 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
0025 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
0026 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
0027 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
0028 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
0029 #include "llvm/ADT/ArrayRef.h"
0030 #include "llvm/ADT/FoldingSet.h"
0031 #include "llvm/ADT/ImmutableSet.h"
0032 #include "llvm/ADT/SmallSet.h"
0033 #include "llvm/ADT/SmallVector.h"
0034 #include "llvm/ADT/StringMap.h"
0035 #include "llvm/ADT/StringRef.h"
0036 #include "llvm/ADT/ilist.h"
0037 #include "llvm/ADT/ilist_node.h"
0038 #include "llvm/ADT/iterator_range.h"
0039 #include <cassert>
0040 #include <memory>
0041 #include <optional>
0042 #include <string>
0043 #include <utility>
0044 #include <vector>
0045 
0046 namespace clang {
0047 
0048 class AnalyzerOptions;
0049 class ASTContext;
0050 class Decl;
0051 class LocationContext;
0052 class SourceManager;
0053 class Stmt;
0054 
0055 namespace ento {
0056 
0057 class BugType;
0058 class CheckerBase;
0059 class ExplodedGraph;
0060 class ExplodedNode;
0061 class ExprEngine;
0062 class MemRegion;
0063 
0064 //===----------------------------------------------------------------------===//
0065 // Interface for individual bug reports.
0066 //===----------------------------------------------------------------------===//
0067 
0068 /// A mapping from diagnostic consumers to the diagnostics they should
0069 /// consume.
0070 using DiagnosticForConsumerMapTy =
0071     llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>;
0072 
0073 /// Interface for classes constructing Stack hints.
0074 ///
0075 /// If a PathDiagnosticEvent occurs in a different frame than the final
0076 /// diagnostic the hints can be used to summarize the effect of the call.
0077 class StackHintGenerator {
0078 public:
0079   virtual ~StackHintGenerator() = 0;
0080 
0081   /// Construct the Diagnostic message for the given ExplodedNode.
0082   virtual std::string getMessage(const ExplodedNode *N) = 0;
0083 };
0084 
0085 /// Constructs a Stack hint for the given symbol.
0086 ///
0087 /// The class knows how to construct the stack hint message based on
0088 /// traversing the CallExpr associated with the call and checking if the given
0089 /// symbol is returned or is one of the arguments.
0090 /// The hint can be customized by redefining 'getMessageForX()' methods.
0091 class StackHintGeneratorForSymbol : public StackHintGenerator {
0092 private:
0093   SymbolRef Sym;
0094   std::string Msg;
0095 
0096 public:
0097   StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
0098   ~StackHintGeneratorForSymbol() override = default;
0099 
0100   /// Search the call expression for the symbol Sym and dispatch the
0101   /// 'getMessageForX()' methods to construct a specific message.
0102   std::string getMessage(const ExplodedNode *N) override;
0103 
0104   /// Produces the message of the following form:
0105   ///   'Msg via Nth parameter'
0106   virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
0107 
0108   virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
0109     return Msg;
0110   }
0111 
0112   virtual std::string getMessageForSymbolNotFound() {
0113     return Msg;
0114   }
0115 };
0116 
0117 /// This class provides an interface through which checkers can create
0118 /// individual bug reports.
0119 class BugReport {
0120 public:
0121   enum class Kind { Basic, PathSensitive };
0122 
0123 protected:
0124   friend class BugReportEquivClass;
0125   friend class BugReporter;
0126 
0127   Kind K;
0128   const BugType& BT;
0129   std::string ShortDescription;
0130   std::string Description;
0131 
0132   SmallVector<SourceRange, 4> Ranges;
0133   SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> Notes;
0134   SmallVector<FixItHint, 4> Fixits;
0135 
0136   BugReport(Kind kind, const BugType &bt, StringRef desc)
0137       : BugReport(kind, bt, "", desc) {}
0138 
0139   BugReport(Kind K, const BugType &BT, StringRef ShortDescription,
0140             StringRef Description)
0141       : K(K), BT(BT), ShortDescription(ShortDescription),
0142         Description(Description) {}
0143 
0144 public:
0145   virtual ~BugReport() = default;
0146 
0147   Kind getKind() const { return K; }
0148 
0149   const BugType& getBugType() const { return BT; }
0150 
0151   /// A verbose warning message that is appropriate for displaying next to
0152   /// the source code that introduces the problem. The description should be
0153   /// at least a full sentence starting with a capital letter. The period at
0154   /// the end of the warning is traditionally omitted. If the description
0155   /// consists of multiple sentences, periods between the sentences are
0156   /// encouraged, but the period at the end of the description is still omitted.
0157   StringRef getDescription() const { return Description; }
0158 
0159   /// A short general warning message that is appropriate for displaying in
0160   /// the list of all reported bugs. It should describe what kind of bug is found
0161   /// but does not need to try to go into details of that specific bug.
0162   /// Grammatical conventions of getDescription() apply here as well.
0163   StringRef getShortDescription(bool UseFallback = true) const {
0164     if (ShortDescription.empty() && UseFallback)
0165       return Description;
0166     return ShortDescription;
0167   }
0168 
0169   /// The primary location of the bug report that points at the undesirable
0170   /// behavior in the code. UIs should attach the warning description to this
0171   /// location. The warning description should describe the bad behavior
0172   /// at this location.
0173   virtual PathDiagnosticLocation getLocation() const = 0;
0174 
0175   /// The smallest declaration that contains the bug location.
0176   /// This is purely cosmetic; the declaration can be displayed to the user
0177   /// but it does not affect whether the report is emitted.
0178   virtual const Decl *getDeclWithIssue() const = 0;
0179 
0180   /// Get the location on which the report should be uniqued. Two warnings are
0181   /// considered to be equivalent whenever they have the same bug types,
0182   /// descriptions, and uniqueing locations. Out of a class of equivalent
0183   /// warnings only one gets displayed to the user. For most warnings the
0184   /// uniqueing location coincides with their location, but sometimes
0185   /// it makes sense to use different locations. For example, a leak
0186   /// checker can place the warning at the location where the last reference
0187   /// to the leaking resource is dropped but at the same time unique the warning
0188   /// by where that resource is acquired (allocated).
0189   virtual PathDiagnosticLocation getUniqueingLocation() const = 0;
0190 
0191   /// Get the declaration that corresponds to (usually contains) the uniqueing
0192   /// location. This is not actively used for uniqueing, i.e. otherwise
0193   /// identical reports that have different uniqueing decls will be considered
0194   /// equivalent.
0195   virtual const Decl *getUniqueingDecl() const = 0;
0196 
0197   /// Add new item to the list of additional notes that need to be attached to
0198   /// this report. If the report is path-sensitive, these notes will not be
0199   /// displayed as part of the execution path explanation, but will be displayed
0200   /// separately. Use bug visitors if you need to add an extra path note.
0201   void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
0202                ArrayRef<SourceRange> Ranges = {}) {
0203     auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
0204 
0205     for (const auto &R : Ranges)
0206       P->addRange(R);
0207 
0208     Notes.push_back(std::move(P));
0209   }
0210 
0211   ArrayRef<std::shared_ptr<PathDiagnosticNotePiece>> getNotes() {
0212     return Notes;
0213   }
0214 
0215   /// Add a range to a bug report.
0216   ///
0217   /// Ranges are used to highlight regions of interest in the source code.
0218   /// They should be at the same source code line as the BugReport location.
0219   /// By default, the source range of the statement corresponding to the error
0220   /// node will be used; add a single invalid range to specify absence of
0221   /// ranges.
0222   void addRange(SourceRange R) {
0223     assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
0224                            "to specify that the report does not have a range.");
0225     Ranges.push_back(R);
0226   }
0227 
0228   /// Get the SourceRanges associated with the report.
0229   virtual ArrayRef<SourceRange> getRanges() const {
0230     return Ranges;
0231   }
0232 
0233   /// Add a fix-it hint to the bug report.
0234   ///
0235   /// Fix-it hints are the suggested edits to the code that would resolve
0236   /// the problem explained by the bug report. Fix-it hints should be
0237   /// as conservative as possible because it is not uncommon for the user
0238   /// to blindly apply all fixits to their project. Note that it is very hard
0239   /// to produce a good fix-it hint for most path-sensitive warnings.
0240   void addFixItHint(const FixItHint &F) {
0241     Fixits.push_back(F);
0242   }
0243 
0244   llvm::ArrayRef<FixItHint> getFixits() const { return Fixits; }
0245 
0246   /// Reports are uniqued to ensure that we do not emit multiple diagnostics
0247   /// for each bug.
0248   virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;
0249 };
0250 
0251 class BasicBugReport : public BugReport {
0252   PathDiagnosticLocation Location;
0253   const Decl *DeclWithIssue = nullptr;
0254 
0255 public:
0256   BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
0257       : BugReport(Kind::Basic, bt, desc), Location(l) {}
0258 
0259   static bool classof(const BugReport *R) {
0260     return R->getKind() == Kind::Basic;
0261   }
0262 
0263   PathDiagnosticLocation getLocation() const override {
0264     assert(Location.isValid());
0265     return Location;
0266   }
0267 
0268   const Decl *getDeclWithIssue() const override {
0269     return DeclWithIssue;
0270   }
0271 
0272   PathDiagnosticLocation getUniqueingLocation() const override {
0273     return getLocation();
0274   }
0275 
0276   const Decl *getUniqueingDecl() const override {
0277     return getDeclWithIssue();
0278   }
0279 
0280   /// Specifically set the Decl where an issue occurred. This isn't necessary
0281   /// for BugReports that cover a path as it will be automatically inferred.
0282   void setDeclWithIssue(const Decl *declWithIssue) {
0283     DeclWithIssue = declWithIssue;
0284   }
0285 
0286   void Profile(llvm::FoldingSetNodeID& hash) const override;
0287 };
0288 
0289 class PathSensitiveBugReport : public BugReport {
0290 public:
0291   using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
0292   using visitor_iterator = VisitorList::iterator;
0293   using visitor_range = llvm::iterator_range<visitor_iterator>;
0294 
0295 protected:
0296   /// The ExplodedGraph node against which the report was thrown. It corresponds
0297   /// to the end of the execution path that demonstrates the bug.
0298   const ExplodedNode *ErrorNode = nullptr;
0299 
0300   /// The range that corresponds to ErrorNode's program point. It is usually
0301   /// highlighted in the report.
0302   const SourceRange ErrorNodeRange;
0303 
0304   /// Profile to identify equivalent bug reports for error report coalescing.
0305 
0306   /// A (stack of) a set of symbols that are registered with this
0307   /// report as being "interesting", and thus used to help decide which
0308   /// diagnostics to include when constructing the final path diagnostic.
0309   /// The stack is largely used by BugReporter when generating PathDiagnostics
0310   /// for multiple PathDiagnosticConsumers.
0311   llvm::DenseMap<SymbolRef, bugreporter::TrackingKind> InterestingSymbols;
0312 
0313   /// A (stack of) set of regions that are registered with this report as being
0314   /// "interesting", and thus used to help decide which diagnostics
0315   /// to include when constructing the final path diagnostic.
0316   /// The stack is largely used by BugReporter when generating PathDiagnostics
0317   /// for multiple PathDiagnosticConsumers.
0318   llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
0319       InterestingRegions;
0320 
0321   /// A set of location contexts that correspoind to call sites which should be
0322   /// considered "interesting".
0323   llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
0324 
0325   /// A set of custom visitors which generate "event" diagnostics at
0326   /// interesting points in the path.
0327   VisitorList Callbacks;
0328 
0329   /// Used for ensuring the visitors are only added once.
0330   llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
0331 
0332   /// When set, this flag disables all callstack pruning from a diagnostic
0333   /// path.  This is useful for some reports that want maximum fidelty
0334   /// when reporting an issue.
0335   bool DoNotPrunePath = false;
0336 
0337   /// Used to track unique reasons why a bug report might be invalid.
0338   ///
0339   /// \sa markInvalid
0340   /// \sa removeInvalidation
0341   using InvalidationRecord = std::pair<const void *, const void *>;
0342 
0343   /// If non-empty, this bug report is likely a false positive and should not be
0344   /// shown to the user.
0345   ///
0346   /// \sa markInvalid
0347   /// \sa removeInvalidation
0348   llvm::SmallSet<InvalidationRecord, 4> Invalidations;
0349 
0350   /// Conditions we're already tracking.
0351   llvm::SmallSet<const ExplodedNode *, 4> TrackedConditions;
0352 
0353   /// Reports with different uniqueing locations are considered to be different
0354   /// for the purposes of deduplication.
0355   PathDiagnosticLocation UniqueingLocation;
0356   const Decl *UniqueingDecl;
0357 
0358   const Stmt *getStmt() const;
0359 
0360   /// If an event occurs in a different frame than the final diagnostic,
0361   /// supply a message that will be used to construct an extra hint on the
0362   /// returns from all the calls on the stack from this event to the final
0363   /// diagnostic.
0364   // FIXME: Allow shared_ptr keys in DenseMap?
0365   std::map<PathDiagnosticPieceRef, std::unique_ptr<StackHintGenerator>>
0366       StackHints;
0367 
0368 public:
0369   PathSensitiveBugReport(const BugType &bt, StringRef desc,
0370                          const ExplodedNode *errorNode)
0371       : PathSensitiveBugReport(bt, desc, desc, errorNode) {}
0372 
0373   PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
0374                          const ExplodedNode *errorNode)
0375       : PathSensitiveBugReport(bt, shortDesc, desc, errorNode,
0376                                /*LocationToUnique*/ {},
0377                                /*DeclToUnique*/ nullptr) {}
0378 
0379   /// Create a PathSensitiveBugReport with a custom uniqueing location.
0380   ///
0381   /// The reports that have the same report location, description, bug type, and
0382   /// ranges are uniqued - only one of the equivalent reports will be presented
0383   /// to the user. This method allows to rest the location which should be used
0384   /// for uniquing reports. For example, memory leaks checker, could set this to
0385   /// the allocation site, rather then the location where the bug is reported.
0386   PathSensitiveBugReport(const BugType &bt, StringRef desc,
0387                          const ExplodedNode *errorNode,
0388                          PathDiagnosticLocation LocationToUnique,
0389                          const Decl *DeclToUnique)
0390       : PathSensitiveBugReport(bt, desc, desc, errorNode, LocationToUnique,
0391                                DeclToUnique) {}
0392 
0393   PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
0394                          const ExplodedNode *errorNode,
0395                          PathDiagnosticLocation LocationToUnique,
0396                          const Decl *DeclToUnique);
0397 
0398   static bool classof(const BugReport *R) {
0399     return R->getKind() == Kind::PathSensitive;
0400   }
0401 
0402   const ExplodedNode *getErrorNode() const { return ErrorNode; }
0403 
0404   /// Indicates whether or not any path pruning should take place
0405   /// when generating a PathDiagnostic from this BugReport.
0406   bool shouldPrunePath() const { return !DoNotPrunePath; }
0407 
0408   /// Disable all path pruning when generating a PathDiagnostic.
0409   void disablePathPruning() { DoNotPrunePath = true; }
0410 
0411   /// Get the location on which the report should be uniqued.
0412   PathDiagnosticLocation getUniqueingLocation() const override {
0413     return UniqueingLocation;
0414   }
0415 
0416   /// Get the declaration containing the uniqueing location.
0417   const Decl *getUniqueingDecl() const override {
0418     return UniqueingDecl;
0419   }
0420 
0421   const Decl *getDeclWithIssue() const override;
0422 
0423   ArrayRef<SourceRange> getRanges() const override;
0424 
0425   PathDiagnosticLocation getLocation() const override;
0426 
0427   /// Marks a symbol as interesting. Different kinds of interestingness will
0428   /// be processed differently by visitors (e.g. if the tracking kind is
0429   /// condition, will append "will be used as a condition" to the message).
0430   void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind =
0431                                           bugreporter::TrackingKind::Thorough);
0432 
0433   void markNotInteresting(SymbolRef sym);
0434 
0435   /// Marks a region as interesting. Different kinds of interestingness will
0436   /// be processed differently by visitors (e.g. if the tracking kind is
0437   /// condition, will append "will be used as a condition" to the message).
0438   void markInteresting(
0439       const MemRegion *R,
0440       bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough);
0441 
0442   void markNotInteresting(const MemRegion *R);
0443 
0444   /// Marks a symbolic value as interesting. Different kinds of interestingness
0445   /// will be processed differently by visitors (e.g. if the tracking kind is
0446   /// condition, will append "will be used as a condition" to the message).
0447   void markInteresting(SVal V, bugreporter::TrackingKind TKind =
0448                                    bugreporter::TrackingKind::Thorough);
0449   void markInteresting(const LocationContext *LC);
0450 
0451   bool isInteresting(SymbolRef sym) const;
0452   bool isInteresting(const MemRegion *R) const;
0453   bool isInteresting(SVal V) const;
0454   bool isInteresting(const LocationContext *LC) const;
0455 
0456   std::optional<bugreporter::TrackingKind>
0457   getInterestingnessKind(SymbolRef sym) const;
0458 
0459   std::optional<bugreporter::TrackingKind>
0460   getInterestingnessKind(const MemRegion *R) const;
0461 
0462   std::optional<bugreporter::TrackingKind> getInterestingnessKind(SVal V) const;
0463 
0464   /// Returns whether or not this report should be considered valid.
0465   ///
0466   /// Invalid reports are those that have been classified as likely false
0467   /// positives after the fact.
0468   bool isValid() const {
0469     return Invalidations.empty();
0470   }
0471 
0472   /// Marks the current report as invalid, meaning that it is probably a false
0473   /// positive and should not be reported to the user.
0474   ///
0475   /// The \p Tag and \p Data arguments are intended to be opaque identifiers for
0476   /// this particular invalidation, where \p Tag represents the visitor
0477   /// responsible for invalidation, and \p Data represents the reason this
0478   /// visitor decided to invalidate the bug report.
0479   ///
0480   /// \sa removeInvalidation
0481   void markInvalid(const void *Tag, const void *Data) {
0482     Invalidations.insert(std::make_pair(Tag, Data));
0483   }
0484 
0485   /// Profile to identify equivalent bug reports for error report coalescing.
0486   /// Reports are uniqued to ensure that we do not emit multiple diagnostics
0487   /// for each bug.
0488   void Profile(llvm::FoldingSetNodeID &hash) const override;
0489 
0490   /// Add custom or predefined bug report visitors to this report.
0491   ///
0492   /// The visitors should be used when the default trace is not sufficient.
0493   /// For example, they allow constructing a more elaborate trace.
0494   /// @{
0495   void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);
0496 
0497   template <class VisitorType, class... Args>
0498   void addVisitor(Args &&... ConstructorArgs) {
0499     addVisitor(
0500         std::make_unique<VisitorType>(std::forward<Args>(ConstructorArgs)...));
0501   }
0502   /// @}
0503 
0504   /// Remove all visitors attached to this bug report.
0505   void clearVisitors();
0506 
0507   /// Iterators through the custom diagnostic visitors.
0508   visitor_iterator visitor_begin() { return Callbacks.begin(); }
0509   visitor_iterator visitor_end() { return Callbacks.end(); }
0510   visitor_range visitors() { return {visitor_begin(), visitor_end()}; }
0511 
0512   /// Notes that the condition of the CFGBlock associated with \p Cond is
0513   /// being tracked.
0514   /// \returns false if the condition is already being tracked.
0515   bool addTrackedCondition(const ExplodedNode *Cond) {
0516     return TrackedConditions.insert(Cond).second;
0517   }
0518 
0519   void addCallStackHint(PathDiagnosticPieceRef Piece,
0520                         std::unique_ptr<StackHintGenerator> StackHint) {
0521     StackHints[Piece] = std::move(StackHint);
0522   }
0523 
0524   bool hasCallStackHint(PathDiagnosticPieceRef Piece) const {
0525     return StackHints.count(Piece) > 0;
0526   }
0527 
0528   /// Produce the hint for the given node. The node contains
0529   /// information about the call for which the diagnostic can be generated.
0530   std::string
0531   getCallStackMessage(PathDiagnosticPieceRef Piece,
0532                       const ExplodedNode *N) const {
0533     auto I = StackHints.find(Piece);
0534     if (I != StackHints.end())
0535       return I->second->getMessage(N);
0536     return "";
0537   }
0538 };
0539 
0540 //===----------------------------------------------------------------------===//
0541 // BugTypes (collections of related reports).
0542 //===----------------------------------------------------------------------===//
0543 
0544 class BugReportEquivClass : public llvm::FoldingSetNode {
0545   friend class BugReporter;
0546 
0547   /// List of *owned* BugReport objects.
0548   llvm::SmallVector<std::unique_ptr<BugReport>, 4> Reports;
0549 
0550   void AddReport(std::unique_ptr<BugReport> &&R) {
0551     Reports.push_back(std::move(R));
0552   }
0553 
0554 public:
0555   BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); }
0556 
0557   ArrayRef<std::unique_ptr<BugReport>> getReports() const { return Reports; }
0558 
0559   void Profile(llvm::FoldingSetNodeID& ID) const {
0560     assert(!Reports.empty());
0561     Reports.front()->Profile(ID);
0562   }
0563 };
0564 
0565 //===----------------------------------------------------------------------===//
0566 // BugReporter and friends.
0567 //===----------------------------------------------------------------------===//
0568 
0569 class BugReporterData {
0570 public:
0571   virtual ~BugReporterData() = default;
0572 
0573   virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
0574   virtual ASTContext &getASTContext() = 0;
0575   virtual SourceManager &getSourceManager() = 0;
0576   virtual AnalyzerOptions &getAnalyzerOptions() = 0;
0577   virtual Preprocessor &getPreprocessor() = 0;
0578 };
0579 
0580 /// BugReporter is a utility class for generating PathDiagnostics for analysis.
0581 /// It collects the BugReports and BugTypes and knows how to generate
0582 /// and flush the corresponding diagnostics.
0583 ///
0584 /// The base class is used for generating path-insensitive
0585 class BugReporter {
0586 private:
0587   BugReporterData& D;
0588 
0589   /// The top-level entry point for the issue to be reported.
0590   const Decl *AnalysisEntryPoint = nullptr;
0591 
0592   /// Generate and flush the diagnostics for the given bug report.
0593   void FlushReport(BugReportEquivClass& EQ);
0594 
0595   /// The set of bug reports tracked by the BugReporter.
0596   llvm::FoldingSet<BugReportEquivClass> EQClasses;
0597 
0598   /// A vector of BugReports for tracking the allocated pointers and cleanup.
0599   std::vector<BugReportEquivClass *> EQClassesVector;
0600 
0601   /// User-provided in-code suppressions.
0602   BugSuppression UserSuppressions;
0603 
0604 public:
0605   BugReporter(BugReporterData &d);
0606   virtual ~BugReporter();
0607 
0608   /// Generate and flush diagnostics for all bug reports.
0609   void FlushReports();
0610 
0611   ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
0612     return D.getPathDiagnosticConsumers();
0613   }
0614 
0615   /// Iterator over the set of BugReports tracked by the BugReporter.
0616   using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
0617   llvm::iterator_range<EQClasses_iterator> equivalenceClasses() {
0618     return EQClasses;
0619   }
0620 
0621   ASTContext &getContext() { return D.getASTContext(); }
0622 
0623   const SourceManager &getSourceManager() { return D.getSourceManager(); }
0624 
0625   const AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }
0626 
0627   Preprocessor &getPreprocessor() { return D.getPreprocessor(); }
0628 
0629   /// Get the top-level entry point for the issue to be reported.
0630   const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }
0631 
0632   void setAnalysisEntryPoint(const Decl *EntryPoint) {
0633     assert(EntryPoint);
0634     AnalysisEntryPoint = EntryPoint;
0635   }
0636 
0637   /// Add the given report to the set of reports tracked by BugReporter.
0638   ///
0639   /// The reports are usually generated by the checkers. Further, they are
0640   /// folded based on the profile value, which is done to coalesce similar
0641   /// reports.
0642   virtual void emitReport(std::unique_ptr<BugReport> R);
0643 
0644   void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
0645                        StringRef BugName, StringRef BugCategory,
0646                        StringRef BugStr, PathDiagnosticLocation Loc,
0647                        ArrayRef<SourceRange> Ranges = {},
0648                        ArrayRef<FixItHint> Fixits = {});
0649 
0650   void EmitBasicReport(const Decl *DeclWithIssue, CheckerNameRef CheckerName,
0651                        StringRef BugName, StringRef BugCategory,
0652                        StringRef BugStr, PathDiagnosticLocation Loc,
0653                        ArrayRef<SourceRange> Ranges = {},
0654                        ArrayRef<FixItHint> Fixits = {});
0655 
0656 private:
0657   llvm::StringMap<std::unique_ptr<BugType>> StrBugTypes;
0658 
0659   /// Returns a BugType that is associated with the given name and
0660   /// category.
0661   BugType *getBugTypeForName(CheckerNameRef CheckerName, StringRef name,
0662                              StringRef category);
0663 
0664   virtual BugReport *
0665   findReportInEquivalenceClass(BugReportEquivClass &eqClass,
0666                                SmallVectorImpl<BugReport *> &bugReports) {
0667     return eqClass.getReports()[0].get();
0668   }
0669 
0670 protected:
0671   /// Generate the diagnostics for the given bug report.
0672   virtual std::unique_ptr<DiagnosticForConsumerMapTy>
0673   generateDiagnosticForConsumerMap(BugReport *exampleReport,
0674                                    ArrayRef<PathDiagnosticConsumer *> consumers,
0675                                    ArrayRef<BugReport *> bugReports);
0676 };
0677 
0678 /// GRBugReporter is used for generating path-sensitive reports.
0679 class PathSensitiveBugReporter final : public BugReporter {
0680   ExprEngine& Eng;
0681 
0682   BugReport *findReportInEquivalenceClass(
0683       BugReportEquivClass &eqClass,
0684       SmallVectorImpl<BugReport *> &bugReports) override;
0685 
0686   /// Generate the diagnostics for the given bug report.
0687   std::unique_ptr<DiagnosticForConsumerMapTy>
0688   generateDiagnosticForConsumerMap(BugReport *exampleReport,
0689                                    ArrayRef<PathDiagnosticConsumer *> consumers,
0690                                    ArrayRef<BugReport *> bugReports) override;
0691 public:
0692   PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
0693       : BugReporter(d), Eng(eng) {}
0694 
0695   /// getGraph - Get the exploded graph created by the analysis engine
0696   ///  for the analyzed method or function.
0697   const ExplodedGraph &getGraph() const;
0698 
0699   /// getStateManager - Return the state manager used by the analysis
0700   ///  engine.
0701   ProgramStateManager &getStateManager() const;
0702 
0703   /// \p bugReports A set of bug reports within a *single* equivalence class
0704   ///
0705   /// \return A mapping from consumers to the corresponding diagnostics.
0706   /// Iterates through the bug reports within a single equivalence class,
0707   /// stops at a first non-invalidated report.
0708   std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
0709       ArrayRef<PathDiagnosticConsumer *> consumers,
0710       ArrayRef<PathSensitiveBugReport *> &bugReports);
0711 
0712   void emitReport(std::unique_ptr<BugReport> R) override;
0713 };
0714 
0715 
0716 class BugReporterContext {
0717   PathSensitiveBugReporter &BR;
0718 
0719   virtual void anchor();
0720 
0721 public:
0722   BugReporterContext(PathSensitiveBugReporter &br) : BR(br) {}
0723 
0724   virtual ~BugReporterContext() = default;
0725 
0726   PathSensitiveBugReporter& getBugReporter() { return BR; }
0727   const PathSensitiveBugReporter &getBugReporter() const { return BR; }
0728 
0729   ProgramStateManager& getStateManager() const {
0730     return BR.getStateManager();
0731   }
0732 
0733   ASTContext &getASTContext() const {
0734     return BR.getContext();
0735   }
0736 
0737   const SourceManager& getSourceManager() const {
0738     return BR.getSourceManager();
0739   }
0740 
0741   const AnalyzerOptions &getAnalyzerOptions() const {
0742     return BR.getAnalyzerOptions();
0743   }
0744 };
0745 
0746 /// The tag that carries some information with it.
0747 ///
0748 /// It can be valuable to produce tags with some bits of information and later
0749 /// reuse them for a better diagnostic.
0750 ///
0751 /// Please make sure that derived class' constuctor is private and that the user
0752 /// can only create objects using DataTag::Factory.  This also means that
0753 /// DataTag::Factory should be friend for every derived class.
0754 class DataTag : public ProgramPointTag {
0755 public:
0756   StringRef getTagDescription() const override { return "Data Tag"; }
0757 
0758   // Manage memory for DataTag objects.
0759   class Factory {
0760     std::vector<std::unique_ptr<DataTag>> Tags;
0761 
0762   public:
0763     template <class DataTagType, class... Args>
0764     const DataTagType *make(Args &&... ConstructorArgs) {
0765       // We cannot use std::make_unique because we cannot access the private
0766       // constructor from inside it.
0767       Tags.emplace_back(
0768           new DataTagType(std::forward<Args>(ConstructorArgs)...));
0769       return static_cast<DataTagType *>(Tags.back().get());
0770     }
0771   };
0772 
0773 protected:
0774   DataTag(void *TagKind) : ProgramPointTag(TagKind) {}
0775 };
0776 
0777 /// The tag upon which the TagVisitor reacts. Add these in order to display
0778 /// additional PathDiagnosticEventPieces along the path.
0779 class NoteTag : public DataTag {
0780 public:
0781   using Callback = std::function<std::string(BugReporterContext &,
0782                                              PathSensitiveBugReport &)>;
0783 
0784 private:
0785   static int Kind;
0786 
0787   const Callback Cb;
0788   const bool IsPrunable;
0789 
0790   NoteTag(Callback &&Cb, bool IsPrunable)
0791       : DataTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}
0792 
0793 public:
0794   static bool classof(const ProgramPointTag *T) {
0795     return T->getTagKind() == &Kind;
0796   }
0797 
0798   std::optional<std::string> generateMessage(BugReporterContext &BRC,
0799                                              PathSensitiveBugReport &R) const {
0800     std::string Msg = Cb(BRC, R);
0801     if (Msg.empty())
0802       return std::nullopt;
0803 
0804     return std::move(Msg);
0805   }
0806 
0807   StringRef getTagDescription() const override {
0808     // TODO: Remember a few examples of generated messages
0809     // and display them in the ExplodedGraph dump by
0810     // returning them from this function.
0811     return "Note Tag";
0812   }
0813 
0814   bool isPrunable() const { return IsPrunable; }
0815 
0816   friend class Factory;
0817   friend class TagVisitor;
0818 };
0819 
0820 } // namespace ento
0821 
0822 } // namespace clang
0823 
0824 #endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H