diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
| commit | b60736ec1405bb0a8dd40989f67ef4c93da068ab (patch) | |
| tree | 5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp | |
| parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) | |
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp index 7bb25f397d01..8a85d454856b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp @@ -23,23 +23,40 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "llvm/ADT/StringRef.h" using namespace clang; using namespace ento; namespace { -class SmartPtrChecker : public Checker<check::PreCall> { - BugType NullDereferenceBugType{this, "Null SmartPtr dereference", - "C++ Smart Pointer"}; +static const BugType *NullDereferenceBugTypePtr; + +class SmartPtrChecker : public Checker<check::PreCall> { public: void checkPreCall(const CallEvent &Call, CheckerContext &C) const; + BugType NullDereferenceBugType{this, "Null SmartPtr dereference", + "C++ Smart Pointer"}; private: - void reportBug(CheckerContext &C, const CallEvent &Call) const; + void reportBug(CheckerContext &C, const MemRegion *DerefRegion, + const CallEvent &Call) const; + void explainDereference(llvm::raw_ostream &OS, const MemRegion *DerefRegion, + const CallEvent &Call) const; }; } // end of anonymous namespace +// Define the inter-checker API. +namespace clang { +namespace ento { +namespace smartptr { + +const BugType *getNullDereferenceBugType() { return NullDereferenceBugTypePtr; } + +} // namespace smartptr +} // namespace ento +} // namespace clang + void SmartPtrChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { if (!smartptr::isStdSmartPtrCall(Call)) @@ -55,23 +72,34 @@ void SmartPtrChecker::checkPreCall(const CallEvent &Call, OverloadedOperatorKind OOK = OC->getOverloadedOperator(); if (OOK == OO_Star || OOK == OO_Arrow) { if (smartptr::isNullSmartPtr(State, ThisRegion)) - reportBug(C, Call); + reportBug(C, ThisRegion, Call); } } -void SmartPtrChecker::reportBug(CheckerContext &C, +void SmartPtrChecker::reportBug(CheckerContext &C, const MemRegion *DerefRegion, const CallEvent &Call) const { ExplodedNode *ErrNode = C.generateErrorNode(); if (!ErrNode) return; - - auto R = std::make_unique<PathSensitiveBugReport>( - NullDereferenceBugType, "Dereference of null smart pointer", ErrNode); + llvm::SmallString<128> Str; + llvm::raw_svector_ostream OS(Str); + explainDereference(OS, DerefRegion, Call); + auto R = std::make_unique<PathSensitiveBugReport>(NullDereferenceBugType, + OS.str(), ErrNode); + R->markInteresting(DerefRegion); C.emitReport(std::move(R)); } +void SmartPtrChecker::explainDereference(llvm::raw_ostream &OS, + const MemRegion *DerefRegion, + const CallEvent &Call) const { + OS << "Dereference of null smart pointer "; + DerefRegion->printPretty(OS); +} + void ento::registerSmartPtrChecker(CheckerManager &Mgr) { - Mgr.registerChecker<SmartPtrChecker>(); + SmartPtrChecker *Checker = Mgr.registerChecker<SmartPtrChecker>(); + NullDereferenceBugTypePtr = &Checker->NullDereferenceBugType; } bool ento::shouldRegisterSmartPtrChecker(const CheckerManager &mgr) { |
