Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / compilerplugins / clang / reservedid.cxx
blobf0840ace62ed9b53a6976a839cfa9dce77421013
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 "config_clang.h"
22 #include "plugin.hxx"
24 namespace {
26 bool isJniFunction(NamedDecl const * decl) {
27 auto const fdecl = dyn_cast<FunctionDecl>(decl);
28 if (fdecl == nullptr
29 || !(decl->getDeclContext()->getDeclKind() == Decl::LinkageSpec
30 && decl->getDeclContext()->getParent()->isTranslationUnit())
31 || !fdecl->isExternC())
33 return false;
35 auto const id = decl->getIdentifier();
36 return id != nullptr && id->getName().startswith("Java_");
39 class ReservedId:
40 public loplugin::FilteringPlugin<ReservedId>
42 public:
43 explicit ReservedId(loplugin::InstantiationData const & data): FilteringPlugin(data)
46 void run() override;
47 void postRun() override;
49 bool VisitNamedDecl(NamedDecl const * decl);
51 private:
52 enum class Kind {
53 Ok, DoubleUnderscore, UnderscoreUppercase, UnderscoreLowercase };
55 Kind determineKind(llvm::StringRef const & id);
57 bool isInLokIncludeFile(SourceLocation spellingLocation) const;
59 bool isApi(NamedDecl const * decl);
62 void ReservedId::run() {
63 //TODO: Rules for C?
64 if (TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()))
65 postRun();
68 void ReservedId::postRun() {
69 if( compiler.hasPreprocessor())
71 auto & prep = compiler.getPreprocessor();
72 for (auto const & m: prep.macros(false)) {
73 auto id = m.first->getName();
74 if (determineKind(id) != Kind::Ok
75 && id != "_ATL_APARTMENT_THREADED"
76 // extensions/source/activex/StdAfx2.h
77 && id != "_ATL_STATIC_REGISTRY"
78 // extensions/source/activex/StdAfx2.h
79 && id != "_CRT_RAND_S" // sal/osl/w32/random.cxx
80 && id != "_GLIBCXX_CDTOR_CALLABI"
81 && id != "_HAS_AUTO_PTR_ETC" // unotools/source/i18n/resmgr.cxx
82 && id != "_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR" // unotools/source/i18n/resmgr.cxx
83 && id != "_MAX_PATH" // Windows
84 && id != "_POSIX_SOURCE"
85 && id != "_USE_MATH_DEFINES" // include/sal/config.h, Windows
86 && id != "_WIN32_DCOM" // embedserv/source/embed/esdll.cxx
87 && id != "_WTL_NO_CSTRING"
88 // fpicker/source/win32/filepicker/platform_vista.h (TODO:
89 // needed?)
90 && id != "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"
91 && id != "__Column_FWD_DEFINED__"
92 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
93 // adoctint.h
94 && id != "__Group_FWD_DEFINED__"
95 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
96 // adoctint.h
97 && id != "__Index_FWD_DEFINED__"
98 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
99 // adoctint.h
100 && id != "__Key_FWD_DEFINED__"
101 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
102 // adoctint.h
103 && id != "__ORCUS_STATIC_LIB"
104 && id != "__Table_FWD_DEFINED__"
105 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
106 // adoctint.h
107 && id != "__USE_GNU"
108 && id != "__User_FWD_DEFINED__")
109 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK
110 // adoctint.h
112 auto d = prep.getLocalMacroDirectiveHistory(m.first);
113 for (;;) {
114 if (d->getKind() == MacroDirective::MD_Define) {
115 auto loc = d->getLocation();
116 if (loc.isValid() && !ignoreLocation(loc) && !suppressWarningAt(loc)) {
117 auto file = getFilenameOfLocation(loc);
118 if (!loplugin::isSameUnoIncludePathname(
119 file,
120 "cppuhelper/implbase_ex_post.hxx")
121 && !loplugin::isSameUnoIncludePathname(
122 file,
123 "cppuhelper/implbase_ex_pre.hxx"))
125 report(
126 DiagnosticsEngine::Warning,
127 "reserved macro identifier", loc);
131 d = d->getPrevious();
132 if (d == nullptr) {
133 break;
141 bool ReservedId::VisitNamedDecl(NamedDecl const * decl) {
142 auto spelLoc = compiler.getSourceManager().getSpellingLoc(
143 decl->getLocation());
144 if (ignoreLocation(spelLoc)) {
145 return true;
147 auto filename = getFilenameOfLocation(spelLoc);
148 if (loplugin::hasPathnamePrefix(filename, SRCDIR "/bridges/source/cpp_uno/")
149 && (filename.endswith("abi.hxx") || filename.endswith("share.hxx")))
151 return true;
153 auto const id = decl->getIdentifier();
154 if (id == nullptr) {
155 return true;
157 auto const s = id->getName();
158 switch (determineKind(s)) {
159 case Kind::Ok:
160 break;
161 case Kind::DoubleUnderscore:
162 /*TODO*/if(s=="BIFF__5"||s=="XML__COLON"||s=="XML__EMPTY"||s=="XML__UNKNOWN_")break;
163 if (!(isApi(decl) || isJniFunction(decl))
164 && s != "__CERT_DecodeDERCertificate"
165 // xmlsecurity/source/xmlsec/nss/nssrenam.h
166 && s != "__CERT_NewTempCertificate"
167 // xmlsecurity/source/xmlsec/nss/nssrenam.h
168 && s != "__CTFont"
169 // vcl/source/window/cairo_cairo.cxx -> include/vcl/sysdata.hxx
170 && s != "__CxxDetectRethrow"
171 // bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx
172 && s != "__ImageBase"
173 // bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx, MS linker magic
174 && s != "__PK11_GetKeyData"
175 // xmlsecurity/source/xmlsec/nss/nssrenam.h
176 && s != "__current_exception" // bridges/inc/except.hxx, Windows
177 && s != "__data_start") // sal/osl/unx/system.cxx
179 report(
180 DiagnosticsEngine::Warning,
181 "identifier %select{beginning with|containing}0 a double"
182 " underscore is reserved",
183 decl->getLocation())
184 << compiler.getLangOpts().CPlusPlus << decl->getSourceRange();
186 break;
187 case Kind::UnderscoreUppercase:
188 if (!isApi(decl)
189 && s != "_ADOColumn"
190 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
191 && s != "_ADOGroup"
192 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
193 && s != "_ADOIndex"
194 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
195 && s != "_ADOKey"
196 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
197 && s != "_ADOTable"
198 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
199 && s != "_ADOUser"
200 // connectivity/source/inc/ado/Awrapadox.hxx, MS SDK adoctint.h
201 && s != "_CustomCellRenderer" // vcl/unx/gtk3/customcellrenderer.hxx
202 && s != "_CustomCellRendererClass" // vcl/unx/gtk3/customcellrenderer.cxx
203 && s != "_FcPattern" // vcl/inc/unx/fc_fontoptions.hxx
204 && s != "_GdkDisplay"
205 // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
206 && s != "_GdkEvent" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
207 && s != "_GdkScreen" // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
208 && s != "_GdkWindow"
209 // vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
210 && s != "_GstVideoOverlay"
211 // avmedia/source/gstreamer/gstplayer.hxx
212 && s != "_GtkMediaStream"
213 // avmedia/source/gtk/gtkplayer.hxx
214 && s != "_GtkWidget"
215 // avmedia/source/gtk/gtkplayer.hxx
216 && s != "_Module" // extensions/source/activex/StdAfx2.h, CComModule
217 && s != "_NotifyingLayout" // vcl/unx/gtk4/notifyinglayout.cxx
218 && s != "_SurfacePaintable" // vcl/unx/gtk3/gtkinst.cxx
219 && s != "_SurfacePaintableClass" // vcl/unx/gtk3/gtkinst.cxx
220 && s != "_SurfaceCellRenderer" // vcl/unx/gtk4/surfacecellrenderer.cxx
221 && s != "_SurfaceCellRendererClass" // vcl/unx/gtk4/surfacecellrenderer.cxx
222 && s != "_TransferableContent" // vcl/unx/gtk4/transferableprovider.cxx
223 && s != "_TransferableContentClass") // vcl/unx/gtk4/transferableprovider.cxx
225 report(
226 DiagnosticsEngine::Warning,
227 "identifier beginning with an underscore followed by an"
228 " uppercase letter is reserved",
229 decl->getLocation())
230 << decl->getSourceRange();
232 break;
233 case Kind::UnderscoreLowercase:
234 if (decl->getDeclContext()->isTranslationUnit()
235 && !isa<ParmVarDecl>(decl) && !isApi(decl)
236 && s != "_cairo" && s != "_cairo_surface"
237 // tools/source/ref/errinf.cxx -> include/vcl/window.hxx ->
238 // include/vcl/outdev.hxx -> include/vcl/cairo.hxx
239 && s != "_cairo_font_options"
240 // vcl/source/window/accessibility.cxx -> vcl/inc/salinst.hxx
241 && s != "_cairo_user_data_key"
242 // vcl/headless/svpbmp.cxx -> vcl/inc/headless/svpgdi.hxx
243 && s != "_end" // sal/osl/unx/system.cxx
244 && s != "_rtl_Locale"
245 // i18nlangtag/source/isolang/mslangid.cxx ->
246 // include/i18nlangtag/languagetag.hxx
247 && s != "_uno_ExtEnvironment"
248 // cppu/source/threadpool/threadident.cxx ->
249 // threadpool/current.hxx
250 && s != "_xmlTextWriter") // include/svl/poolitem.hxx
252 report(
253 DiagnosticsEngine::Warning,
254 "identifier beginning with an underscore followed by a"
255 " lowercase letter is reserved in the global namespace",
256 decl->getLocation())
257 << decl->getSourceRange();
259 break;
261 return true;
264 ReservedId::Kind ReservedId::determineKind(llvm::StringRef const & id) {
265 if (compiler.getLangOpts().CPlusPlus
266 && id.find("__") != llvm::StringRef::npos)
268 return Kind::DoubleUnderscore;
270 if (id.size() >= 2 && id[0] == '_') {
271 auto c = id[1];
272 if (c == '_') {
273 return Kind::DoubleUnderscore;
275 if (c >= 'A' && c <= 'Z') {
276 return Kind::UnderscoreUppercase;
278 if (c >= 'a' && c <= 'z') {
279 return Kind::UnderscoreLowercase;
282 return Kind::Ok;
285 bool ReservedId::isInLokIncludeFile(SourceLocation spellingLocation) const {
286 return loplugin::hasPathnamePrefix(
287 getFilenameOfLocation(spellingLocation),
288 SRCDIR "/include/LibreOfficeKit/");
291 bool ReservedId::isApi(NamedDecl const * decl) {
292 auto const fdecl = dyn_cast<FunctionDecl>(decl);
293 if (fdecl != nullptr) {
294 decl = fdecl->getCanonicalDecl();
295 } else {
296 auto const tdecl = dyn_cast<TagDecl>(decl);
297 if (tdecl != nullptr) {
298 decl = tdecl->getCanonicalDecl();
301 auto const loc = compiler.getSourceManager().getSpellingLoc(
302 decl->getLocation());
303 if (!(isInUnoIncludeFile(loc) || isInLokIncludeFile(loc))
304 || isa<ParmVarDecl>(decl))
306 return false;
308 auto const ctx = decl->getDeclContext();
309 if (ctx->isTranslationUnit()
310 || (ctx->getDeclKind() == Decl::LinkageSpec
311 && ctx->getParent()->isTranslationUnit()))
313 return true;
315 if (ctx->isNamespace()) {
316 auto const id = dyn_cast<NamespaceDecl>(ctx)->getIdentifier();
317 return !(id == nullptr || id->getName() == "detail");
319 return false;
322 loplugin::Plugin::Registration<ReservedId> reservedid("reservedid");
326 #endif // LO_CLANG_SHARED_PLUGINS
328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */