Hi Artem,
It seems I was wrong, the situation is not so simple as I thought initially.
First of all, here the checkPreCall() call, it checks a call against CloseHandle and outputs result along with passed function information:
void HandleChecker::checkPreCall(
const CallEvent &Call,
CheckerContext &C) const
{
if (Call.isCalled(_closeHandleFn))
fprintf(stderr, "It’s CloseHandle: ");
else
fprintf(stderr, "It’s NOT CloseHandle: ");
Call.dump();
}
The first sample uses usual CloseHandle call, without function pointer:
CloseHandle(NULL);
So it works.
My original code that didn’t work has used template class. The simplified code:
typedef BOOL (WINAPI *P_CloseHandle)(HANDLE);
template <P_CloseHandle pCloseHandle> struct AutoCloseHandle
{
AutoCloseHandle(HANDLE h) : _h(h) {}
~AutoCloseHandle() { pCloseHandle(_h); };
HANDLE _h;
};
int main()
{
AutoCloseHandle<&CloseHandle> autoCloseHandle(NULL);
return 1;
}
The output:
It’s NOT CloseHandle: &CloseHandle(this->_h)
It’s NOT CloseHandle: 0
It’s NOT CloseHandle: Call to ~AutoCloseHandle<&CloseHandle>() noexcept {
&CloseHandle(this->_h);
}
It’s NOT CloseHandle: &CloseHandle(this->_h)
Could you see if you can get Call.getOriginExpr()->dump() and/or Call.getDecl()->dump()? These should be more informative.
Sure, I’ve added it. Call.getDecl() is NULL for that call. Call.getOriginExpr() is the following:
CallExpr 0x64ecb10 ‘BOOL’:‘int’
-SubstNonTypeTemplateParmExpr 0x64ecac0 ‘BOOL (*)(HANDLE) attribute((stdcall))’
-UnaryOperator 0x64ecaa8 'BOOL (*)(HANDLE) __attribute__((stdcall))' prefix '&' cannot overflow
-DeclRefExpr 0x64eca90 ‘BOOL (HANDLE) attribute((stdcall))’:‘BOOL (HANDLE) attribute((stdcall))’ lvalue Function 0x57b8890 ‘CloseHandle’ ‘BOOL (HANDLE) attribute((stdcall))’:‘BOOL (HANDLE) attribute((stdcall))’
-ImplicitCastExpr 0x64ecb30 'HANDLE':'void *' <LValueToRValue>
-MemberExpr 0x64ecae8 ‘HANDLE’:‘void *’ lvalue ->_h 0x64dc710
`-CXXThisExpr 0x64ecad8 ‘struct AutoCloseHandle<&CloseHandle> *’ this
Call.dump()'s result:
&CloseHandle(this->_h)
Thank you!