From fe3b20d5ab4b47823fb48ad7cfbc47b8224ce826 Mon Sep 17 00:00:00 2001 From: NagyDonat Date: Thu, 11 Apr 2024 10:44:35 +0200 Subject: [PATCH] [analyzer] Use CDM::CLibrary instead of isGlobalCFunction() (#88267) This commit updates several checkers to use call descriptions with the matching mode `CDM::CLibrary` instead of checking `Call.isGlobalCFunction()` after performing the match. This resolves several TODOs in various checkers. Note that both matching with `CDM::CLibrary` and calling `isGlobalCFunction` leads to `CheckerContext::isCLibraryFunction()` checks (so this change is close to being NFC), but if it is used via the matching mode then the checker can automatically recognize the builtin variants of the matched functions. I'll also make similar changes in GenericTaintChecker, but that checker has separate and inconsistent rules for handling the normal and the builtin variant of several functions (e.g. `memcpy` and `__builtin_memcpy`), so I'll put those changes into a separate commit. --- .../Checkers/BasicObjCFoundationChecks.cpp | 12 +- .../Checkers/PthreadLockChecker.cpp | 115 +++++++++++------- .../Checkers/SimpleStreamChecker.cpp | 10 +- .../StaticAnalyzer/Checkers/StreamChecker.cpp | 69 +++++------ .../StaticAnalyzer/Checkers/ValistChecker.cpp | 35 +++--- 5 files changed, 130 insertions(+), 111 deletions(-) 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))