Currently we match the summary signature based on the arguments in the CallExpr.
There are a few problems with this approach.
- Variadic arguments are handled badly. Consider the below code:
int foo(void *stream, const char *format, ...); void test_arg_constraint_on_variadic_fun() { foo(0, "%d%d", 1, 2); // CallExpr }
Here the call expression holds 4 arguments, whereas the function declaration
has only 2 ParmVarDecls. So there is no way to create a summary that
matches the call expression, because the discrepancy in the number of
arguments causes a mismatch.
- The call expression does not handle the restrict type qualifier. In C99, fwrite's signature is the following:
size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict);
However, in a call expression, like below, the type of the argument does not
have the restrict qualifier.
void test_fread_fwrite(FILE *fp, int *buf) { size_t x = fwrite(buf, sizeof(int), 10, fp); }
The type of the 1st argument in the CallExpr is
PointerType 0x55b7168af2e0 'const void *' `-QualType 0x55b7168373c1 'const void' const `-BuiltinType 0x55b7168373c0 'void'
However, the type in the signature of the FunctionDecl and in the summary map is
QualType 0x55b7168af2e2 'const void *__restrict' __restrict `-PointerType 0x55b7168af2e0 'const void *' `-QualType 0x55b7168373c1 'const void' const `-BuiltinType 0x55b7168373c0 'void'
The restrict qualifier is not in the call expression (actually, why would it be?). So, this results in an unmatched signature and the summary is not applied.
The solution is to match the summary against the referened callee
FunctionDecl that we can query from the CallExpr.
Further patches will continue with additional refactoring where I am going to
do a lookup during the checker initialization and the signature match will
happen there. That way, we will not check the signature during every call,
rather we will compare only two FunctionDecl pointers.
This assert can be removed, after the previous getCanonicalType call it looks redundant.