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/.
16 #include "clang/AST/CXXInheritance.h"
19 * Check for data member being shadowed.
21 * @TODO check for any members in superclass hierarchy with duplicate names,
22 * more specific names will make the code easier to read
27 class DataMemberShadow
:
28 public RecursiveASTVisitor
<DataMemberShadow
>, public loplugin::Plugin
31 explicit DataMemberShadow(InstantiationData
const & data
): Plugin(data
) {}
33 virtual void run() override
{
34 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
37 bool VisitFieldDecl(FieldDecl
const *);
40 bool DataMemberShadow::VisitFieldDecl(FieldDecl
const * fieldDecl
)
42 if (ignoreLocation(fieldDecl
)) {
45 StringRef aFileName
= compiler
.getSourceManager().getFilename(
46 compiler
.getSourceManager().getSpellingLoc(fieldDecl
->getLocStart()));
48 // FIXME complex stuff to fix later
50 if (aFileName
== SRCDIR
"/connectivity/source/inc/calc/CTable.hxx")
52 if (aFileName
.startswith(SRCDIR
"/chart2/source/"))
54 if (aFileName
== SRCDIR
"/cppcanvas/source/mtfrenderer/emfplus.cxx")
56 if (aFileName
== SRCDIR
"/cui/source/customize/eventdlg.hxx")
58 if (aFileName
== SRCDIR
"/include/sfx2/recentdocsview.hxx")
60 if (aFileName
== SRCDIR
"/include/sfx2/templatelocalview.hxx")
62 if (aFileName
== SRCDIR
"/filter/source/graphicfilter/idxf/dxfentrd.hxx")
64 if (aFileName
== SRCDIR
"/framework/source/uielement/popuptoolbarcontroller.cxx")
66 if (aFileName
== SRCDIR
"/lotuswordpro/source/filter/xfilter/xfcellstyle.hxx")
68 if (aFileName
== SRCDIR
"/lotuswordpro/source/filter/xfilter/xfdrawobj.hxx")
70 if (aFileName
== SRCDIR
"/sc/source/ui/vba/vbastyles.hxx")
72 if (aFileName
== SRCDIR
"/sd/inc/Outliner.hxx")
74 if (aFileName
== SRCDIR
"/sd/source/ui/annotations/annotationtag.cxx")
76 if (aFileName
== SRCDIR
"/sd/source/ui/inc/FrameView.hxx"
77 || aFileName
== SRCDIR
"/sd/source/filter/ppt/../../ui/inc/FrameView.hxx")
79 if (aFileName
== SRCDIR
"/sd/source/ui/inc/unopage.hxx")
81 if (aFileName
== SRCDIR
"/sd/source/ui/view/viewoverlaymanager.cxx")
83 if (aFileName
== SRCDIR
"/sdext/source/presenter/PresenterSpritePane.hxx")
85 if (aFileName
== SRCDIR
"/store/source/stortree.hxx"
86 || aFileName
== SRCDIR
"/store/source/stordata.hxx")
88 if (aFileName
== SRCDIR
"/svx/source/table/cell.hxx"
89 || aFileName
== SRCDIR
"/svx/source/unodraw/../table/cell.hxx"
90 || aFileName
== SRCDIR
"/svx/source/accessibility/../table/cell.hxx")
92 if (aFileName
== SRCDIR
"/sw/source/uibase/inc/dbtree.hxx")
94 if (aFileName
== SRCDIR
"/vcl/unx/generic/print/genpspgraphics.cxx")
96 if (aFileName
== SRCDIR
"/xmloff/source/draw/ximplink.hxx")
99 const CXXRecordDecl
* parentCXXRecordDecl
= dyn_cast
<CXXRecordDecl
>(fieldDecl
->getDeclContext());
100 if (!parentCXXRecordDecl
) {
104 fieldDecl
= fieldDecl
->getCanonicalDecl();
106 #if CLANG_VERSION >= 30800
108 auto BaseMatchesCallback
= [&](const CXXBaseSpecifier
*cxxBaseSpecifier
, CXXBasePath
& Paths
)
110 if (!cxxBaseSpecifier
->getType().getTypePtr())
112 const CXXRecordDecl
* baseCXXRecordDecl
= cxxBaseSpecifier
->getType()->getAsCXXRecordDecl();
113 if (!baseCXXRecordDecl
)
115 if (baseCXXRecordDecl
->isInvalidDecl())
117 for (const FieldDecl
* baseFieldDecl
: baseCXXRecordDecl
->fields())
119 if (baseFieldDecl
->getAccess() == AS_private
120 || !baseFieldDecl
->getDeclName().isIdentifier()
121 || fieldDecl
->getName() != baseFieldDecl
->getName()) {
125 for (CXXBasePathElement
const & pathElement
: Paths
) {
126 if (!sPath
.empty()) {
129 sPath
+= pathElement
.Class
->getNameAsString();
132 sPath
+= baseCXXRecordDecl
->getNameAsString();
133 report(DiagnosticsEngine::Warning
,
134 "data member %0 is shadowing member in superclass, through inheritance path %1",
135 fieldDecl
->getLocStart())
136 << fieldDecl
->getName()
138 << fieldDecl
->getSourceRange();
139 report(DiagnosticsEngine::Note
,
140 "superclass member here",
141 baseFieldDecl
->getLocStart())
142 << baseFieldDecl
->getSourceRange();
148 parentCXXRecordDecl
->lookupInBases(BaseMatchesCallback
, aPaths
);
153 loplugin::Plugin::Registration
< DataMemberShadow
> X("datamembershadow", true);
157 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */