/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ #ifndef LO_CLANG_SHARED_PLUGINS
// Check for calls to virtual methods from destructors. These are dangerous because intention might be to call // a method on a subclass, while in actual fact, it only calls the method on the current or super class. //
namespace {
class FragileDestructor: public loplugin::FilteringPlugin<FragileDestructor>
{ public: explicit FragileDestructor(loplugin::InstantiationData const & data):
FilteringPlugin(data) {}
bool FragileDestructor::TraverseCXXDestructorDecl(CXXDestructorDecl* cxxDestructorDecl)
{
PreTraverseCXXDestructorDecl(cxxDestructorDecl); auto ret = FilteringPlugin::TraverseCXXDestructorDecl(cxxDestructorDecl);
PostTraverseCXXDestructorDecl(cxxDestructorDecl, ret); return ret;
}
bool FragileDestructor::VisitCXXMemberCallExpr(const CXXMemberCallExpr* callExpr)
{ if (m_vDestructors.empty() || ignoreLocation(callExpr)) returntrue; const CXXMethodDecl* methodDecl = callExpr->getMethodDecl(); if (!methodDecl->isVirtual() || methodDecl->hasAttr<FinalAttr>()) returntrue; const CXXRecordDecl* parentRecordDecl = methodDecl->getParent(); if (parentRecordDecl->hasAttr<FinalAttr>()) returntrue; if (!callExpr->getImplicitObjectArgument()->IgnoreImpCasts()->isImplicitCXXThis()) returntrue;
// if we see an explicit call to its own method, that's OK auto s1 = compiler.getSourceManager().getCharacterData(callExpr->getBeginLoc()); auto s2 = compiler.getSourceManager().getCharacterData(callExpr->getEndLoc());
std::string tok(s1, s2-s1); if (tok.find("::") != std::string::npos) returntrue;
// Very common pattern that we call acquire/dispose in destructors of UNO objects // to make sure they are cleaned up. if (methodDecl->getName() == "acquire" || methodDecl->getName() == "dispose") returntrue;
report(
DiagnosticsEngine::Warning, "calling virtual method from destructor, either make the virtual method final, or make this class final",
callExpr->getBeginLoc())
<< callExpr->getSourceRange();
report(
DiagnosticsEngine::Note, "callee method here",
methodDecl->getBeginLoc())
<< methodDecl->getSourceRange(); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.