/* -*- 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/. */ #include "plugin.hxx" namespace { class BadStatics : public clang::RecursiveASTVisitor , public loplugin::Plugin { public: explicit BadStatics(InstantiationData const& rData) : Plugin(rData) {} void run() override { if (compiler.getLangOpts().CPlusPlus) { // no non-trivial dtors in C TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } } /*static*/ std::pair isBadStaticType( QualType const& rType, FieldDecl const*const pCurrentFieldDecl) { QualType const pCanonical(rType.getUnqualifiedType().getCanonicalType()); RecordType const*const pRecordType(pCanonical->getAs()); if (!pRecordType) { return std::make_pair(false, nullptr); } auto const type(pCanonical.getAsString()); if ( type == "class Image" || type == "class Bitmap" || type == "class BitmapEx" ) { return std::make_pair(true, pCurrentFieldDecl); } RecordDecl const*const pDefinition(pRecordType->getDecl()->getDefinition()); assert(pDefinition); CXXRecordDecl const*const pDecl(dyn_cast(pDefinition)); assert(pDecl); for (auto it = pDecl->field_begin(); it != pDecl->field_end(); ++it) { auto const ret(isBadStaticType((*it)->getType(), *it)); if (ret.first) { return ret; } } for (auto it = pDecl->bases_begin(); it != pDecl->bases_end(); ++it) { auto const ret(isBadStaticType((*it).getType(), pCurrentFieldDecl)); if (ret.first) { return ret; } } for (auto it = pDecl->vbases_begin(); it != pDecl->vbases_end(); ++it) { auto const ret(isBadStaticType((*it).getType(), pCurrentFieldDecl)); if (ret.first) { return ret; } } return std::make_pair(false, nullptr); } bool VisitVarDecl(VarDecl const*const pVarDecl) { if (ignoreLocation(pVarDecl)) { return true; } if (pVarDecl->hasGlobalStorage() && pVarDecl->isThisDeclarationADefinition()) { auto const ret(isBadStaticType(pVarDecl->getType(), nullptr)); if (ret.first) { report(DiagnosticsEngine::Warning, "bad static variable causes crash on shutdown", pVarDecl->getLocation()) << pVarDecl->getSourceRange(); if (ret.second != nullptr) { report(DiagnosticsEngine::Remark, "... due to this member", ret.second->getLocation()) << ret.second->getSourceRange(); } } } return true; } }; loplugin::Plugin::Registration X("badstatics"); } // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */