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/.
9 #ifndef LO_CLANG_SHARED_PLUGINS
16 #include "clang/AST/CXXInheritance.h"
19 what might be more interesting is a warning about subclasses that add
20 members but do not override virtual operator==() - that is easily
21 forgotten and hard to notice.
26 public loplugin::FilteringPlugin
<SfxPoolItem
>
29 explicit SfxPoolItem(loplugin::InstantiationData
const & data
): FilteringPlugin(data
)
32 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
34 bool VisitCXXRecordDecl( const CXXRecordDecl
* );
37 bool BaseCheckNotSfxPoolItemSubclass(const CXXRecordDecl
*BaseDefinition
) {
38 if (BaseDefinition
&& loplugin::TypeCheck(BaseDefinition
).Class("SfxPoolItem").GlobalNamespace()) {
44 bool isDerivedFromSfxPoolItem(const CXXRecordDecl
*decl
) {
47 if (loplugin::TypeCheck(decl
).Class("SfxPoolItem").GlobalNamespace())
49 if (!decl
->hasDefinition()) {
52 if (// not sure what hasAnyDependentBases() does,
53 // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
54 !decl
->hasAnyDependentBases() &&
55 !decl
->forallBases(BaseCheckNotSfxPoolItemSubclass
)) {
62 bool BaseCheckNotSwMsgPoolItemSubclass(const CXXRecordDecl
*BaseDefinition
) {
63 if (BaseDefinition
&& loplugin::TypeCheck(BaseDefinition
).Class("SwMsgPoolItem")) {
69 bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl
*decl
) {
72 if (loplugin::TypeCheck(decl
).Class("SwMsgPoolItem").GlobalNamespace())
74 if (!decl
->hasDefinition()) {
77 if (// not sure what hasAnyDependentBases() does,
78 // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
79 !decl
->hasAnyDependentBases() &&
80 !decl
->forallBases(BaseCheckNotSwMsgPoolItemSubclass
)) {
86 bool endsWith(const std::string
& a
, const std::string
& b
) {
87 if (b
.size() > a
.size()) return false;
88 return std::equal(a
.begin() + a
.size() - b
.size(), a
.end(), b
.begin());
91 bool SfxPoolItem::VisitCXXRecordDecl(const CXXRecordDecl
* decl
)
93 if (ignoreLocation(decl
)) {
96 if (!decl
->isThisDeclarationADefinition()) {
99 // check if this class is derived from Window
100 if (!isDerivedFromSfxPoolItem(decl
)) {
103 // the SwMsgPoolItem are some sort of hack to transport down-castable objects to SwClient::Modify(), they're not "real" items
104 if (isDerivedFromSwMsgPoolItem(decl
)) {
107 if (decl
->field_begin() == decl
->field_end()) {
110 // the enum types do some weird stuff involving SfxEnumItemInterface
111 auto tc
= loplugin::TypeCheck(decl
);
112 if (tc
.Class("SfxEnumItem").GlobalNamespace() || tc
.Class("SfxAllEnumItem").GlobalNamespace())
115 for (auto it
= decl
->method_begin(); it
!= decl
->method_end(); ++it
) {
116 if ( endsWith((*it
)->getQualifiedNameAsString(), "::operator==") )
120 DiagnosticsEngine::Warning
,
121 "SfxPoolItem subclass %0 declares new fields, but does not override operator==",
123 << decl
->getQualifiedNameAsString() << decl
->getSourceRange();
128 loplugin::Plugin::Registration
< SfxPoolItem
> sfxpoolitem("sfxpoolitem");
132 #endif // LO_CLANG_SHARED_PLUGINS
134 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */