diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index c72a97cc01e914..80f128b917b200 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -542,10 +542,10 @@ namespace { class CFRetainReleaseChecker : public Checker { mutable APIMisuse BT{this, "null passed to CF memory management function"}; const CallDescriptionSet ModelledCalls = { - {{"CFRetain"}, 1}, - {{"CFRelease"}, 1}, - {{"CFMakeCollectable"}, 1}, - {{"CFAutorelease"}, 1}, + {CDM::CLibrary, {"CFRetain"}, 1}, + {CDM::CLibrary, {"CFRelease"}, 1}, + {CDM::CLibrary, {"CFMakeCollectable"}, 1}, + {CDM::CLibrary, {"CFAutorelease"}, 1}, }; public: @@ -555,10 +555,6 @@ class CFRetainReleaseChecker : public Checker { void CFRetainReleaseChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { - // TODO: Make this check part of CallDescription. - if (!Call.isGlobalCFunction()) - return; - // Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease. if (!ModelledCalls.contains(Call)) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index fa8572cf85edfe..86530086ff1b27 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -87,7 +87,8 @@ class PthreadLockChecker : public Checker PThreadCallbacks = { // Init. - {{{"pthread_mutex_init"}, 2}, &PthreadLockChecker::InitAnyLock}, + {{CDM::CLibrary, {"pthread_mutex_init"}, 2}, + &PthreadLockChecker::InitAnyLock}, // TODO: pthread_rwlock_init(2 arguments). // TODO: lck_mtx_init(3 arguments). // TODO: lck_mtx_alloc_init(2 arguments) => returns the mutex. @@ -95,74 +96,106 @@ class PthreadLockChecker : public Checker returns the mutex. // Acquire. - {{{"pthread_mutex_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, - {{{"pthread_rwlock_rdlock"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, - {{{"pthread_rwlock_wrlock"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, - {{{"lck_mtx_lock"}, 1}, &PthreadLockChecker::AcquireXNULock}, - {{{"lck_rw_lock_exclusive"}, 1}, &PthreadLockChecker::AcquireXNULock}, - {{{"lck_rw_lock_shared"}, 1}, &PthreadLockChecker::AcquireXNULock}, + {{CDM::CLibrary, {"pthread_mutex_lock"}, 1}, + &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"pthread_rwlock_rdlock"}, 1}, + &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"pthread_rwlock_wrlock"}, 1}, + &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"lck_mtx_lock"}, 1}, + &PthreadLockChecker::AcquireXNULock}, + {{CDM::CLibrary, {"lck_rw_lock_exclusive"}, 1}, + &PthreadLockChecker::AcquireXNULock}, + {{CDM::CLibrary, {"lck_rw_lock_shared"}, 1}, + &PthreadLockChecker::AcquireXNULock}, // Try. - {{{"pthread_mutex_trylock"}, 1}, &PthreadLockChecker::TryPthreadLock}, - {{{"pthread_rwlock_tryrdlock"}, 1}, &PthreadLockChecker::TryPthreadLock}, - {{{"pthread_rwlock_trywrlock"}, 1}, &PthreadLockChecker::TryPthreadLock}, - {{{"lck_mtx_try_lock"}, 1}, &PthreadLockChecker::TryXNULock}, - {{{"lck_rw_try_lock_exclusive"}, 1}, &PthreadLockChecker::TryXNULock}, - {{{"lck_rw_try_lock_shared"}, 1}, &PthreadLockChecker::TryXNULock}, + {{CDM::CLibrary, {"pthread_mutex_trylock"}, 1}, + &PthreadLockChecker::TryPthreadLock}, + {{CDM::CLibrary, {"pthread_rwlock_tryrdlock"}, 1}, + &PthreadLockChecker::TryPthreadLock}, + {{CDM::CLibrary, {"pthread_rwlock_trywrlock"}, 1}, + &PthreadLockChecker::TryPthreadLock}, + {{CDM::CLibrary, {"lck_mtx_try_lock"}, 1}, + &PthreadLockChecker::TryXNULock}, + {{CDM::CLibrary, {"lck_rw_try_lock_exclusive"}, 1}, + &PthreadLockChecker::TryXNULock}, + {{CDM::CLibrary, {"lck_rw_try_lock_shared"}, 1}, + &PthreadLockChecker::TryXNULock}, // Release. - {{{"pthread_mutex_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"pthread_rwlock_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"lck_mtx_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"lck_rw_unlock_exclusive"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"lck_rw_unlock_shared"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"lck_rw_done"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"pthread_mutex_unlock"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"pthread_rwlock_unlock"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"lck_mtx_unlock"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"lck_rw_unlock_exclusive"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"lck_rw_unlock_shared"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"lck_rw_done"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, // Destroy. - {{{"pthread_mutex_destroy"}, 1}, &PthreadLockChecker::DestroyPthreadLock}, - {{{"lck_mtx_destroy"}, 2}, &PthreadLockChecker::DestroyXNULock}, + {{CDM::CLibrary, {"pthread_mutex_destroy"}, 1}, + &PthreadLockChecker::DestroyPthreadLock}, + {{CDM::CLibrary, {"lck_mtx_destroy"}, 2}, + &PthreadLockChecker::DestroyXNULock}, // TODO: pthread_rwlock_destroy(1 argument). // TODO: lck_rw_destroy(2 arguments). }; CallDescriptionMap FuchsiaCallbacks = { // Init. - {{{"spin_lock_init"}, 1}, &PthreadLockChecker::InitAnyLock}, + {{CDM::CLibrary, {"spin_lock_init"}, 1}, + &PthreadLockChecker::InitAnyLock}, // Acquire. - {{{"spin_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, - {{{"spin_lock_save"}, 3}, &PthreadLockChecker::AcquirePthreadLock}, - {{{"sync_mutex_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, - {{{"sync_mutex_lock_with_waiter"}, 1}, + {{CDM::CLibrary, {"spin_lock"}, 1}, + &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"spin_lock_save"}, 3}, + &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"sync_mutex_lock"}, 1}, + &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"sync_mutex_lock_with_waiter"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, // Try. - {{{"spin_trylock"}, 1}, &PthreadLockChecker::TryFuchsiaLock}, - {{{"sync_mutex_trylock"}, 1}, &PthreadLockChecker::TryFuchsiaLock}, - {{{"sync_mutex_timedlock"}, 2}, &PthreadLockChecker::TryFuchsiaLock}, + {{CDM::CLibrary, {"spin_trylock"}, 1}, + &PthreadLockChecker::TryFuchsiaLock}, + {{CDM::CLibrary, {"sync_mutex_trylock"}, 1}, + &PthreadLockChecker::TryFuchsiaLock}, + {{CDM::CLibrary, {"sync_mutex_timedlock"}, 2}, + &PthreadLockChecker::TryFuchsiaLock}, // Release. - {{{"spin_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"spin_unlock_restore"}, 3}, &PthreadLockChecker::ReleaseAnyLock}, - {{{"sync_mutex_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"spin_unlock"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"spin_unlock_restore"}, 3}, + &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"sync_mutex_unlock"}, 1}, + &PthreadLockChecker::ReleaseAnyLock}, }; CallDescriptionMap C11Callbacks = { // Init. - {{{"mtx_init"}, 2}, &PthreadLockChecker::InitAnyLock}, + {{CDM::CLibrary, {"mtx_init"}, 2}, &PthreadLockChecker::InitAnyLock}, // Acquire. - {{{"mtx_lock"}, 1}, &PthreadLockChecker::AcquirePthreadLock}, + {{CDM::CLibrary, {"mtx_lock"}, 1}, + &PthreadLockChecker::AcquirePthreadLock}, // Try. - {{{"mtx_trylock"}, 1}, &PthreadLockChecker::TryC11Lock}, - {{{"mtx_timedlock"}, 2}, &PthreadLockChecker::TryC11Lock}, + {{CDM::CLibrary, {"mtx_trylock"}, 1}, &PthreadLockChecker::TryC11Lock}, + {{CDM::CLibrary, {"mtx_timedlock"}, 2}, &PthreadLockChecker::TryC11Lock}, // Release. - {{{"mtx_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, + {{CDM::CLibrary, {"mtx_unlock"}, 1}, &PthreadLockChecker::ReleaseAnyLock}, // Destroy - {{{"mtx_destroy"}, 1}, &PthreadLockChecker::DestroyPthreadLock}, + {{CDM::CLibrary, {"mtx_destroy"}, 1}, + &PthreadLockChecker::DestroyPthreadLock}, }; ProgramStateRef resolvePossiblyDestroyedMutex(ProgramStateRef state, @@ -258,13 +291,9 @@ REGISTER_MAP_WITH_PROGRAMSTATE(DestroyRetVal, const MemRegion *, SymbolRef) void PthreadLockChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { - // An additional umbrella check that all functions modeled by this checker - // are global C functions. - // TODO: Maybe make this the default behavior of CallDescription - // with exactly one identifier? // FIXME: Try to handle cases when the implementation was inlined rather // than just giving up. - if (!Call.isGlobalCFunction() || C.wasInlined) + if (C.wasInlined) return; if (const FnCheck *Callback = PThreadCallbacks.lookup(Call)) diff --git a/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp index 50d50562d3e756..5152624d00f466 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp @@ -52,8 +52,8 @@ class SimpleStreamChecker : public Checker { - const CallDescription OpenFn{{"fopen"}, 2}; - const CallDescription CloseFn{{"fclose"}, 1}; + const CallDescription OpenFn{CDM::CLibrary, {"fopen"}, 2}; + const CallDescription CloseFn{CDM::CLibrary, {"fclose"}, 1}; const BugType DoubleCloseBugType{this, "Double fclose", "Unix Stream API Error"}; @@ -92,9 +92,6 @@ REGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, StreamState) void SimpleStreamChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) - return; - if (!OpenFn.matches(Call)) return; @@ -111,9 +108,6 @@ void SimpleStreamChecker::checkPostCall(const CallEvent &Call, void SimpleStreamChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) - return; - if (!CloseFn.matches(Call)) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 31c756ab0c5812..bd495cd0f9710d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -302,85 +302,88 @@ class StreamChecker : public Checker FnDescriptions = { - {{{"fopen"}, 2}, {nullptr, &StreamChecker::evalFopen, ArgNone}}, - {{{"fdopen"}, 2}, {nullptr, &StreamChecker::evalFopen, ArgNone}}, - {{{"freopen"}, 3}, + {{CDM::CLibrary, {"fopen"}, 2}, + {nullptr, &StreamChecker::evalFopen, ArgNone}}, + {{CDM::CLibrary, {"fdopen"}, 2}, + {nullptr, &StreamChecker::evalFopen, ArgNone}}, + {{CDM::CLibrary, {"freopen"}, 3}, {&StreamChecker::preFreopen, &StreamChecker::evalFreopen, 2}}, - {{{"tmpfile"}, 0}, {nullptr, &StreamChecker::evalFopen, ArgNone}}, - {{{"fclose"}, 1}, + {{CDM::CLibrary, {"tmpfile"}, 0}, + {nullptr, &StreamChecker::evalFopen, ArgNone}}, + {{CDM::CLibrary, {"fclose"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalFclose, 0}}, - {{{"fread"}, 4}, + {{CDM::CLibrary, {"fread"}, 4}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalFreadFwrite, _1, _2, _3, _4, true), 3}}, - {{{"fwrite"}, 4}, + {{CDM::CLibrary, {"fwrite"}, 4}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalFreadFwrite, _1, _2, _3, _4, false), 3}}, - {{{"fgetc"}, 1}, + {{CDM::CLibrary, {"fgetc"}, 1}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalFgetx, _1, _2, _3, _4, true), 0}}, - {{{"fgets"}, 3}, + {{CDM::CLibrary, {"fgets"}, 3}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalFgetx, _1, _2, _3, _4, false), 2}}, - {{{"getc"}, 1}, + {{CDM::CLibrary, {"getc"}, 1}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalFgetx, _1, _2, _3, _4, true), 0}}, - {{{"fputc"}, 2}, + {{CDM::CLibrary, {"fputc"}, 2}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, true), 1}}, - {{{"fputs"}, 2}, + {{CDM::CLibrary, {"fputs"}, 2}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, false), 1}}, - {{{"putc"}, 2}, + {{CDM::CLibrary, {"putc"}, 2}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, true), 1}}, - {{{"fprintf"}}, + {{CDM::CLibrary, {"fprintf"}}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalFprintf, _1, _2, _3, _4), 0}}, - {{{"vfprintf"}, 3}, + {{CDM::CLibrary, {"vfprintf"}, 3}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalFprintf, _1, _2, _3, _4), 0}}, - {{{"fscanf"}}, + {{CDM::CLibrary, {"fscanf"}}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalFscanf, _1, _2, _3, _4), 0}}, - {{{"vfscanf"}, 3}, + {{CDM::CLibrary, {"vfscanf"}, 3}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalFscanf, _1, _2, _3, _4), 0}}, - {{{"ungetc"}, 2}, + {{CDM::CLibrary, {"ungetc"}, 2}, {&StreamChecker::preWrite, std::bind(&StreamChecker::evalUngetc, _1, _2, _3, _4), 1}}, - {{{"getdelim"}, 4}, + {{CDM::CLibrary, {"getdelim"}, 4}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalGetdelim, _1, _2, _3, _4), 3}}, - {{{"getline"}, 3}, + {{CDM::CLibrary, {"getline"}, 3}, {&StreamChecker::preRead, std::bind(&StreamChecker::evalGetdelim, _1, _2, _3, _4), 2}}, - {{{"fseek"}, 3}, + {{CDM::CLibrary, {"fseek"}, 3}, {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}}, - {{{"fseeko"}, 3}, + {{CDM::CLibrary, {"fseeko"}, 3}, {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}}, - {{{"ftell"}, 1}, + {{CDM::CLibrary, {"ftell"}, 1}, {&StreamChecker::preWrite, &StreamChecker::evalFtell, 0}}, - {{{"ftello"}, 1}, + {{CDM::CLibrary, {"ftello"}, 1}, {&StreamChecker::preWrite, &StreamChecker::evalFtell, 0}}, - {{{"fflush"}, 1}, + {{CDM::CLibrary, {"fflush"}, 1}, {&StreamChecker::preFflush, &StreamChecker::evalFflush, 0}}, - {{{"rewind"}, 1}, + {{CDM::CLibrary, {"rewind"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalRewind, 0}}, - {{{"fgetpos"}, 2}, + {{CDM::CLibrary, {"fgetpos"}, 2}, {&StreamChecker::preWrite, &StreamChecker::evalFgetpos, 0}}, - {{{"fsetpos"}, 2}, + {{CDM::CLibrary, {"fsetpos"}, 2}, {&StreamChecker::preDefault, &StreamChecker::evalFsetpos, 0}}, - {{{"clearerr"}, 1}, + {{CDM::CLibrary, {"clearerr"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalClearerr, 0}}, - {{{"feof"}, 1}, + {{CDM::CLibrary, {"feof"}, 1}, {&StreamChecker::preDefault, std::bind(&StreamChecker::evalFeofFerror, _1, _2, _3, _4, ErrorFEof), 0}}, - {{{"ferror"}, 1}, + {{CDM::CLibrary, {"ferror"}, 1}, {&StreamChecker::preDefault, std::bind(&StreamChecker::evalFeofFerror, _1, _2, _3, _4, ErrorFError), 0}}, - {{{"fileno"}, 1}, + {{CDM::CLibrary, {"fileno"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalFileno, 0}}, }; @@ -540,8 +543,6 @@ class StreamChecker : public CheckergetType(); if (!T->isIntegralOrEnumerationType() && !T->isPointerType() && diff --git a/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp index 2d1b873abf73f0..28320f46f237ac 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp @@ -100,32 +100,31 @@ class ValistChecker : public Checker, }; const SmallVector - ValistChecker::VAListAccepters = {{{{"vfprintf"}, 3}, 2}, - {{{"vfscanf"}, 3}, 2}, - {{{"vprintf"}, 2}, 1}, - {{{"vscanf"}, 2}, 1}, - {{{"vsnprintf"}, 4}, 3}, - {{{"vsprintf"}, 3}, 2}, - {{{"vsscanf"}, 3}, 2}, - {{{"vfwprintf"}, 3}, 2}, - {{{"vfwscanf"}, 3}, 2}, - {{{"vwprintf"}, 2}, 1}, - {{{"vwscanf"}, 2}, 1}, - {{{"vswprintf"}, 4}, 3}, + ValistChecker::VAListAccepters = {{{CDM::CLibrary, {"vfprintf"}, 3}, 2}, + {{CDM::CLibrary, {"vfscanf"}, 3}, 2}, + {{CDM::CLibrary, {"vprintf"}, 2}, 1}, + {{CDM::CLibrary, {"vscanf"}, 2}, 1}, + {{CDM::CLibrary, {"vsnprintf"}, 4}, 3}, + {{CDM::CLibrary, {"vsprintf"}, 3}, 2}, + {{CDM::CLibrary, {"vsscanf"}, 3}, 2}, + {{CDM::CLibrary, {"vfwprintf"}, 3}, 2}, + {{CDM::CLibrary, {"vfwscanf"}, 3}, 2}, + {{CDM::CLibrary, {"vwprintf"}, 2}, 1}, + {{CDM::CLibrary, {"vwscanf"}, 2}, 1}, + {{CDM::CLibrary, {"vswprintf"}, 4}, 3}, // vswprintf is the wide version of // vsnprintf, vsprintf has no wide version - {{{"vswscanf"}, 3}, 2}}; + {{CDM::CLibrary, {"vswscanf"}, 3}, 2}}; -const CallDescription ValistChecker::VaStart({"__builtin_va_start"}, /*Args=*/2, +const CallDescription ValistChecker::VaStart(CDM::CLibrary, + {"__builtin_va_start"}, /*Args=*/2, /*Params=*/1), - ValistChecker::VaCopy({"__builtin_va_copy"}, 2), - ValistChecker::VaEnd({"__builtin_va_end"}, 1); + ValistChecker::VaCopy(CDM::CLibrary, {"__builtin_va_copy"}, 2), + ValistChecker::VaEnd(CDM::CLibrary, {"__builtin_va_end"}, 1); } // end anonymous namespace void ValistChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) - return; if (VaStart.matches(Call)) checkVAListStartCall(Call, C, false); else if (VaCopy.matches(Call))