aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp48
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) {