avoid windres preprocessor quoting-messups with current cygwin
[LibreOffice.git] / compilerplugins / clang / datamembershadow.cxx
blob6e71ce57a4e7191d20ca1c1889a08df0271aa3b0
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>
12 #include <map>
13 #include <set>
15 #include "plugin.hxx"
16 #include "clang/AST/CXXInheritance.h"
18 /**
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
25 namespace
28 class DataMemberShadow:
29 public RecursiveASTVisitor<DataMemberShadow>, public loplugin::Plugin
31 public:
32 explicit DataMemberShadow(loplugin::InstantiationData const & data):
33 Plugin(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)) {
45 return true;
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/"))
53 return true;
54 if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/recentdocsview.hxx"))
55 return true;
56 if (loplugin::isSamePathname(aFileName, SRCDIR "/include/sfx2/templatelocalview.hxx"))
57 return true;
58 if (loplugin::isSamePathname(aFileName, SRCDIR "/store/source/stortree.hxx")
59 || loplugin::isSamePathname(aFileName, SRCDIR "/store/source/stordata.hxx"))
60 return true;
61 if (loplugin::isSamePathname(aFileName, SRCDIR "/sw/source/uibase/inc/dbtree.hxx"))
62 return true;
64 const CXXRecordDecl* parentCXXRecordDecl = dyn_cast<CXXRecordDecl>(fieldDecl->getDeclContext());
65 if (!parentCXXRecordDecl) {
66 return true;
69 fieldDecl = fieldDecl->getCanonicalDecl();
71 auto BaseMatchesCallback = [&](const CXXBaseSpecifier *cxxBaseSpecifier, CXXBasePath& Paths)
73 if (!cxxBaseSpecifier->getType().getTypePtr())
74 return false;
75 const CXXRecordDecl* baseCXXRecordDecl = cxxBaseSpecifier->getType()->getAsCXXRecordDecl();
76 if (!baseCXXRecordDecl)
77 return false;
78 if (baseCXXRecordDecl->isInvalidDecl())
79 return false;
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()) {
87 continue;
89 std::string sPath;
90 for (CXXBasePathElement const & pathElement : Paths) {
91 if (!sPath.empty()) {
92 sPath += "->";
94 sPath += pathElement.Class->getNameAsString();
96 sPath += "->";
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()
102 << sPath
103 << fieldDecl->getSourceRange();
104 report(DiagnosticsEngine::Note,
105 "superclass member here",
106 baseFieldDecl->getLocStart())
107 << baseFieldDecl->getSourceRange();
109 return false;
112 CXXBasePaths aPaths;
113 parentCXXRecordDecl->lookupInBases(BaseMatchesCallback, aPaths);
114 return true;
117 loplugin::Plugin::Registration< DataMemberShadow > X("datamembershadow", true);
121 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */