diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3259,6 +3259,11 @@ return true; } + if (FName == "singleShotImpl" && + FD->getQualifiedNameAsString() == "QTimer::singleShotImpl") { + return true; + } + // Handle cases where we know a buffer's /address/ can escape. // Note that the above checks handle some special cases where we know that // even though the address escapes, it's still our responsibility to free the diff --git a/clang/test/Analysis/Inputs/qt-simulator.h b/clang/test/Analysis/Inputs/qt-simulator.h --- a/clang/test/Analysis/Inputs/qt-simulator.h +++ b/clang/test/Analysis/Inputs/qt-simulator.h @@ -6,6 +6,7 @@ namespace Qt { enum ConnectionType {}; +enum TimerType {}; } struct QMetaObject { @@ -31,3 +32,8 @@ }; struct QApplication : public QCoreApplication {}; + +struct QTimer { + static void singleShotImpl(int, Qt::TimerType, const QObject *, + QtPrivate::QSlotObjectBase *); +}; diff --git a/clang/test/Analysis/qt_malloc.cpp b/clang/test/Analysis/qt_malloc.cpp --- a/clang/test/Analysis/qt_malloc.cpp +++ b/clang/test/Analysis/qt_malloc.cpp @@ -19,3 +19,8 @@ new QtPrivate::QSlotObjectBase(), (Qt::ConnectionType)0, nullptr, nullptr); } + +void singleShot(QTimer *timer) { + timer->singleShotImpl(0, (Qt::TimerType)0, nullptr, + new QtPrivate::QSlotObjectBase()); +}