bump product version to 7.2.5.1
[LibreOffice.git] / compilerplugins / clang / reservedid.cxx
blob0792c96b2da6169ff9ba723c8cbd0d597c7294d4
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 #ifndef LO_CLANG_SHARED_PLUGINS
12 #include <algorithm>
13 #include <cassert>
14 #include <limits>
15 #include <set>
16 #include <string>
18 #include "clang/AST/Attr.h"
20 #include "plugin.hxx"
22 namespace {
24 bool isJniFunction(NamedDecl const * decl) {
25 auto const fdecl = dyn_cast<FunctionDecl>(decl);
26 if (fdecl == nullptr
27 || !(decl->getDeclContext()->getDeclKind() == Decl::LinkageSpec
28 && decl->getDeclContext()->getParent()->isTranslationUnit())
29 || !fdecl->isExternC())
31 return false;
33 auto const id = decl->getIdentifier();
34 return id != nullptr && id->getName().startswith("Java_");
37 class ReservedId:
38 public loplugin::FilteringPlugin<ReservedId>
40 public:
41 explicit ReservedId(loplugin::InstantiationData const & data): FilteringPlugin(data)
44 void run() override;
45 void postRun() override;
47 bool VisitNamedDecl(NamedDecl const * decl);
49 private:
50 enum class Kind {
51 Ok, DoubleUnderscore, UnderscoreUppercase, UnderscoreLowercase };
53 Kind determineKind(llvm::StringRef const & id);
55 bool isInLokIncludeFile(SourceLocation spellingLocation) const;
57 bool isApi(NamedDecl const * decl);
60 void ReservedId::run() {
61 //TODO: Rules for C?
62 if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()))
63 postRun();
66 void ReservedId::postRun() {
67 if( compiler.hasPreprocessor())
69 auto & prep = compiler.getPreprocessor();
70 for (auto const & m: prep.macros(false)) {
71 auto id = m.first->getName();
72 if (determineKind(id) != Kind::Ok
73 && id != "_ATL_APARTMENT_THREADED"
74 // extensions/source/activex/StdAfx2.h
75 && id != "_ATL_STATIC_REGISTRY"
76 // extensions/source/activex/StdAfx2.h
77 && id != "_GLIBCXX_CDTOR_CALLABI"
78 && id != "_HAS_AUTO_PTR_ETC" // unotools/source/i18n/resmgr.cxx
79 && id != "_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR" // unotools/source/i18n/resmgr.cxx
80 && id != "_MAX_PATH" // Windows
81 && id != "_POSIX_SOURCE"
82 && id != "_USE_MATH_DEFINES" // include/sal/config.h, Windows
83 && id != "_WIN32_DCOM" // embedserv/source/embed/esdll.cxx
84 && id != "_WTL_NO_CSTRING"
85 // fpicker/source/win32/filepicker/platform_vista.h (TODO:
86 // needed?)
87 && id != "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"
88 && id != "__Column_FWD_DEFINED__"
89 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
90 // adoctint.h
91 && id != "__Group_FWD_DEFINED__"
92 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
93 // adoctint.h
94 && id != "__Index_FWD_DEFINED__"
95 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
96 // adoctint.h
97 && id != "__Key_FWD_DEFINED__"
98 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
99 // adoctint.h
100 && id != "__ORCUS_STATIC_LIB"
101 && id != "__Table_FWD_DEFINED__"
102 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
103 // adoctint.h
104 && id != "__USE_GNU"
105 && id != "__User_FWD_DEFINED__")
106 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
107 // adoctint.h
109 auto d = prep.getLocalMacroDirectiveHistory(m.first);
110 for (;;) {
111 if (d->getKind() == MacroDirective::MD_Define) {
112 auto loc = d->getLocation();
113 if (loc.isValid() && !ignoreLocation(loc)) {
114 auto file = getFilenameOfLocation(loc);
115 if (!loplugin::isSamePathname(
116 file,
117 SRCDIR
118 "/include/cppuhelper/implbase_ex_post.hxx")
119 && !loplugin::isSamePathname(
120 file,
121 SRCDIR
122 "/include/cppuhelper/implbase_ex_pre.hxx"))
124 report(
125 DiagnosticsEngine::Warning,
126 "reserved macro identifier", loc);
130 d = d->getPrevious();
131 if (d == nullptr) {
132 break;
140 bool ReservedId::VisitNamedDecl(NamedDecl const * decl) {
141 auto spelLoc = compiler.getSourceManager().getSpellingLoc(
142 decl->getLocation());
143 if (ignoreLocation(spelLoc)) {
144 return true;
146 auto filename = getFilenameOfLocation(spelLoc);
147 if (loplugin::hasPathnamePrefix(filename, SRCDIR "/bridges/source/cpp_uno/")
148 && (filename.endswith("abi.hxx") || filename.endswith("share.hxx")))
150 return true;
152 auto const id = decl->getIdentifier();
153 if (id == nullptr) {
154 return true;
156 auto const s = id->getName();
157 switch (determineKind(s)) {
158 case Kind::Ok:
159 break;
160 case Kind::DoubleUnderscore:
161 /*TODO*/if(s=="BIFF__5"||s=="XML__COLON"||s=="XML__EMPTY"||s=="XML__UNKNOWN_")break;
162 if (!(isApi(decl) || isJniFunction(decl))
163 && s != "__CERT_DecodeDERCertificate"
164 // xmlsecurity/source/xmlsec/nss/nssrenam.h
165 && s != "__CERT_NewTempCertificate"
166 // xmlsecurity/source/xmlsec/nss/nssrenam.h
167 && s != "__CTFont"
168 // vcl/source/window/cairo_cairo.cxx -> include/vcl/sysdata.hxx
169 && s != "__CxxDetectRethrow"
170 // bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx
171 && s != "__GLXcontextRec" // vcl/unx/glxtest.cxx
172 && s != "__GLXFBConfigRec" // vcl/unx/glxtest.cxx
173 && s != "__PK11_GetKeyData"
174 // xmlsecurity/source/xmlsec/nss/nssrenam.h
175 && s != "__current_exception" // bridges/inc/except.hxx, Windows
176 && s != "__data_start") // sal/osl/unx/system.cxx
178 report(
179 DiagnosticsEngine::Warning,
180 "identifier %select{beginning with|containing}0 a double"
181 " underscore is reserved",
182 decl->getLocation())
183 << compiler.getLangOpts().CPlusPlus << decl->getSourceRange();
185 break;
186 case Kind::UnderscoreUppercase:
187 if (!isApi(decl)
188 && s != "_ADOColumn"
189 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
190 && s != "_ADOGroup"
191 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
192 && s != "_ADOIndex"
193 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
194 && s != "_ADOKey"
195 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
196 && s != "_ADOTable"
197 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
198 && s != "_ADOUser"
199 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
200 && s != "_ClipboardContent" // vcl/unx/gtk3/gtkinst.cxx
201 && s != "_ClipboardContentClass" // vcl/unx/gtk3/gtkinst.cxx
202 && s != "_FcPattern" // vcl/inc/unx/fc_fontoptions.hxx
203 && s != "_GdkDisplay"
204 // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
205 && s != "_GdkEvent" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
206 && s != "_GdkScreen" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
207 && s != "_GdkWindow"
208 // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
209 && s != "_GstVideoOverlay"
210 // avmedia/source/gstreamer/gstplayer.hxx
211 && s != "_Module" // extensions/source/activex/StdAfx2.h, CComModule
212 && s != "_SurfacePaintable" // vcl/unx/gtk3/gtkinst.cxx
213 && s != "_SurfacePaintableClass" // vcl/unx/gtk3/gtkinst.cxx
214 && s != "_XRegion" // vcl/unx/generic/gdi/x11cairotextrender.cxx
215 && s != "_XTrap") // vcl/unx/generic/gdi/xrender_peer.hxx
217 report(
218 DiagnosticsEngine::Warning,
219 "identifier beginning with an underscore followed by an"
220 " uppercase letter is reserved",
221 decl->getLocation())
222 << decl->getSourceRange();
224 break;
225 case Kind::UnderscoreLowercase:
226 if (decl->getDeclContext()->isTranslationUnit()
227 && !isa<ParmVarDecl>(decl) && !isApi(decl)
228 && s != "_cairo" && s != "_cairo_surface"
229 // tools/source/ref/errinf.cxx -> include/vcl/window.hxx ->
230 // include/vcl/outdev.hxx -> include/vcl/cairo.hxx
231 && s != "_cairo_font_options"
232 // vcl/source/window/accessibility.cxx -> vcl/inc/salinst.hxx
233 && s != "_cairo_user_data_key"
234 // vcl/headless/svpbmp.cxx -> vcl/inc/headless/svpgdi.hxx
235 && s != "_end" // sal/osl/unx/system.cxx
236 && s != "_rtl_Locale"
237 // i18nlangtag/source/isolang/mslangid.cxx ->
238 // include/i18nlangtag/languagetag.hxx
239 && s != "_uno_ExtEnvironment"
240 // cppu/source/threadpool/threadident.cxx ->
241 // threadpool/current.hxx
242 && s != "_xmlTextWriter") // include/svl/poolitem.hxx
244 report(
245 DiagnosticsEngine::Warning,
246 "identifier beginning with an underscore followed by a"
247 " lowercase letter is reserved in the global namespace",
248 decl->getLocation())
249 << decl->getSourceRange();
251 break;
253 return true;
256 ReservedId::Kind ReservedId::determineKind(llvm::StringRef const & id) {
257 if (compiler.getLangOpts().CPlusPlus
258 && id.find("__") != llvm::StringRef::npos)
260 return Kind::DoubleUnderscore;
262 if (id.size() >= 2 && id[0] == '_') {
263 auto c = id[1];
264 if (c == '_') {
265 return Kind::DoubleUnderscore;
267 if (c >= 'A' && c <= 'Z') {
268 return Kind::UnderscoreUppercase;
270 if (c >= 'a' && c <= 'z') {
271 return Kind::UnderscoreLowercase;
274 return Kind::Ok;
277 bool ReservedId::isInLokIncludeFile(SourceLocation spellingLocation) const {
278 return loplugin::hasPathnamePrefix(
279 getFilenameOfLocation(spellingLocation),
280 SRCDIR "/include/LibreOfficeKit/");
283 bool ReservedId::isApi(NamedDecl const * decl) {
284 auto const fdecl = dyn_cast<FunctionDecl>(decl);
285 if (fdecl != nullptr) {
286 decl = fdecl->getCanonicalDecl();
287 } else {
288 auto const tdecl = dyn_cast<TagDecl>(decl);
289 if (tdecl != nullptr) {
290 decl = tdecl->getCanonicalDecl();
293 auto const loc = compiler.getSourceManager().getSpellingLoc(
294 decl->getLocation());
295 if (!(isInUnoIncludeFile(loc) || isInLokIncludeFile(loc))
296 || isa<ParmVarDecl>(decl))
298 return false;
300 auto const ctx = decl->getDeclContext();
301 if (ctx->isTranslationUnit()
302 || (ctx->getDeclKind() == Decl::LinkageSpec
303 && ctx->getParent()->isTranslationUnit()))
305 return true;
307 if (ctx->isNamespace()) {
308 auto const id = dyn_cast<NamespaceDecl>(ctx)->getIdentifier();
309 return !(id == nullptr || id->getName() == "detail");
311 return false;
314 loplugin::Plugin::Registration<ReservedId> reservedid("reservedid");
318 #endif // LO_CLANG_SHARED_PLUGINS
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */