33 using namespace clang;
37 class DeleteWithNonVirtualDtorChecker
38 :
public Checker<check::PreStmt<CXXDeleteExpr>> {
39 mutable std::unique_ptr<BugType> BT;
43 DeleteBugVisitor() : Satisfied(
false) {}
44 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
48 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
49 BugReporterContext &BRC,
50 BugReport &BR)
override;
57 void checkPreStmt(
const CXXDeleteExpr *DE, CheckerContext &C)
const;
61 void DeleteWithNonVirtualDtorChecker::checkPreStmt(
const CXXDeleteExpr *DE,
62 CheckerContext &C)
const {
64 const MemRegion *MR = C.getSVal(DeletedObj).getAsRegion();
68 const auto *BaseClassRegion = MR->getAs<TypedValueRegion>();
69 const auto *DerivedClassRegion = MR->getBaseRegion()->getAs<SymbolicRegion>();
70 if (!BaseClassRegion || !DerivedClassRegion)
73 const auto *BaseClass = BaseClassRegion->getValueType()->getAsCXXRecordDecl();
74 const auto *DerivedClass =
76 if (!BaseClass || !DerivedClass)
79 if (!BaseClass->hasDefinition() || !DerivedClass->hasDefinition())
82 if (BaseClass->getDestructor()->isVirtual())
85 if (!DerivedClass->isDerivedFrom(BaseClass))
89 BT.reset(
new BugType(
this,
90 "Destruction of a polymorphic object with no " 94 ExplodedNode *N = C.generateNonFatalErrorNode();
95 auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
98 R->markInteresting(BaseClassRegion);
99 R->addVisitor(llvm::make_unique<DeleteBugVisitor>());
100 C.emitReport(std::move(R));
103 std::shared_ptr<PathDiagnosticPiece>
104 DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
105 const ExplodedNode *N, BugReporterContext &BRC,
115 const auto *CastE = dyn_cast<
CastExpr>(S);
121 if (
const auto *ImplCastE = dyn_cast<ImplicitCastExpr>(CastE)) {
122 if (ImplCastE->getCastKind() != CK_DerivedToBase)
127 const MemRegion *M = N->getSVal(CastE).getAsRegion();
132 if (!BR.isInteresting(M))
139 llvm::raw_svector_ostream
OS(Buf);
140 OS <<
"Conversion from derived to base happened here";
141 PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
142 N->getLocationContext());
143 return std::make_shared<PathDiagnosticEventPiece>(Pos,
OS.str(),
true,
147 void ento::registerDeleteWithNonVirtualDtorChecker(CheckerManager &mgr) {
148 mgr.registerChecker<DeleteWithNonVirtualDtorChecker>();
151 bool ento::shouldRegisterDeleteWithNonVirtualDtorChecker(
Stmt - This represents one statement.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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 ...