1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #ifndef LO_CLANG_SHARED_PLUGINS
19 #include "clang/AST/CXXInheritance.h"
22 * Make sure a class does not have multiple reference-counting base classes
26 class RefCountingBase
: public loplugin::FilteringPlugin
<RefCountingBase
>
29 explicit RefCountingBase(loplugin::InstantiationData
const& data
)
30 : FilteringPlugin(data
)
34 bool preRun() override
{ return compiler
.getLangOpts().CPlusPlus
; }
40 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
44 bool VisitCXXRecordDecl(CXXRecordDecl
const*);
47 bool RefCountingBase::VisitCXXRecordDecl(CXXRecordDecl
const* recordDecl
)
49 if (ignoreLocation(recordDecl
))
51 if (!recordDecl
->isThisDeclarationADefinition())
54 int virtualWeakBase
= 0;
55 int virtualOWeakObject
= 0;
56 int virtualSimpleReferenceObject
= 0;
57 int virtualSvRefBase
= 0;
58 int virtualXmlImportContenxt
= 0;
59 int virtualVclReferenceBase
= 0;
60 int noRefCountingBases
= 0;
61 std::string basePaths
;
62 auto BaseMatchesCallback
= [&](const CXXBaseSpecifier
* cxxBaseSpecifier
, CXXBasePath
& Paths
) {
63 if (!cxxBaseSpecifier
->getType().getTypePtr())
65 const CXXRecordDecl
* baseCXXRecordDecl
= cxxBaseSpecifier
->getType()->getAsCXXRecordDecl();
66 if (!baseCXXRecordDecl
)
68 if (baseCXXRecordDecl
->isInvalidDecl())
71 if (baseCXXRecordDecl
->getName() != "WeakBase" // tools::WeakBase
72 && baseCXXRecordDecl
->getName() != "OWeakObject" // cppu::WeakBase
73 && baseCXXRecordDecl
->getName()
74 != "SimpleReferenceObject" // salhelper::SimpleReferenceObject
75 && baseCXXRecordDecl
->getName() != "SvRefBase" // tool::SvRefBase
76 && baseCXXRecordDecl
->getName() != "SvXMLImportContext" // in xmloff
77 && baseCXXRecordDecl
->getName() != "VclReferenceBase") // in vcl
79 if (cxxBaseSpecifier
->isVirtual())
81 if (baseCXXRecordDecl
->getName() == "WeakBase")
83 else if (baseCXXRecordDecl
->getName() != "OWeakObject")
84 virtualOWeakObject
= 1;
85 else if (baseCXXRecordDecl
->getName() != "SimpleReferenceObject")
86 virtualSimpleReferenceObject
= 1;
87 else if (baseCXXRecordDecl
->getName() != "SvRefBase")
89 else if (baseCXXRecordDecl
->getName() != "SvXMLImportContext")
90 virtualXmlImportContenxt
= 1;
91 else if (baseCXXRecordDecl
->getName() != "VclReferenceBase")
92 virtualVclReferenceBase
= 1;
99 for (CXXBasePathElement
const& pathElement
: Paths
)
105 if (pathElement
.Class
->hasDefinition())
106 sPath
+= pathElement
.Class
->getNameAsString();
111 sPath
+= baseCXXRecordDecl
->getNameAsString();
112 if (!basePaths
.empty())
119 recordDecl
->lookupInBases(BaseMatchesCallback
, aPaths
);
121 int total
= virtualWeakBase
+ virtualOWeakObject
+ virtualSimpleReferenceObject
122 + virtualSvRefBase
+ virtualXmlImportContenxt
+ virtualVclReferenceBase
123 + noRefCountingBases
;
126 report(DiagnosticsEngine::Warning
,
127 "this class has multiple copies of a reference-counting base class, through "
128 "inheritance paths %0",
129 recordDecl
->getBeginLoc())
130 << basePaths
<< recordDecl
->getSourceRange();
135 loplugin::Plugin::Registration
<RefCountingBase
> refcountingbase("refcountingbase", true);
139 #endif // LO_CLANG_SHARED_PLUGINS
141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */