In the implementation of checker, there are three ways to determine whether
CallExpr is the function call specified.
1). ‘CallDescription’, used in SimpleStreamChecker, BlockInCriticalSectionChecker
2). ‘ASTContext.Idents.get()’, used in MallocChecker, StreamChecker and
3). ‘isCLibraryFunction() and isCPPStdLibraryFunction()’, used in CStringChecker.
For 1), my understanding is that CallDescription corresponds to CallEvent.
My question is, for 2) and 3),
which way is better when determining whether
a function call is the specified library function?
Should ‘isCPPStdLibraryFunction()’ be moved from CStringChecker.cpp to
CheckerContext.cpp like ‘isCLibraryFunction()’?
If I understand correctly,‘ASTContext.Idents.get()’ may have false positives,
for example, ASTContext.Idents.get(“malloc”) may match to user-defined
function of the same name. Is that right?
CallDescription is the ultimate easy-to-use interface created specifically for this purpose, but it's young and doesn't do much yet. It is already superior because it checks the number of arguments. It's better to improve CallDescription if it lacks features you need, instead of doing things manually, because CallDescription's ultimate goal is your convenience.
Things to be aware of:
- Identifier is a simple "word"; C function foo() and C++ method Class::foo() both have the same callee identifier "foo". So you might need isCLibraryFunction(FD) (without the name argument) as an additional check now (which should probably be squeezed into CallDescription - let it support fully qualified names, or make sure that there isn't much to qualify). Similarly, Objective-C messages are not yet supported.
- CallDescription is doing the right thing by taking callee identifier from the path-sensitive CallEvent, not from the syntactic CallExpr. Because path-sensitive analysis is able to determine the callee more often, eg. when there is a call by function pointer.
- You cannot easily discriminate between standard library functions and user-defined functions with the same name. C standard specifies how library functions defined in particular headers behave, but it says nothing about the situation when the user defines a function with the same name on his own. It might help to check if the function is in "system headers" by consulting the ASTContext.getSourceManager()::isInSystemHeader(), but it's still possible to write code to trick this check, so you still want to avoid crashes by checking that the function has a valid prototype, at least the number of arguments.