diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-09-12 17:01:43 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-09-14 11:22:49 +0200 |
commit | 3a2176ae256643a3b8c42bca33d333aecad61d19 (patch) | |
tree | 1a67f920f34141ffe485cedf5bcec74b9f878bbf /compilerplugins | |
parent | 58cb4fc7d17ae5b339c5ed6ae139e6ef2433c927 (diff) |
new loplugin refcountingbase
Look for classes that have more than one ref-counting base class.
A situation which is going to cause trouble.
Which reveals that sdr::table::Cell has two different ref-counting bases,
so rather make SdrText extends OWeakObject, which means
that Cell can just have one ref-counting base,
Change-Id: I8d968270f7b449cff2f29da0bd48fa17181c68c5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139807
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/refcountingbase.cxx | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/compilerplugins/clang/refcountingbase.cxx b/compilerplugins/clang/refcountingbase.cxx new file mode 100644 index 000000000000..dddc7335e8d5 --- /dev/null +++ b/compilerplugins/clang/refcountingbase.cxx @@ -0,0 +1,141 @@ +/* -*- 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 + +#include <string> +#include <iostream> +#include <map> +#include <set> + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" + +/** + * Make sure a class does not have multiple reference-counting base classes + */ +namespace +{ +class RefCountingBase : public loplugin::FilteringPlugin<RefCountingBase> +{ +public: + explicit RefCountingBase(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXRecordDecl(CXXRecordDecl const*); +}; + +bool RefCountingBase::VisitCXXRecordDecl(CXXRecordDecl const* recordDecl) +{ + if (ignoreLocation(recordDecl)) + return true; + if (!recordDecl->isThisDeclarationADefinition()) + return true; + + int virtualWeakBase = 0; + int virtualOWeakObject = 0; + int virtualSimpleReferenceObject = 0; + int virtualSvRefBase = 0; + int virtualXmlImportContenxt = 0; + int virtualVclReferenceBase = 0; + int noRefCountingBases = 0; + std::string basePaths; + auto BaseMatchesCallback = [&](const CXXBaseSpecifier* cxxBaseSpecifier, CXXBasePath& Paths) { + if (!cxxBaseSpecifier->getType().getTypePtr()) + return false; + const CXXRecordDecl* baseCXXRecordDecl = cxxBaseSpecifier->getType()->getAsCXXRecordDecl(); + if (!baseCXXRecordDecl) + return false; + if (baseCXXRecordDecl->isInvalidDecl()) + return false; + + if (baseCXXRecordDecl->getName() != "WeakBase" // tools::WeakBase + && baseCXXRecordDecl->getName() != "OWeakObject" // cppu::WeakBase + && baseCXXRecordDecl->getName() + != "SimpleReferenceObject" // salhelper::SimpleReferenceObject + && baseCXXRecordDecl->getName() != "SvRefBase" // tool::SvRefBase + && baseCXXRecordDecl->getName() != "SvXMLImportContext" // in xmloff + && baseCXXRecordDecl->getName() != "VclReferenceBase") // in vcl + return false; + if (cxxBaseSpecifier->isVirtual()) + { + if (baseCXXRecordDecl->getName() == "WeakBase") + virtualWeakBase = 1; + else if (baseCXXRecordDecl->getName() != "OWeakObject") + virtualOWeakObject = 1; + else if (baseCXXRecordDecl->getName() != "SimpleReferenceObject") + virtualSimpleReferenceObject = 1; + else if (baseCXXRecordDecl->getName() != "SvRefBase") + virtualSvRefBase = 1; + else if (baseCXXRecordDecl->getName() != "SvXMLImportContext") + virtualXmlImportContenxt = 1; + else if (baseCXXRecordDecl->getName() != "VclReferenceBase") + virtualVclReferenceBase = 1; + else + assert(false); + } + else + ++noRefCountingBases; + std::string sPath; + for (CXXBasePathElement const& pathElement : Paths) + { + if (!sPath.empty()) + { + sPath += "->"; + } + if (pathElement.Class->hasDefinition()) + sPath += pathElement.Class->getNameAsString(); + else + sPath += "???"; + } + sPath += "->"; + sPath += baseCXXRecordDecl->getNameAsString(); + if (!basePaths.empty()) + basePaths += ", "; + basePaths += sPath; + return false; + }; + + CXXBasePaths aPaths; + recordDecl->lookupInBases(BaseMatchesCallback, aPaths); + + int total = virtualWeakBase + virtualOWeakObject + virtualSimpleReferenceObject + + virtualSvRefBase + virtualXmlImportContenxt + virtualVclReferenceBase + + noRefCountingBases; + if (total > 1) + { + report(DiagnosticsEngine::Warning, + "this class has multiple copies of a reference-counting base class, through " + "inheritance paths %0", + recordDecl->getBeginLoc()) + << basePaths << recordDecl->getSourceRange(); + } + return true; +} + +loplugin::Plugin::Registration<RefCountingBase> refcountingbase("refcountingbase", true); + +} // namespace + +#endif // LO_CLANG_SHARED_PLUGINS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |