34 using namespace clang;
38 class DeleteWithNonVirtualDtorChecker
39 :
public Checker<check::PreStmt<CXXDeleteExpr>> {
40 mutable std::unique_ptr<BugType> BT;
44 DeleteBugVisitor() : Satisfied(
false) {}
45 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
49 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
50 BugReporterContext &BRC,
51 BugReport &BR)
override;
58 void checkPreStmt(
const CXXDeleteExpr *DE, CheckerContext &C)
const;
62 void DeleteWithNonVirtualDtorChecker::checkPreStmt(
const CXXDeleteExpr *DE,
63 CheckerContext &C)
const {
65 const MemRegion *MR = C.getSVal(DeletedObj).getAsRegion();
69 const auto *BaseClassRegion = MR->getAs<TypedValueRegion>();
70 const auto *DerivedClassRegion = MR->getBaseRegion()->getAs<SymbolicRegion>();
71 if (!BaseClassRegion || !DerivedClassRegion)
74 const auto *BaseClass = BaseClassRegion->getValueType()->getAsCXXRecordDecl();
75 const auto *DerivedClass =
77 if (!BaseClass || !DerivedClass)
80 if (!BaseClass->hasDefinition() || !DerivedClass->hasDefinition())
83 if (BaseClass->getDestructor()->isVirtual())
86 if (!DerivedClass->isDerivedFrom(BaseClass))
90 BT.reset(
new BugType(
this,
91 "Destruction of a polymorphic object with no " 95 ExplodedNode *N = C.generateNonFatalErrorNode();
96 auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
99 R->markInteresting(BaseClassRegion);
100 R->addVisitor(llvm::make_unique<DeleteBugVisitor>());
101 C.emitReport(std::move(R));
104 std::shared_ptr<PathDiagnosticPiece>
105 DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
106 const ExplodedNode *N, BugReporterContext &BRC,
116 const auto *CastE = dyn_cast<
CastExpr>(S);
122 if (
const auto *ImplCastE = dyn_cast<ImplicitCastExpr>(CastE)) {
123 if (ImplCastE->getCastKind() != CK_DerivedToBase)
128 const MemRegion *M = N->getSVal(CastE).getAsRegion();
133 if (!BR.isInteresting(M))
140 llvm::raw_svector_ostream
OS(Buf);
141 OS <<
"Conversion from derived to base happened here";
142 PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
143 N->getLocationContext());
144 return std::make_shared<PathDiagnosticEventPiece>(Pos,
OS.str(),
true,
148 void ento::registerDeleteWithNonVirtualDtorChecker(CheckerManager &mgr) {
149 mgr.registerChecker<DeleteWithNonVirtualDtorChecker>();
Stmt - This represents one statement.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
This represents one expression.
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to...
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
Dataflow Directional Tag Classes.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...