brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · f8050bc Raw
313 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "MtUnsafeCheck.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11 12using namespace clang::ast_matchers;13 14// Initial list was extracted from gcc documentation15static const clang::StringRef GlibcFunctions[] = {16    "::argp_error",17    "::argp_help",18    "::argp_parse",19    "::argp_state_help",20    "::argp_usage",21    "::asctime",22    "::clearenv",23    "::crypt",24    "::ctime",25    "::cuserid",26    "::drand48",27    "::ecvt",28    "::encrypt",29    "::endfsent",30    "::endgrent",31    "::endhostent",32    "::endnetent",33    "::endnetgrent",34    "::endprotoent",35    "::endpwent",36    "::endservent",37    "::endutent",38    "::endutxent",39    "::erand48",40    "::error_at_line",41    "::exit",42    "::fcloseall",43    "::fcvt",44    "::fgetgrent",45    "::fgetpwent",46    "::gammal",47    "::getchar_unlocked",48    "::getdate",49    "::getfsent",50    "::getfsfile",51    "::getfsspec",52    "::getgrent",53    "::getgrent_r",54    "::getgrgid",55    "::getgrnam",56    "::gethostbyaddr",57    "::gethostbyname",58    "::gethostbyname2",59    "::gethostent",60    "::getlogin",61    "::getmntent",62    "::getnetbyaddr",63    "::getnetbyname",64    "::getnetent",65    "::getnetgrent",66    "::getnetgrent_r",67    "::getopt",68    "::getopt_long",69    "::getopt_long_only",70    "::getpass",71    "::getprotobyname",72    "::getprotobynumber",73    "::getprotoent",74    "::getpwent",75    "::getpwent_r",76    "::getpwnam",77    "::getpwuid",78    "::getservbyname",79    "::getservbyport",80    "::getservent",81    "::getutent",82    "::getutent_r",83    "::getutid",84    "::getutid_r",85    "::getutline",86    "::getutline_r",87    "::getutxent",88    "::getutxid",89    "::getutxline",90    "::getwchar_unlocked",91    "::glob",92    "::glob64",93    "::gmtime",94    "::hcreate",95    "::hdestroy",96    "::hsearch",97    "::innetgr",98    "::jrand48",99    "::l64a",100    "::lcong48",101    "::lgammafNx",102    "::localeconv",103    "::localtime",104    "::login",105    "::login_tty",106    "::logout",107    "::logwtmp",108    "::lrand48",109    "::mallinfo",110    "::mallopt",111    "::mblen",112    "::mbrlen",113    "::mbrtowc",114    "::mbsnrtowcs",115    "::mbsrtowcs",116    "::mbtowc",117    "::mcheck",118    "::mprobe",119    "::mrand48",120    "::mtrace",121    "::muntrace",122    "::nrand48",123    "::__ppc_get_timebase_freq",124    "::ptsname",125    "::putchar_unlocked",126    "::putenv",127    "::pututline",128    "::pututxline",129    "::putwchar_unlocked",130    "::qecvt",131    "::qfcvt",132    "::register_printf_function",133    "::seed48",134    "::setenv",135    "::setfsent",136    "::setgrent",137    "::sethostent",138    "::sethostid",139    "::setkey",140    "::setlocale",141    "::setlogmask",142    "::setnetent",143    "::setnetgrent",144    "::setprotoent",145    "::setpwent",146    "::setservent",147    "::setutent",148    "::setutxent",149    "::siginterrupt",150    "::sigpause",151    "::sigprocmask",152    "::sigsuspend",153    "::sleep",154    "::srand48",155    "::strsignal",156    "::strtok",157    "::tcflow",158    "::tcsendbreak",159    "::tmpnam",160    "::ttyname",161    "::unsetenv",162    "::updwtmp",163    "::utmpname",164    "::utmpxname",165    "::valloc",166    "::vlimit",167    "::wcrtomb",168    "::wcsnrtombs",169    "::wcsrtombs",170    "::wctomb",171    "::wordexp",172};173 174static const clang::StringRef PosixFunctions[] = {175    "::asctime",176    "::basename",177    "::catgets",178    "::crypt",179    "::ctime",180    "::dbm_clearerr",181    "::dbm_close",182    "::dbm_delete",183    "::dbm_error",184    "::dbm_fetch",185    "::dbm_firstkey",186    "::dbm_nextkey",187    "::dbm_open",188    "::dbm_store",189    "::dirname",190    "::dlerror",191    "::drand48",192    "::encrypt",193    "::endgrent",194    "::endpwent",195    "::endutxent",196    "::ftw",197    "::getc_unlocked",198    "::getchar_unlocked",199    "::getdate",200    "::getenv",201    "::getgrent",202    "::getgrgid",203    "::getgrnam",204    "::gethostent",205    "::getlogin",206    "::getnetbyaddr",207    "::getnetbyname",208    "::getnetent",209    "::getopt",210    "::getprotobyname",211    "::getprotobynumber",212    "::getprotoent",213    "::getpwent",214    "::getpwnam",215    "::getpwuid",216    "::getservbyname",217    "::getservbyport",218    "::getservent",219    "::getutxent",220    "::getutxid",221    "::getutxline",222    "::gmtime",223    "::hcreate",224    "::hdestroy",225    "::hsearch",226    "::inet_ntoa",227    "::l64a",228    "::lgamma",229    "::lgammaf",230    "::lgammal",231    "::localeconv",232    "::localtime",233    "::lrand48",234    "::mrand48",235    "::nftw",236    "::nl_langinfo",237    "::ptsname",238    "::putc_unlocked",239    "::putchar_unlocked",240    "::putenv",241    "::pututxline",242    "::rand",243    "::readdir",244    "::setenv",245    "::setgrent",246    "::setkey",247    "::setpwent",248    "::setutxent",249    "::strerror",250    "::strsignal",251    "::strtok",252    "::system",253    "::ttyname",254    "::unsetenv",255    "::wcstombs",256    "::wctomb",257};258 259namespace clang::tidy {260 261template <> struct OptionEnumMapping<concurrency::MtUnsafeCheck::FunctionSet> {262  static llvm::ArrayRef<263      std::pair<concurrency::MtUnsafeCheck::FunctionSet, StringRef>>264  getEnumMapping() {265    static constexpr std::pair<concurrency::MtUnsafeCheck::FunctionSet,266                               StringRef>267        Mapping[] = {{concurrency::MtUnsafeCheck::FunctionSet::Posix, "posix"},268                     {concurrency::MtUnsafeCheck::FunctionSet::Glibc, "glibc"},269                     {concurrency::MtUnsafeCheck::FunctionSet::Any, "any"}};270    return {Mapping};271  }272};273 274namespace concurrency {275 276static ast_matchers::internal::Matcher<clang::NamedDecl>277hasAnyMtUnsafeNames(MtUnsafeCheck::FunctionSet Libc) {278  switch (Libc) {279  case MtUnsafeCheck::FunctionSet::Posix:280    return hasAnyName(PosixFunctions);281  case MtUnsafeCheck::FunctionSet::Glibc:282    return hasAnyName(GlibcFunctions);283  case MtUnsafeCheck::FunctionSet::Any:284    return anyOf(hasAnyName(PosixFunctions), hasAnyName(GlibcFunctions));285  }286  llvm_unreachable("invalid FunctionSet");287}288 289MtUnsafeCheck::MtUnsafeCheck(StringRef Name, ClangTidyContext *Context)290    : ClangTidyCheck(Name, Context),291      FuncSet(Options.get("FunctionSet", MtUnsafeCheck::FunctionSet::Any)) {}292 293void MtUnsafeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {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 concurrency312} // namespace clang::tidy313