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/.
15 #include "clang/AST/CXXInheritance.h"
18 what might be more interesting is a warning about subclasses that add
19 members but do not override virtual operator==() - that is easily
20 forgotten and hard to notice.
25 public RecursiveASTVisitor
<SfxPoolItem
>, public loplugin::Plugin
28 explicit SfxPoolItem(loplugin::InstantiationData
const & data
): Plugin(data
)
31 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
33 bool VisitCXXRecordDecl( const CXXRecordDecl
* );
36 bool BaseCheckNotSfxPoolItemSubclass(const CXXRecordDecl
*BaseDefinition
) {
37 if (BaseDefinition
&& loplugin::TypeCheck(BaseDefinition
).Class("SfxPoolItem").GlobalNamespace()) {
43 bool isDerivedFromSfxPoolItem(const CXXRecordDecl
*decl
) {
46 if (loplugin::TypeCheck(decl
).Class("SfxPoolItem").GlobalNamespace())
48 if (!decl
->hasDefinition()) {
51 if (// not sure what hasAnyDependentBases() does,
52 // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
53 !decl
->hasAnyDependentBases() &&
54 !decl
->forallBases(BaseCheckNotSfxPoolItemSubclass
, true)) {
61 bool BaseCheckNotSwMsgPoolItemSubclass(const CXXRecordDecl
*BaseDefinition
) {
62 if (BaseDefinition
&& loplugin::TypeCheck(BaseDefinition
).Class("SwMsgPoolItem")) {
68 bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl
*decl
) {
71 if (loplugin::TypeCheck(decl
).Class("SwMsgPoolItem").GlobalNamespace())
73 if (!decl
->hasDefinition()) {
76 if (// not sure what hasAnyDependentBases() does,
77 // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
78 !decl
->hasAnyDependentBases() &&
79 !decl
->forallBases(BaseCheckNotSwMsgPoolItemSubclass
, true)) {
85 bool endsWith(const std::string
& a
, const std::string
& b
) {
86 if (b
.size() > a
.size()) return false;
87 return std::equal(a
.begin() + a
.size() - b
.size(), a
.end(), b
.begin());
90 bool SfxPoolItem::VisitCXXRecordDecl(const CXXRecordDecl
* decl
)
92 if (ignoreLocation(decl
)) {
95 if (!decl
->hasDefinition()) {
98 // check if this class is derived from Window
99 if (!isDerivedFromSfxPoolItem(decl
)) {
102 // the SwMsgPoolItem are some sort of hack to transport down-castable objects to SwClient::Modify(), they're not "real" items
103 if (isDerivedFromSwMsgPoolItem(decl
)) {
106 if (decl
->field_begin() == decl
->field_end()) {
109 // the enum types do some weird stuff involving SfxEnumItemInterface
110 auto tc
= loplugin::TypeCheck(decl
);
111 if (tc
.Class("SfxEnumItem").GlobalNamespace() || tc
.Class("SfxAllEnumItem").GlobalNamespace())
114 // the new field is only used for reading and writing to storage
115 if (tc
.Class("SvxCharSetColorItem").GlobalNamespace())
118 for (auto it
= decl
->method_begin(); it
!= decl
->method_end(); ++it
) {
119 if ( endsWith((*it
)->getQualifiedNameAsString(), "::operator==") )
123 DiagnosticsEngine::Warning
,
124 "SfxPoolItem subclass %0 declares new fields, but does not override operator==",
126 << decl
->getQualifiedNameAsString() << decl
->getSourceRange();
131 loplugin::Plugin::Registration
< SfxPoolItem
> X("sfxpoolitem");
135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */