diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) | |
download | src-486754660bb926339aefcf012a3f848592babb8b.tar.gz src-486754660bb926339aefcf012a3f848592babb8b.zip |
Vendor import of clang trunk r338150:vendor/clang/clang-trunk-r338150
Notes
Notes:
svn path=/vendor/clang/dist/; revision=336815
svn path=/vendor/clang/clang-trunk-r338150/; revision=336816; tag=vendor/clang/clang-trunk-r338150
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h | 246 |
1 files changed, 135 insertions, 111 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index cd1355d03b63..111e1d1e8e20 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -1,4 +1,4 @@ -//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===// +//===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,78 +15,101 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" +#include <cassert> +#include <memory> +#include <string> +#include <utility> +#include <vector> namespace clang { +class AnalyzerOptions; class ASTContext; +class Decl; class DiagnosticsEngine; +class LocationContext; +class SourceManager; class Stmt; -class ParentMap; namespace ento { -class PathDiagnostic; -class ExplodedNode; +class BugType; +class CheckerBase; class ExplodedGraph; -class BugReport; -class BugReporter; -class BugReporterContext; +class ExplodedNode; class ExprEngine; -class BugType; +class MemRegion; +class SValBuilder; //===----------------------------------------------------------------------===// // Interface for individual bug reports. //===----------------------------------------------------------------------===// +/// A mapping from diagnostic consumers to the diagnostics they should +/// consume. +using DiagnosticForConsumerMapTy = + llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>; + /// This class provides an interface through which checkers can create /// individual bug reports. class BugReport : public llvm::ilist_node<BugReport> { public: class NodeResolver { virtual void anchor(); + public: - virtual ~NodeResolver() {} + virtual ~NodeResolver() = default; + virtual const ExplodedNode* getOriginalNode(const ExplodedNode *N) = 0; }; - typedef const SourceRange *ranges_iterator; - typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList; - typedef VisitorList::iterator visitor_iterator; - typedef SmallVector<StringRef, 2> ExtraTextList; - typedef SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> NoteList; + using ranges_iterator = const SourceRange *; + using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>; + using visitor_iterator = VisitorList::iterator; + using ExtraTextList = SmallVector<StringRef, 2>; + using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>; protected: - friend class BugReporter; friend class BugReportEquivClass; + friend class BugReporter; BugType& BT; - const Decl *DeclWithIssue; + const Decl *DeclWithIssue = nullptr; std::string ShortDescription; std::string Description; PathDiagnosticLocation Location; PathDiagnosticLocation UniqueingLocation; const Decl *UniqueingDecl; - const ExplodedNode *ErrorNode; + const ExplodedNode *ErrorNode = nullptr; SmallVector<SourceRange, 4> Ranges; ExtraTextList ExtraText; NoteList Notes; - typedef llvm::DenseSet<SymbolRef> Symbols; - typedef llvm::DenseSet<const MemRegion *> Regions; + using Symbols = llvm::DenseSet<SymbolRef>; + using Regions = llvm::DenseSet<const MemRegion *>; /// A (stack of) a set of symbols that are registered with this /// report as being "interesting", and thus used to help decide which @@ -113,20 +136,16 @@ protected: /// Used for ensuring the visitors are only added once. llvm::FoldingSet<BugReporterVisitor> CallbacksSet; - /// Used for clients to tell if the report's configuration has changed - /// since the last time they checked. - unsigned ConfigurationChangeToken; - /// When set, this flag disables all callstack pruning from a diagnostic /// path. This is useful for some reports that want maximum fidelty /// when reporting an issue. - bool DoNotPrunePath; + bool DoNotPrunePath = false; /// Used to track unique reasons why a bug report might be invalid. /// /// \sa markInvalid /// \sa removeInvalidation - typedef std::pair<const void *, const void *> InvalidationRecord; + using InvalidationRecord = std::pair<const void *, const void *>; /// If non-empty, this bug report is likely a false positive and should not be /// shown to the user. @@ -146,20 +165,17 @@ private: public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) - : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode), - ConfigurationChangeToken(0), DoNotPrunePath(false) {} + : BT(bt), Description(desc), ErrorNode(errornode) {} BugReport(BugType& bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errornode) - : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc), - Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0), - DoNotPrunePath(false) {} + : BT(bt), ShortDescription(shortDesc), Description(desc), + ErrorNode(errornode) {} BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l) - : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l), - ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {} + : BT(bt), Description(desc), Location(l) {} - /// \brief Create a BugReport with a custom uniqueing location. + /// Create a BugReport with a custom uniqueing location. /// /// The reports that have the same report location, description, bug type, and /// ranges are uniqued - only one of the equivalent reports will be presented @@ -168,18 +184,15 @@ public: /// the allocation site, rather then the location where the bug is reported. BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) - : BT(bt), DeclWithIssue(nullptr), Description(desc), - UniqueingLocation(LocationToUnique), - UniqueingDecl(DeclToUnique), - ErrorNode(errornode), ConfigurationChangeToken(0), - DoNotPrunePath(false) {} + : BT(bt), Description(desc), UniqueingLocation(LocationToUnique), + UniqueingDecl(DeclToUnique), ErrorNode(errornode) {} virtual ~BugReport(); const BugType& getBugType() const { return BT; } BugType& getBugType() { return BT; } - /// \brief True when the report has an execution path associated with it. + /// True when the report has an execution path associated with it. /// /// A report is said to be path-sensitive if it was thrown against a /// particular exploded node in the path-sensitive analysis graph. @@ -218,10 +231,6 @@ public: bool isInteresting(SVal V); bool isInteresting(const LocationContext *LC); - unsigned getConfigurationChangeToken() const { - return ConfigurationChangeToken; - } - /// Returns whether or not this report should be considered valid. /// /// Invalid reports are those that have been classified as likely false @@ -242,13 +251,6 @@ public: void markInvalid(const void *Tag, const void *Data) { Invalidations.insert(std::make_pair(Tag, Data)); } - - /// Reverses the effects of a previous invalidation. - /// - /// \sa markInvalid - void removeInvalidation(const void *Tag, const void *Data) { - Invalidations.erase(std::make_pair(Tag, Data)); - } /// Return the canonical declaration, be it a method or class, where /// this issue semantically occurred. @@ -286,7 +288,7 @@ public: return Notes; } - /// \brief This allows for addition of meta data to the diagnostic. + /// This allows for addition of meta data to the diagnostic. /// /// Currently, only the HTMLDiagnosticClient knows how to display it. void addExtraText(StringRef S) { @@ -297,26 +299,26 @@ public: return ExtraText; } - /// \brief Return the "definitive" location of the reported bug. + /// Return the "definitive" location of the reported bug. /// /// While a bug can span an entire path, usually there is a specific /// location that can be used to identify where the key issue occurred. /// This location is used by clients rendering diagnostics. virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; - /// \brief Get the location on which the report should be uniqued. + /// Get the location on which the report should be uniqued. PathDiagnosticLocation getUniqueingLocation() const { return UniqueingLocation; } - /// \brief Get the declaration containing the uniqueing location. + /// Get the declaration containing the uniqueing location. const Decl *getUniqueingDecl() const { return UniqueingDecl; } const Stmt *getStmt() const; - /// \brief Add a range to a bug report. + /// Add a range to a bug report. /// /// Ranges are used to highlight regions of interest in the source code. /// They should be at the same source code line as the BugReport location. @@ -329,10 +331,10 @@ public: Ranges.push_back(R); } - /// \brief Get the SourceRanges associated with the report. + /// Get the SourceRanges associated with the report. virtual llvm::iterator_range<ranges_iterator> getRanges(); - /// \brief Add custom or predefined bug report visitors to this report. + /// Add custom or predefined bug report visitors to this report. /// /// The visitors should be used when the default trace is not sufficient. /// For example, they allow constructing a more elaborate trace. @@ -341,6 +343,9 @@ public: /// registerVarDeclsLastStore(). void addVisitor(std::unique_ptr<BugReporterVisitor> visitor); + /// Remove all visitors attached to this bug report. + void clearVisitors(); + /// Iterators through the custom diagnostic visitors. visitor_iterator visitor_begin() { return Callbacks.begin(); } visitor_iterator visitor_end() { return Callbacks.end(); } @@ -356,10 +361,11 @@ public: //===----------------------------------------------------------------------===// class BugReportEquivClass : public llvm::FoldingSetNode { + friend class BugReporter; + /// List of *owned* BugReport objects. llvm::ilist<BugReport> Reports; - friend class BugReporter; void AddReport(std::unique_ptr<BugReport> R) { Reports.push_back(R.release()); } @@ -373,8 +379,8 @@ public: Reports.front().Profile(ID); } - typedef llvm::ilist<BugReport>::iterator iterator; - typedef llvm::ilist<BugReport>::const_iterator const_iterator; + using iterator = llvm::ilist<BugReport>::iterator; + using const_iterator = llvm::ilist<BugReport>::const_iterator; iterator begin() { return Reports.begin(); } iterator end() { return Reports.end(); } @@ -390,22 +396,26 @@ public: class BugReporterData { public: virtual ~BugReporterData(); + virtual DiagnosticsEngine& getDiagnostic() = 0; virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; virtual ASTContext &getASTContext() = 0; - virtual SourceManager& getSourceManager() = 0; - virtual AnalyzerOptions& getAnalyzerOptions() = 0; + virtual SourceManager &getSourceManager() = 0; + virtual AnalyzerOptions &getAnalyzerOptions() = 0; }; /// BugReporter is a utility class for generating PathDiagnostics for analysis. /// It collects the BugReports and BugTypes and knows how to generate /// and flush the corresponding diagnostics. +/// +/// The base class is used for generating path-insensitive class BugReporter { public: enum Kind { BaseBRKind, GRBugReporterKind }; private: - typedef llvm::ImmutableSet<BugType*> BugTypesTy; + using BugTypesTy = llvm::ImmutableSet<BugType *>; + BugTypesTy::Factory F; BugTypesTy BugTypes; @@ -415,27 +425,28 @@ private: /// Generate and flush the diagnostics for the given bug report. void FlushReport(BugReportEquivClass& EQ); - /// Generate and flush the diagnostics for the given bug report - /// and PathDiagnosticConsumer. - void FlushReport(BugReport *exampleReport, - PathDiagnosticConsumer &PD, - ArrayRef<BugReport*> BugReports); + /// Generate the diagnostics for the given bug report. + std::unique_ptr<DiagnosticForConsumerMapTy> + generateDiagnosticForConsumerMap(BugReport *exampleReport, + ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> bugReports); /// The set of bug reports tracked by the BugReporter. llvm::FoldingSet<BugReportEquivClass> EQClasses; + /// A vector of BugReports for tracking the allocated pointers and cleanup. std::vector<BugReportEquivClass *> EQClassesVector; protected: - BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), - D(d) {} + BugReporter(BugReporterData& d, Kind k) + : BugTypes(F.getEmptySet()), kind(k), D(d) {} public: - BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind), - D(d) {} + BugReporter(BugReporterData& d) + : BugTypes(F.getEmptySet()), kind(BaseBRKind), D(d) {} virtual ~BugReporter(); - /// \brief Generate and flush diagnostics for all bug reports. + /// Generate and flush diagnostics for all bug reports. void FlushReports(); Kind getKind() const { return kind; } @@ -448,33 +459,31 @@ public: return D.getPathDiagnosticConsumers(); } - /// \brief Iterator over the set of BugTypes tracked by the BugReporter. - typedef BugTypesTy::iterator iterator; + /// Iterator over the set of BugTypes tracked by the BugReporter. + using iterator = BugTypesTy::iterator; iterator begin() { return BugTypes.begin(); } iterator end() { return BugTypes.end(); } - /// \brief Iterator over the set of BugReports tracked by the BugReporter. - typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; + /// Iterator over the set of BugReports tracked by the BugReporter. + using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator; EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } EQClasses_iterator EQClasses_end() { return EQClasses.end(); } ASTContext &getContext() { return D.getASTContext(); } - SourceManager& getSourceManager() { return D.getSourceManager(); } + SourceManager &getSourceManager() { return D.getSourceManager(); } - AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); } + AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); } - virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, - PathDiagnosticConsumer &PC, - ArrayRef<BugReport *> &bugReports) { - return true; + virtual std::unique_ptr<DiagnosticForConsumerMapTy> + generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> &bugReports) { + return {}; } - bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); - void Register(BugType *BT); - /// \brief Add the given report to the set of reports tracked by BugReporter. + /// Add the given report to the set of reports tracked by BugReporter. /// /// The reports are usually generated by the checkers. Further, they are /// folded based on the profile value, which is done to coalesce similar @@ -494,25 +503,22 @@ public: private: llvm::StringMap<BugType *> StrBugTypes; - /// \brief Returns a BugType that is associated with the given name and + /// Returns a BugType that is associated with the given name and /// category. BugType *getBugTypeForName(CheckName CheckName, StringRef name, StringRef category); }; -// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. +/// GRBugReporter is used for generating path-sensitive reports. class GRBugReporter : public BugReporter { ExprEngine& Eng; + public: GRBugReporter(BugReporterData& d, ExprEngine& eng) - : BugReporter(d, GRBugReporterKind), Eng(eng) {} + : BugReporter(d, GRBugReporterKind), Eng(eng) {} ~GRBugReporter() override; - /// getEngine - Return the analysis engine used to analyze a given - /// function or method. - ExprEngine &getEngine() { return Eng; } - /// getGraph - Get the exploded graph created by the analysis engine /// for the analyzed method or function. ExplodedGraph &getGraph(); @@ -521,16 +527,14 @@ public: /// engine. ProgramStateManager &getStateManager(); - /// Generates a path corresponding to one of the given bug reports. - /// - /// Which report is used for path generation is not specified. The - /// bug reporter will try to pick the shortest path, but this is not - /// guaranteed. + /// \p bugReports A set of bug reports within a *single* equivalence class /// - /// \return True if the report was valid and a path was generated, - /// false if the reports should be considered invalid. - bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, - ArrayRef<BugReport*> &bugReports) override; + /// \return A mapping from consumers to the corresponding diagnostics. + /// Iterates through the bug reports within a single equivalence class, + /// stops at a first non-invalidated report. + std::unique_ptr<DiagnosticForConsumerMapTy> + generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> &bugReports) override; /// classof - Used by isa<>, cast<>, and dyn_cast<>. static bool classof(const BugReporter* R) { @@ -538,13 +542,29 @@ public: } }; + +class NodeMapClosure : public BugReport::NodeResolver { + InterExplodedGraphMap &M; + +public: + NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} + + const ExplodedNode *getOriginalNode(const ExplodedNode *N) override { + return M.lookup(N); + } +}; + class BugReporterContext { - virtual void anchor(); GRBugReporter &BR; + NodeMapClosure NMC; + + virtual void anchor(); + public: - BugReporterContext(GRBugReporter& br) : BR(br) {} + BugReporterContext(GRBugReporter &br, InterExplodedGraphMap &Backmap) + : BR(br), NMC(Backmap) {} - virtual ~BugReporterContext() {} + virtual ~BugReporterContext() = default; GRBugReporter& getBugReporter() { return BR; } @@ -554,7 +574,7 @@ public: return BR.getStateManager(); } - SValBuilder& getSValBuilder() { + SValBuilder &getSValBuilder() { return getStateManager().getSValBuilder(); } @@ -566,11 +586,15 @@ public: return BR.getSourceManager(); } - virtual BugReport::NodeResolver& getNodeResolver() = 0; + AnalyzerOptions &getAnalyzerOptions() { + return BR.getAnalyzerOptions(); + } + + NodeMapClosure& getNodeResolver() { return NMC; } }; -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H |