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 "config_clang.h"
19 #include "clang/AST/CXXInheritance.h"
22 * Check for data member being shadowed.
24 * @TODO check for any members in superclass hierarchy with duplicate names,
25 * regardless of their visibility,
26 * more specific names will make the code easier to read
31 class DataMemberShadow
:
32 public loplugin::FilteringPlugin
<DataMemberShadow
>
35 explicit DataMemberShadow(loplugin::InstantiationData
const & data
):
36 FilteringPlugin(data
) {}
38 virtual void run() override
{
39 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
42 bool VisitFieldDecl(FieldDecl
const *);
45 bool DataMemberShadow::VisitFieldDecl(FieldDecl
const * fieldDecl
)
47 if (ignoreLocation(fieldDecl
)) {
50 StringRef aFileName
= getFilenameOfLocation(
51 compiler
.getSourceManager().getSpellingLoc(fieldDecl
->getBeginLoc()));
53 // FIXME complex stuff to fix later
55 if (loplugin::hasPathnamePrefix(aFileName
, SRCDIR
"/chart2/source/"))
57 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/include/sfx2/recentdocsview.hxx"))
59 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/include/sfx2/templatelocalview.hxx"))
61 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/store/source/stortree.hxx")
62 || loplugin::isSamePathname(aFileName
, SRCDIR
"/store/source/stordata.hxx"))
64 if (loplugin::isSamePathname(aFileName
, SRCDIR
"/sw/source/uibase/inc/dbtree.hxx"))
67 const CXXRecordDecl
* parentCXXRecordDecl
= dyn_cast
<CXXRecordDecl
>(fieldDecl
->getDeclContext());
68 if (!parentCXXRecordDecl
) {
72 fieldDecl
= fieldDecl
->getCanonicalDecl();
74 auto BaseMatchesCallback
= [&](const CXXBaseSpecifier
*cxxBaseSpecifier
, CXXBasePath
& Paths
)
76 if (!cxxBaseSpecifier
->getType().getTypePtr())
78 const CXXRecordDecl
* baseCXXRecordDecl
= cxxBaseSpecifier
->getType()->getAsCXXRecordDecl();
79 if (!baseCXXRecordDecl
)
81 if (baseCXXRecordDecl
->isInvalidDecl())
83 for (const FieldDecl
* baseFieldDecl
: baseCXXRecordDecl
->fields())
85 // TODO look for overlaps even with private fields
87 if (baseFieldDecl
->getAccess() == AS_private
88 || !baseFieldDecl
->getDeclName().isIdentifier()
89 || fieldDecl
->getName() != baseFieldDecl
->getName()) {
93 for (CXXBasePathElement
const & pathElement
: Paths
) {
97 sPath
+= pathElement
.Class
->getNameAsString();
100 sPath
+= baseCXXRecordDecl
->getNameAsString();
101 report(DiagnosticsEngine::Warning
,
102 "data member %0 is shadowing member in superclass, through inheritance path %1",
103 fieldDecl
->getBeginLoc())
104 << fieldDecl
->getName()
106 << fieldDecl
->getSourceRange();
107 report(DiagnosticsEngine::Note
,
108 "superclass member here",
109 baseFieldDecl
->getBeginLoc())
110 << baseFieldDecl
->getSourceRange();
116 parentCXXRecordDecl
->lookupInBases(BaseMatchesCallback
, aPaths
);
120 loplugin::Plugin::Registration
< DataMemberShadow
> datamembershadow("datamembershadow", true);
124 #endif // LO_CLANG_SHARED_PLUGINS
126 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */