nss: upgrade to release 3.73
[LibreOffice.git] / compilerplugins / clang / staticmethods.cxx
blob86206022496f9753d2e840ebb4eedee78beafeec
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 "clang/AST/Attr.h"
12 #include "check.hxx"
13 #include "plugin.hxx"
16 Look for member functions that can be static
18 namespace {
20 class StaticMethods:
21 public loplugin::FilteringPlugin<StaticMethods>
23 private:
24 bool bVisitedThis;
25 public:
26 explicit StaticMethods(loplugin::InstantiationData const & data): FilteringPlugin(data), bVisitedThis(false) {}
28 void run() override
29 { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
31 bool TraverseCXXMethodDecl(const CXXMethodDecl * decl);
33 bool VisitCXXThisExpr(const CXXThisExpr *) { bVisitedThis = true; return true; }
34 // these two indicate that we hit something that makes our analysis unreliable
35 bool VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *) { bVisitedThis = true; return true; }
36 bool VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *) { bVisitedThis = true; return true; }
37 private:
38 StringRef getFilename(SourceLocation loc);
41 bool BaseCheckNotTestFixtureSubclass(const CXXRecordDecl *BaseDefinition) {
42 if (loplugin::TypeCheck(BaseDefinition).Class("TestFixture").Namespace("CppUnit").GlobalNamespace()) {
43 return false;
45 return true;
48 bool isDerivedFromTestFixture(const CXXRecordDecl *decl) {
49 if (!decl->hasDefinition())
50 return false;
51 if (// not sure what hasAnyDependentBases() does,
52 // but it avoids classes we don't want, e.g. WeakAggComponentImplHelper1
53 !decl->hasAnyDependentBases() &&
54 !decl->forallBases(BaseCheckNotTestFixtureSubclass)) {
55 return true;
57 return false;
60 StringRef StaticMethods::getFilename(SourceLocation loc)
62 SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc);
63 return getFilenameOfLocation(spellingLocation);
66 bool startsWith(const std::string& rStr, const char* pSubStr) {
67 return rStr.compare(0, strlen(pSubStr), pSubStr) == 0;
70 bool StaticMethods::TraverseCXXMethodDecl(const CXXMethodDecl * pCXXMethodDecl) {
71 if (ignoreLocation(pCXXMethodDecl)) {
72 return true;
74 if (!pCXXMethodDecl->isInstance() || pCXXMethodDecl->isVirtual() || !pCXXMethodDecl->doesThisDeclarationHaveABody() || pCXXMethodDecl->isLateTemplateParsed()) {
75 return true;
77 if (pCXXMethodDecl->getOverloadedOperator() != OverloadedOperatorKind::OO_None || pCXXMethodDecl->hasAttr<OverrideAttr>()) {
78 return true;
80 if (isa<CXXConstructorDecl>(pCXXMethodDecl) || isa<CXXDestructorDecl>(pCXXMethodDecl) || isa<CXXConversionDecl>(pCXXMethodDecl)) {
81 return true;
83 if (isInUnoIncludeFile(pCXXMethodDecl)) {
84 return true;
86 if (pCXXMethodDecl->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
87 return true;
89 // the CppUnit stuff uses macros and methods that can't be changed
90 if (isDerivedFromTestFixture(pCXXMethodDecl->getParent())) {
91 return true;
93 // don't mess with the backwards compatibility stuff
94 if (loplugin::isSamePathname(getFilename(compat::getBeginLoc(pCXXMethodDecl)), SRCDIR "/cppuhelper/source/compat.cxx")) {
95 return true;
97 // the DDE has a dummy implementation on Linux and a real one on Windows
98 auto aFilename = getFilename(compat::getBeginLoc(pCXXMethodDecl->getCanonicalDecl()));
99 if (loplugin::isSamePathname(aFilename, SRCDIR "/include/svl/svdde.hxx")) {
100 return true;
102 auto cdc = loplugin::DeclCheck(pCXXMethodDecl->getParent());
103 // special case having something to do with static initialisation
104 // sal/osl/all/utility.cxx
105 if (cdc.Class("OGlobalTimer").Namespace("osl").GlobalNamespace()) {
106 return true;
108 // leave the TopLeft() method alone for consistency with the other "corner" methods
109 if (cdc.Class("BitmapInfoAccess").GlobalNamespace()) {
110 return true;
112 // the unotools and svl config code stuff is doing weird stuff with a reference-counted statically allocated pImpl class
113 if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/unotools/")) {
114 return true;
116 if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/svl/")) {
117 return true;
119 if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/framework/") || loplugin::hasPathnamePrefix(aFilename, SRCDIR "/framework/")) {
120 return true;
122 // there is some odd stuff happening here I don't fully understand, leave it for now
123 if (loplugin::hasPathnamePrefix(aFilename, SRCDIR "/include/canvas/") || loplugin::hasPathnamePrefix(aFilename, SRCDIR "/canvas/")) {
124 return true;
126 // classes that have static data and some kind of weird reference-counting trick in its constructor
127 if (cdc.Class("LinguOptions").GlobalNamespace()
128 || (cdc.Class("EditableExtendedColorConfig").Namespace("svtools")
129 .GlobalNamespace())
130 || (cdc.Class("ExtendedColorConfig").Namespace("svtools")
131 .GlobalNamespace())
132 || cdc.Class("SvtMiscOptions").GlobalNamespace()
133 || cdc.Class("SvtAccessibilityOptions").GlobalNamespace()
134 || cdc.Class("ColorConfig").Namespace("svtools").GlobalNamespace()
135 || cdc.Class("SvtOptionsDrawinglayer").GlobalNamespace()
136 || cdc.Class("SvtMenuOptions").GlobalNamespace()
137 || cdc.Class("SvtToolPanelOptions").GlobalNamespace()
138 || cdc.Class("SvtSlideSorterBarOptions").GlobalNamespace()
139 || (cdc.Class("SharedResources").Namespace("connectivity")
140 .GlobalNamespace())
141 || (cdc.Class("OParseContextClient").Namespace("svxform")
142 .GlobalNamespace())
143 || cdc.Class("OLimitedFormats").Namespace("frm").GlobalNamespace())
145 return true;
147 auto fdc = loplugin::DeclCheck(pCXXMethodDecl);
148 // only empty on Linux, not on windows
149 if ((fdc.Function("GetVisualRepresentationInNativeFormat_Impl")
150 .Class("OleEmbeddedObject").GlobalNamespace())
151 || (fdc.Function("GetRidOfComponent").Class("OleEmbeddedObject")
152 .GlobalNamespace())
153 || (fdc.Function("isProfileLocked").Class("ProfileAccess")
154 .Namespace("mozab").Namespace("connectivity").GlobalNamespace())
155 || cdc.Class("SbxDecimal").GlobalNamespace()
156 || fdc.Function("Call").Class("SbiDllMgr").GlobalNamespace()
157 || fdc.Function("FreeDll").Class("SbiDllMgr").GlobalNamespace()
158 || (fdc.Function("InitializeDde").Class("SfxApplication")
159 .GlobalNamespace())
160 || (fdc.Function("RemoveDdeTopic").Class("SfxApplication")
161 .GlobalNamespace())
162 || (fdc.Function("UpdateSkiaStatus").Class("OfaViewTabPage")
163 .GlobalNamespace())
164 || (fdc.Function("ReleaseData").Class("ScannerManager")
165 .GlobalNamespace()))
167 return true;
169 // debugging stuff
170 if (fdc.Function("dump").Class("InternalData").Namespace("chart")
171 .GlobalNamespace())
173 return true;
175 // used in a function-pointer-table
176 if ((cdc.Class("SbiRuntime").GlobalNamespace()
177 && startsWith(pCXXMethodDecl->getNameAsString(), "Step"))
178 || (cdc.Class("OoxFormulaParserImpl").AnonymousNamespace().Namespace("xls").Namespace("oox")
179 .GlobalNamespace())
180 || cdc.Class("SwTableFormula").GlobalNamespace()
181 || (cdc.Class("BiffFormulaParserImpl").Namespace("xls").Namespace("oox")
182 .GlobalNamespace())
183 || (fdc.Function("Read_F_Shape").Class("SwWW8ImplReader")
184 .GlobalNamespace())
185 || (fdc.Function("Read_Majority").Class("SwWW8ImplReader")
186 .GlobalNamespace())
187 || fdc.Function("Ignore").Class("SwWrtShell").GlobalNamespace())
189 return true;
191 // have no idea why this can't be static, but 'make check' fails with it so...
192 if (fdc.Function("resolveRelationshipsOfTypeFromOfficeDoc").Class("Shape")
193 .Namespace("drawingml").Namespace("oox").GlobalNamespace())
195 return true;
197 // template magic
198 if (fdc.Function("getValue").Class("ColumnBatch").GlobalNamespace()
199 || cdc.Class("TitleImpl").GlobalNamespace()
200 || (fdc.Function("getDefaultPropertyName").Class("DefaultReturnHelper")
201 .Namespace("vba").Namespace("ooo").GlobalNamespace()))
203 return true;
205 // depends on config options
206 if ((fdc.Function("autoInstallFontLangSupport").Class("PrintFontManager")
207 .Namespace("psp").GlobalNamespace())
208 || fdc.Function("AllocateFrame").Class("GtkSalFrame").GlobalNamespace()
209 || (fdc.Function("TriggerPaintEvent").Class("GtkSalFrame")
210 .GlobalNamespace()))
212 return true;
215 bVisitedThis = false;
216 TraverseStmt(pCXXMethodDecl->getBody());
217 if (bVisitedThis) {
218 return true;
221 if (containsPreprocessingConditionalInclusion((pCXXMethodDecl->getSourceRange()))) {
222 return true;
225 report(
226 DiagnosticsEngine::Warning,
227 "this member function can be declared static",
228 pCXXMethodDecl->getCanonicalDecl()->getLocation())
229 << pCXXMethodDecl->getCanonicalDecl()->getSourceRange();
230 FunctionDecl const * def;
231 if (pCXXMethodDecl->isDefined(def)
232 && def != pCXXMethodDecl->getCanonicalDecl())
234 report(DiagnosticsEngine::Note, "defined here:", def->getLocation())
235 << def->getSourceRange();
237 return true;
240 loplugin::Plugin::Registration<StaticMethods> X("staticmethods");
244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */