clang-tools 23.0.0git
MtUnsafeCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "MtUnsafeCheck.h"
10#include "clang/ASTMatchers/ASTMatchFinder.h"
11
12using namespace clang::ast_matchers;
13
14namespace clang::tidy {
15
16// Initial list was extracted from gcc documentation
17static constexpr StringRef GlibcFunctions[] = {
18 "::argp_error",
19 "::argp_help",
20 "::argp_parse",
21 "::argp_state_help",
22 "::argp_usage",
23 "::asctime",
24 "::clearenv",
25 "::crypt",
26 "::ctime",
27 "::cuserid",
28 "::drand48",
29 "::ecvt",
30 "::encrypt",
31 "::endfsent",
32 "::endgrent",
33 "::endhostent",
34 "::endnetent",
35 "::endnetgrent",
36 "::endprotoent",
37 "::endpwent",
38 "::endservent",
39 "::endutent",
40 "::endutxent",
41 "::erand48",
42 "::error_at_line",
43 "::exit",
44 "::fcloseall",
45 "::fcvt",
46 "::fgetgrent",
47 "::fgetpwent",
48 "::gammal",
49 "::getchar_unlocked",
50 "::getdate",
51 "::getfsent",
52 "::getfsfile",
53 "::getfsspec",
54 "::getgrent",
55 "::getgrent_r",
56 "::getgrgid",
57 "::getgrnam",
58 "::gethostbyaddr",
59 "::gethostbyname",
60 "::gethostbyname2",
61 "::gethostent",
62 "::getlogin",
63 "::getmntent",
64 "::getnetbyaddr",
65 "::getnetbyname",
66 "::getnetent",
67 "::getnetgrent",
68 "::getnetgrent_r",
69 "::getopt",
70 "::getopt_long",
71 "::getopt_long_only",
72 "::getpass",
73 "::getprotobyname",
74 "::getprotobynumber",
75 "::getprotoent",
76 "::getpwent",
77 "::getpwent_r",
78 "::getpwnam",
79 "::getpwuid",
80 "::getservbyname",
81 "::getservbyport",
82 "::getservent",
83 "::getutent",
84 "::getutent_r",
85 "::getutid",
86 "::getutid_r",
87 "::getutline",
88 "::getutline_r",
89 "::getutxent",
90 "::getutxid",
91 "::getutxline",
92 "::getwchar_unlocked",
93 "::glob",
94 "::glob64",
95 "::gmtime",
96 "::hcreate",
97 "::hdestroy",
98 "::hsearch",
99 "::innetgr",
100 "::jrand48",
101 "::l64a",
102 "::lcong48",
103 "::lgammafNx",
104 "::localeconv",
105 "::localtime",
106 "::login",
107 "::login_tty",
108 "::logout",
109 "::logwtmp",
110 "::lrand48",
111 "::mallinfo",
112 "::mallopt",
113 "::mblen",
114 "::mbrlen",
115 "::mbrtowc",
116 "::mbsnrtowcs",
117 "::mbsrtowcs",
118 "::mbtowc",
119 "::mcheck",
120 "::mprobe",
121 "::mrand48",
122 "::mtrace",
123 "::muntrace",
124 "::nrand48",
125 "::__ppc_get_timebase_freq",
126 "::ptsname",
127 "::putchar_unlocked",
128 "::putenv",
129 "::pututline",
130 "::pututxline",
131 "::putwchar_unlocked",
132 "::qecvt",
133 "::qfcvt",
134 "::register_printf_function",
135 "::seed48",
136 "::setenv",
137 "::setfsent",
138 "::setgrent",
139 "::sethostent",
140 "::sethostid",
141 "::setkey",
142 "::setlocale",
143 "::setlogmask",
144 "::setnetent",
145 "::setnetgrent",
146 "::setprotoent",
147 "::setpwent",
148 "::setservent",
149 "::setutent",
150 "::setutxent",
151 "::siginterrupt",
152 "::sigpause",
153 "::sigprocmask",
154 "::sigsuspend",
155 "::sleep",
156 "::srand48",
157 "::strsignal",
158 "::strtok",
159 "::tcflow",
160 "::tcsendbreak",
161 "::tmpnam",
162 "::ttyname",
163 "::unsetenv",
164 "::updwtmp",
165 "::utmpname",
166 "::utmpxname",
167 "::valloc",
168 "::vlimit",
169 "::wcrtomb",
170 "::wcsnrtombs",
171 "::wcsrtombs",
172 "::wctomb",
173 "::wordexp",
174};
175
176static constexpr StringRef PosixFunctions[] = {
177 "::asctime",
178 "::basename",
179 "::catgets",
180 "::crypt",
181 "::ctime",
182 "::dbm_clearerr",
183 "::dbm_close",
184 "::dbm_delete",
185 "::dbm_error",
186 "::dbm_fetch",
187 "::dbm_firstkey",
188 "::dbm_nextkey",
189 "::dbm_open",
190 "::dbm_store",
191 "::dirname",
192 "::dlerror",
193 "::drand48",
194 "::encrypt",
195 "::endgrent",
196 "::endpwent",
197 "::endutxent",
198 "::ftw",
199 "::getc_unlocked",
200 "::getchar_unlocked",
201 "::getdate",
202 "::getenv",
203 "::getgrent",
204 "::getgrgid",
205 "::getgrnam",
206 "::gethostent",
207 "::getlogin",
208 "::getnetbyaddr",
209 "::getnetbyname",
210 "::getnetent",
211 "::getopt",
212 "::getprotobyname",
213 "::getprotobynumber",
214 "::getprotoent",
215 "::getpwent",
216 "::getpwnam",
217 "::getpwuid",
218 "::getservbyname",
219 "::getservbyport",
220 "::getservent",
221 "::getutxent",
222 "::getutxid",
223 "::getutxline",
224 "::gmtime",
225 "::hcreate",
226 "::hdestroy",
227 "::hsearch",
228 "::inet_ntoa",
229 "::l64a",
230 "::lgamma",
231 "::lgammaf",
232 "::lgammal",
233 "::localeconv",
234 "::localtime",
235 "::lrand48",
236 "::mrand48",
237 "::nftw",
238 "::nl_langinfo",
239 "::ptsname",
240 "::putc_unlocked",
241 "::putchar_unlocked",
242 "::putenv",
243 "::pututxline",
244 "::rand",
245 "::readdir",
246 "::setenv",
247 "::setgrent",
248 "::setkey",
249 "::setpwent",
250 "::setutxent",
251 "::strerror",
252 "::strsignal",
253 "::strtok",
254 "::system",
255 "::ttyname",
256 "::unsetenv",
257 "::wcstombs",
258 "::wctomb",
259};
260
261template <> struct OptionEnumMapping<concurrency::MtUnsafeCheck::FunctionSet> {
262 static llvm::ArrayRef<
263 std::pair<concurrency::MtUnsafeCheck::FunctionSet, StringRef>>
265 static constexpr std::pair<concurrency::MtUnsafeCheck::FunctionSet,
266 StringRef>
270 return {Mapping};
271 }
272};
273
274namespace concurrency {
275
276static ast_matchers::internal::Matcher<NamedDecl>
278 switch (Libc) {
280 return hasAnyName(PosixFunctions);
282 return hasAnyName(GlibcFunctions);
284 return anyOf(hasAnyName(PosixFunctions), hasAnyName(GlibcFunctions));
285 }
286 llvm_unreachable("invalid FunctionSet");
287}
288
290 : ClangTidyCheck(Name, Context),
291 FuncSet(Options.get("FunctionSet", MtUnsafeCheck::FunctionSet::Any)) {}
292
294 Options.store(Opts, "FunctionSet", FuncSet);
295}
296
297void MtUnsafeCheck::registerMatchers(MatchFinder *Finder) {
298 Finder->addMatcher(
299 callExpr(callee(functionDecl(hasAnyMtUnsafeNames(FuncSet))))
300 .bind("mt-unsafe"),
301 this);
302}
303
304void MtUnsafeCheck::check(const MatchFinder::MatchResult &Result) {
305 const auto *Call = Result.Nodes.getNodeAs<CallExpr>("mt-unsafe");
306 assert(Call && "Unhandled binding in the Matcher");
307
308 diag(Call->getBeginLoc(), "function is not thread safe");
309}
310
311} // namespace concurrency
312} // namespace clang::tidy
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
MtUnsafeCheck(StringRef Name, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
static ast_matchers::internal::Matcher< NamedDecl > hasAnyMtUnsafeNames(MtUnsafeCheck::FunctionSet Libc)
static constexpr StringRef PosixFunctions[]
static constexpr StringRef GlibcFunctions[]
llvm::StringMap< ClangTidyValue > OptionMap
static llvm::ArrayRef< std::pair< concurrency::MtUnsafeCheck::FunctionSet, StringRef > > getEnumMapping()
This class should be specialized by any enum type that needs to be converted to and from an llvm::Str...