[clang] [analyzer] Use CDM::CLibrary instead of isGlobalCFunction() (PR #88267)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 10 06:40:45 PDT 2024
https://github.com/NagyDonat created https://github.com/llvm/llvm-project/pull/88267
This commit updates several checkers to use call descriptions with the matching mode `CDM::CLibrary` instead 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.
>From fd16342e77dd34ca63be20658d410b99a8122f49 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Thu, 21 Mar 2024 16:59:42 +0100
Subject: [PATCH] [analyzer] Use CDM::CLibrary instead of isGlobalCFunction()
This commit updates several checkers to use call descriptions with the
matching mode `CDM::CLibrary` instead 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<check::PreCall> {
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<check::PreCall> {
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<check::PostCall, check::DeadSymbols,
CheckerKind CheckKind) const;
CallDescriptionMap<FnCheck> 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<check::PostCall, check::DeadSymbols,
// TODO: lck_rw_alloc_init(2 arguments) => 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<FnCheck> 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<FnCheck> 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<check::PostCall,
check::PreCall,
check::DeadSymbols,
check::PointerEscape> {
- 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<check::PreCall, eval::Call,
private:
CallDescriptionMap<FnDescription> 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 Checker<check::PreCall, eval::Call,
const FnDescription *lookupFn(const CallEvent &Call) const {
// Recognize "global C functions" with only integral or pointer arguments
// (and matching name) as stream functions.
- if (!Call.isGlobalCFunction())
- return nullptr;
for (auto *P : Call.parameters()) {
QualType T = P->getType();
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<check::PreCall, check::PreStmt<VAArgExpr>,
};
const SmallVector<ValistChecker::VAListAccepter, 15>
- 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))
More information about the cfe-commits
mailing list