Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / sfxpoolitem.cxx
blobd269070e03febdb91a5a2f7f52ef916e1c9cf364
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <string>
11 #include <iostream>
13 #include "plugin.hxx"
14 #include "check.hxx"
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.
22 namespace {
24 class SfxPoolItem:
25 public RecursiveASTVisitor<SfxPoolItem>, public loplugin::Plugin
27 public:
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()) {
38 return false;
40 return true;
43 bool isDerivedFromSfxPoolItem(const CXXRecordDecl *decl) {
44 if (!decl)
45 return false;
46 if (loplugin::TypeCheck(decl).Class("SfxPoolItem").GlobalNamespace())
47 return true;
48 if (!decl->hasDefinition()) {
49 return false;
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)) {
55 return true;
57 return false;
61 bool BaseCheckNotSwMsgPoolItemSubclass(const CXXRecordDecl *BaseDefinition) {
62 if (BaseDefinition && loplugin::TypeCheck(BaseDefinition).Class("SwMsgPoolItem")) {
63 return false;
65 return true;
68 bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl) {
69 if (!decl)
70 return false;
71 if (loplugin::TypeCheck(decl).Class("SwMsgPoolItem").GlobalNamespace())
72 return true;
73 if (!decl->hasDefinition()) {
74 return false;
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)) {
80 return true;
82 return false;
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)) {
93 return true;
95 if (!decl->hasDefinition()) {
96 return true;
98 // check if this class is derived from Window
99 if (!isDerivedFromSfxPoolItem(decl)) {
100 return true;
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)) {
104 return true;
106 if (decl->field_begin() == decl->field_end()) {
107 return true;
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())
112 return true;
114 // the new field is only used for reading and writing to storage
115 if (tc.Class("SvxCharSetColorItem").GlobalNamespace())
116 return true;
118 for (auto it = decl->method_begin(); it != decl->method_end(); ++it) {
119 if ( endsWith((*it)->getQualifiedNameAsString(), "::operator==") )
120 return true;
122 report(
123 DiagnosticsEngine::Warning,
124 "SfxPoolItem subclass %0 declares new fields, but does not override operator==",
125 decl->getLocStart())
126 << decl->getQualifiedNameAsString() << decl->getSourceRange();
127 return true;
131 loplugin::Plugin::Registration< SfxPoolItem > X("sfxpoolitem");
135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */