diff options
4 files changed, 56 insertions, 7 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 2357cbd095..6bca6411c3 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -28,10 +28,28 @@ class ExplodedNode; class MemRegion; class PathDiagnosticPiece; +/// \brief BugReporterVisitors are used to add custom diagnostics along a path. +/// +/// Custom visitors should subclass the BugReporterVisitorImpl class for a +/// default implementation of the clone() method. +/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the +/// default implementation of clone() will NOT do the right thing, and you +/// will have to provide your own implementation.) class BugReporterVisitor : public llvm::FoldingSetNode { public: virtual ~BugReporterVisitor(); + /// \brief Returns a copy of this BugReporter. + /// + /// Custom BugReporterVisitors should not override this method directly. + /// Instead, they should inherit from BugReporterVisitorImpl and provide + /// a protected or public copy constructor. + /// + /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the + /// default implementation of clone() will NOT do the right thing, and you + /// will have to provide your own implementation.) + virtual BugReporterVisitor *clone() const = 0; + /// \brief Return a diagnostic piece which should be associated with the /// given node. /// @@ -61,7 +79,24 @@ public: }; -class FindLastStoreBRVisitor : public BugReporterVisitor { +/// This class provides a convenience implementation for clone() using the +/// Curiously-Recurring Template Pattern. If you are implementing a custom +/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public +/// or protected copy constructor. +/// +/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the +/// default implementation of clone() will NOT do the right thing, and you +/// will have to provide your own implementation.) +template <class DERIVED> +class BugReporterVisitorImpl : public BugReporterVisitor { + virtual BugReporterVisitor *clone() const { + return new DERIVED(*(DERIVED *)this); + } +}; + +class FindLastStoreBRVisitor + : public BugReporterVisitorImpl<FindLastStoreBRVisitor> +{ const MemRegion *R; SVal V; bool satisfied; @@ -94,7 +129,9 @@ public: BugReport &BR); }; -class TrackConstraintBRVisitor : public BugReporterVisitor { +class TrackConstraintBRVisitor + : public BugReporterVisitorImpl<TrackConstraintBRVisitor> +{ DefinedSVal Constraint; const bool Assumption; bool isSatisfied; @@ -111,7 +148,9 @@ public: BugReport &BR); }; -class NilReceiverBRVisitor : public BugReporterVisitor { +class NilReceiverBRVisitor + : public BugReporterVisitorImpl<NilReceiverBRVisitor> +{ public: void Profile(llvm::FoldingSetNodeID &ID) const { static int x = 0; @@ -125,7 +164,7 @@ public: }; /// Visitor that tries to report interesting diagnostics from conditions. -class ConditionBRVisitor : public BugReporterVisitor { +class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { public: void Profile(llvm::FoldingSetNodeID &ID) const { static int x = 0; diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index 3e42ba3f06..cb976e03a5 100644 --- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -131,7 +131,8 @@ private: /// The bug visitor which allows us to print extra diagnostics along the /// BugReport path. For example, showing the allocation site of the leaked /// region. - class SecKeychainBugVisitor : public BugReporterVisitor { + class SecKeychainBugVisitor + : public BugReporterVisitorImpl<SecKeychainBugVisitor> { protected: // The allocated region symbol tracked by the main analysis. SymbolRef Sym; diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 502fb1ed75..8f4502ca31 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -197,7 +197,7 @@ private: /// The bug visitor which allows us to print extra diagnostics along the /// BugReport path. For example, showing the allocation site of the leaked /// region. - class MallocBugVisitor : public BugReporterVisitor { + class MallocBugVisitor : public BugReporterVisitorImpl<MallocBugVisitor> { protected: enum NotificationMode { Normal, diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index bf4b76c640..9255796172 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1713,7 +1713,7 @@ namespace { // Bug Reports. // //===---------===// - class CFRefReportVisitor : public BugReporterVisitor { + class CFRefReportVisitor : public BugReporterVisitorImpl<CFRefReportVisitor> { protected: SymbolRef Sym; const SummaryLogTy &SummaryLog; @@ -1748,6 +1748,15 @@ namespace { PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); + + virtual BugReporterVisitor *clone() const { + // The curiously-recurring template pattern only works for one level of + // subclassing. Rather than make a new template base for + // CFRefReportVisitor, we simply override clone() to do the right thing. + // This could be trouble someday if BugReporterVisitorImpl is ever + // used for something else besides a convenient implementation of clone(). + return new CFRefLeakReportVisitor(*this); + } }; class CFRefReport : public BugReport { |