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 * regardless of their visibility,
23 * more specific names will make the code easier to read
28 class DataMemberShadow
:
29 public RecursiveASTVisitor
<DataMemberShadow
>, public loplugin::Plugin
32 explicit DataMemberShadow(loplugin::InstantiationData
const & data
):
35 virtual void run() override
{
36 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
39 bool VisitFieldDecl(FieldDecl
const *);
42 bool DataMemberShadow::VisitFieldDecl(FieldDecl
const * fieldDecl
)
44 if (ignoreLocation(fieldDecl
)) {
47 StringRef aFileName
= compiler
.getSourceManager().getFilename(
48 compiler
.getSourceManager().getSpellingLoc(fieldDecl
->getLocStart()));
50 // FIXME complex stuff to fix later
52 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/chart2/source/"))
54 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/include/sfx2/recentdocsview.hxx"))
56 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/include/sfx2/templatelocalview.hxx"))
58 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/store/source/stortree.hxx")
59 || loplugin::isSamePathname(aFileName
, SRCDIR
"/store/source/stordata.hxx"))
61 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/sw/source/uibase/inc/dbtree.hxx"))
64 const CXXRecordDecl
* parentCXXRecordDecl
= dyn_cast
<CXXRecordDecl
>(fieldDecl
->getDeclContext());
65 if (!parentCXXRecordDecl
) {
69 fieldDecl
= fieldDecl
->getCanonicalDecl();
71 auto BaseMatchesCallback
= [&](const CXXBaseSpecifier
*cxxBaseSpecifier
, CXXBasePath
& Paths
)
73 if (!cxxBaseSpecifier
->getType().getTypePtr())
75 const CXXRecordDecl
* baseCXXRecordDecl
= cxxBaseSpecifier
->getType()->getAsCXXRecordDecl();
76 if (!baseCXXRecordDecl
)
78 if (baseCXXRecordDecl
->isInvalidDecl())
80 for (const FieldDecl
* baseFieldDecl
: baseCXXRecordDecl
->fields())
82 // TODO look for overlaps even with private fields
84 if (baseFieldDecl
->getAccess() == AS_private
85 || !baseFieldDecl
->getDeclName().isIdentifier()
86 || fieldDecl
->getName() != baseFieldDecl
->getName()) {
90 for (CXXBasePathElement
const & pathElement
: Paths
) {
94 sPath
+= pathElement
.Class
->getNameAsString();
97 sPath
+= baseCXXRecordDecl
->getNameAsString();
98 report(DiagnosticsEngine::Warning
,
99 "data member %0 is shadowing member in superclass, through inheritance path %1",
100 fieldDecl
->getLocStart())
101 << fieldDecl
->getName()
103 << fieldDecl
->getSourceRange();
104 report(DiagnosticsEngine::Note
,
105 "superclass member here",
106 baseFieldDecl
->getLocStart())
107 << baseFieldDecl
->getSourceRange();
113 parentCXXRecordDecl
->lookupInBases(BaseMatchesCallback
, aPaths
);
117 loplugin::Plugin::Registration
< DataMemberShadow
> X("datamembershadow", true);
121 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */