123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- //===--- MtUnsafeCheck.cpp - clang-tidy -----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "MtUnsafeCheck.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/ASTMatchers/ASTMatchFinder.h"
- using namespace clang::ast_matchers;
- // Initial list was extracted from gcc documentation
- static const clang::StringRef GlibcFunctions[] = {
- "::argp_error",
- "::argp_help",
- "::argp_parse",
- "::argp_state_help",
- "::argp_usage",
- "::asctime",
- "::clearenv",
- "::crypt",
- "::ctime",
- "::cuserid",
- "::drand48",
- "::ecvt",
- "::encrypt",
- "::endfsent",
- "::endgrent",
- "::endhostent",
- "::endnetent",
- "::endnetgrent",
- "::endprotoent",
- "::endpwent",
- "::endservent",
- "::endutent",
- "::endutxent",
- "::erand48",
- "::error_at_line",
- "::exit",
- "::fcloseall",
- "::fcvt",
- "::fgetgrent",
- "::fgetpwent",
- "::gammal",
- "::getchar_unlocked",
- "::getdate",
- "::getfsent",
- "::getfsfile",
- "::getfsspec",
- "::getgrent",
- "::getgrent_r",
- "::getgrgid",
- "::getgrnam",
- "::gethostbyaddr",
- "::gethostbyname",
- "::gethostbyname2",
- "::gethostent",
- "::getlogin",
- "::getmntent",
- "::getnetbyaddr",
- "::getnetbyname",
- "::getnetent",
- "::getnetgrent",
- "::getnetgrent_r",
- "::getopt",
- "::getopt_long",
- "::getopt_long_only",
- "::getpass",
- "::getprotobyname",
- "::getprotobynumber",
- "::getprotoent",
- "::getpwent",
- "::getpwent_r",
- "::getpwnam",
- "::getpwuid",
- "::getservbyname",
- "::getservbyport",
- "::getservent",
- "::getutent",
- "::getutent_r",
- "::getutid",
- "::getutid_r",
- "::getutline",
- "::getutline_r",
- "::getutxent",
- "::getutxid",
- "::getutxline",
- "::getwchar_unlocked",
- "::glob",
- "::glob64",
- "::gmtime",
- "::hcreate",
- "::hdestroy",
- "::hsearch",
- "::innetgr",
- "::jrand48",
- "::l64a",
- "::lcong48",
- "::lgammafNx",
- "::localeconv",
- "::localtime",
- "::login",
- "::login_tty",
- "::logout",
- "::logwtmp",
- "::lrand48",
- "::mallinfo",
- "::mallopt",
- "::mblen",
- "::mbrlen",
- "::mbrtowc",
- "::mbsnrtowcs",
- "::mbsrtowcs",
- "::mbtowc",
- "::mcheck",
- "::mprobe",
- "::mrand48",
- "::mtrace",
- "::muntrace",
- "::nrand48",
- "::__ppc_get_timebase_freq",
- "::ptsname",
- "::putchar_unlocked",
- "::putenv",
- "::pututline",
- "::pututxline",
- "::putwchar_unlocked",
- "::qecvt",
- "::qfcvt",
- "::register_printf_function",
- "::seed48",
- "::setenv",
- "::setfsent",
- "::setgrent",
- "::sethostent",
- "::sethostid",
- "::setkey",
- "::setlocale",
- "::setlogmask",
- "::setnetent",
- "::setnetgrent",
- "::setprotoent",
- "::setpwent",
- "::setservent",
- "::setutent",
- "::setutxent",
- "::siginterrupt",
- "::sigpause",
- "::sigprocmask",
- "::sigsuspend",
- "::sleep",
- "::srand48",
- "::strerror",
- "::strsignal",
- "::strtok",
- "::tcflow",
- "::tcsendbreak",
- "::tmpnam",
- "::ttyname",
- "::unsetenv",
- "::updwtmp",
- "::utmpname",
- "::utmpxname",
- "::valloc",
- "::vlimit",
- "::wcrtomb",
- "::wcsnrtombs",
- "::wcsrtombs",
- "::wctomb",
- "::wordexp",
- };
- static const clang::StringRef PosixFunctions[] = {
- "::asctime",
- "::basename",
- "::catgets",
- "::crypt",
- "::ctime",
- "::dbm_clearerr",
- "::dbm_close",
- "::dbm_delete",
- "::dbm_error",
- "::dbm_fetch",
- "::dbm_firstkey",
- "::dbm_nextkey",
- "::dbm_open",
- "::dbm_store",
- "::dirname",
- "::dlerror",
- "::drand48",
- "::encrypt",
- "::endgrent",
- "::endpwent",
- "::endutxent",
- "::ftw",
- "::getc_unlocked",
- "::getchar_unlocked",
- "::getdate",
- "::getenv",
- "::getgrent",
- "::getgrgid",
- "::getgrnam",
- "::gethostent",
- "::getlogin",
- "::getnetbyaddr",
- "::getnetbyname",
- "::getnetent",
- "::getopt",
- "::getprotobyname",
- "::getprotobynumber",
- "::getprotoent",
- "::getpwent",
- "::getpwnam",
- "::getpwuid",
- "::getservbyname",
- "::getservbyport",
- "::getservent",
- "::getutxent",
- "::getutxid",
- "::getutxline",
- "::gmtime",
- "::hcreate",
- "::hdestroy",
- "::hsearch",
- "::inet_ntoa",
- "::l64a",
- "::lgamma",
- "::lgammaf",
- "::lgammal",
- "::localeconv",
- "::localtime",
- "::lrand48",
- "::mrand48",
- "::nftw",
- "::nl_langinfo",
- "::ptsname",
- "::putc_unlocked",
- "::putchar_unlocked",
- "::putenv",
- "::pututxline",
- "::rand",
- "::readdir",
- "::setenv",
- "::setgrent",
- "::setkey",
- "::setpwent",
- "::setutxent",
- "::strerror",
- "::strsignal",
- "::strtok",
- "::system",
- "::ttyname",
- "::unsetenv",
- "::wcstombs",
- "::wctomb",
- };
- namespace clang::tidy {
- template <> struct OptionEnumMapping<concurrency::MtUnsafeCheck::FunctionSet> {
- static llvm::ArrayRef<
- std::pair<concurrency::MtUnsafeCheck::FunctionSet, StringRef>>
- getEnumMapping() {
- static constexpr std::pair<concurrency::MtUnsafeCheck::FunctionSet,
- StringRef>
- Mapping[] = {{concurrency::MtUnsafeCheck::FunctionSet::Posix, "posix"},
- {concurrency::MtUnsafeCheck::FunctionSet::Glibc, "glibc"},
- {concurrency::MtUnsafeCheck::FunctionSet::Any, "any"}};
- return ArrayRef(Mapping);
- }
- };
- namespace concurrency {
- static ast_matchers::internal::Matcher<clang::NamedDecl>
- hasAnyMtUnsafeNames(MtUnsafeCheck::FunctionSet Libc) {
- switch (Libc) {
- case MtUnsafeCheck::FunctionSet::Posix:
- return hasAnyName(PosixFunctions);
- case MtUnsafeCheck::FunctionSet::Glibc:
- return hasAnyName(GlibcFunctions);
- case MtUnsafeCheck::FunctionSet::Any:
- return anyOf(hasAnyName(PosixFunctions), hasAnyName(GlibcFunctions));
- }
- llvm_unreachable("invalid FunctionSet");
- }
- MtUnsafeCheck::MtUnsafeCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context),
- FuncSet(Options.get("FunctionSet", MtUnsafeCheck::FunctionSet::Any)) {}
- void MtUnsafeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
- Options.store(Opts, "FunctionSet", FuncSet);
- }
- void MtUnsafeCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(
- callExpr(callee(functionDecl(hasAnyMtUnsafeNames(FuncSet))))
- .bind("mt-unsafe"),
- this);
- }
- void MtUnsafeCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *Call = Result.Nodes.getNodeAs<CallExpr>("mt-unsafe");
- assert(Call && "Unhandled binding in the Matcher");
- diag(Call->getBeginLoc(), "function is not thread safe");
- }
- } // namespace concurrency
- } // namespace clang::tidy
|