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
18 #include "clang/AST/CXXInheritance.h"
21 * Check for data member being shadowed.
23 * @TODO check for any members in superclass hierarchy with duplicate names,
24 * regardless of their visibility,
25 * more specific names will make the code easier to read
30 class DataMemberShadow
:
31 public loplugin::FilteringPlugin
<DataMemberShadow
>
34 explicit DataMemberShadow(loplugin::InstantiationData
const & data
):
35 FilteringPlugin(data
) {}
37 virtual void run() override
{
38 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
41 bool VisitFieldDecl(FieldDecl
const *);
44 bool DataMemberShadow::VisitFieldDecl(FieldDecl
const * fieldDecl
)
46 if (ignoreLocation(fieldDecl
)) {
49 StringRef aFileName
= getFilenameOfLocation(
50 compiler
.getSourceManager().getSpellingLoc(compat::getBeginLoc(fieldDecl
)));
52 // FIXME complex stuff to fix later
54 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/chart2/source/"))
56 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/include/sfx2/recentdocsview.hxx"))
58 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/include/sfx2/templatelocalview.hxx"))
60 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/store/source/stortree.hxx")
61 || loplugin::isSamePathname(aFileName
, SRCDIR
"/store/source/stordata.hxx"))
63 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/sw/source/uibase/inc/dbtree.hxx"))
66 const CXXRecordDecl
* parentCXXRecordDecl
= dyn_cast
<CXXRecordDecl
>(fieldDecl
->getDeclContext());
67 if (!parentCXXRecordDecl
) {
71 fieldDecl
= fieldDecl
->getCanonicalDecl();
73 auto BaseMatchesCallback
= [&](const CXXBaseSpecifier
*cxxBaseSpecifier
, CXXBasePath
& Paths
)
75 if (!cxxBaseSpecifier
->getType().getTypePtr())
77 const CXXRecordDecl
* baseCXXRecordDecl
= cxxBaseSpecifier
->getType()->getAsCXXRecordDecl();
78 if (!baseCXXRecordDecl
)
80 if (baseCXXRecordDecl
->isInvalidDecl())
82 for (const FieldDecl
* baseFieldDecl
: baseCXXRecordDecl
->fields())
84 // TODO look for overlaps even with private fields
86 if (baseFieldDecl
->getAccess() == AS_private
87 || !baseFieldDecl
->getDeclName().isIdentifier()
88 || fieldDecl
->getName() != baseFieldDecl
->getName()) {
92 for (CXXBasePathElement
const & pathElement
: Paths
) {
96 sPath
+= pathElement
.Class
->getNameAsString();
99 sPath
+= baseCXXRecordDecl
->getNameAsString();
100 report(DiagnosticsEngine::Warning
,
101 "data member %0 is shadowing member in superclass, through inheritance path %1",
102 compat::getBeginLoc(fieldDecl
))
103 << fieldDecl
->getName()
105 << fieldDecl
->getSourceRange();
106 report(DiagnosticsEngine::Note
,
107 "superclass member here",
108 compat::getBeginLoc(baseFieldDecl
))
109 << baseFieldDecl
->getSourceRange();
115 parentCXXRecordDecl
->lookupInBases(BaseMatchesCallback
, aPaths
);
119 loplugin::Plugin::Registration
< DataMemberShadow
> datamembershadow("datamembershadow", true);
123 #endif // LO_CLANG_SHARED_PLUGINS
125 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */