Query Regarding RetainCountChecker | Clang Static Analyzer

Dear all,

Consider the following hypothetical test cases (using the Integer Set Library objects and annotations) which is passed through the RetainCountChecker.

// Case 1
#define __isl_give attribute((cf_returns_retained))
#define __isl_take attribute((cf_consumed))

// Declaration of isl_basic_map_cow(). Definition is in another .c file and hence is not visible to the static analyzer.
__isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap);

__isl_give isl_basic_map *foo(__isl_take isl_basic_map *bmap) {
isl_basic_map *temp = bmap;
bmap = isl_basic_map_cow(bmap);
free(bmap);
return temp; // Leak warning is raised for ‘bmap’ here.
}

// Case 2

#define __isl_give attribute((cf_returns_retained))
#define __isl_take attribute((cf_consumed))

// Declaration of isl_basic_map_cow(). Definition is in another .c file and hence is not visible to the static analyzer.
__isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap);

__isl_give isl_basic_map *foo(__isl_take isl_basic_map *bmap) {
isl_basic_map *temp = bmap;
bmap = isl_basic_map_cow(bmap);
free(bmap);
return bmap; // Use-after-free warning is raised for ‘bmap’ here.
}

My question:

  • Looking at the warnings raised in both the cases. could someone please explain me why is a leak warning being raised in Case 1? isl_basic_map_cow() returns an object with a +1 retain count which is then freed.

Thank you.

Regards,
Malhar Thakkar

These warnings seem reasonable to me, because we can be certain that free() doesn't decrement reference counts - instead it frees the memory (release doesn't imply freeing the memory - something else may still retain). So `bmap' is freed but not released, therefore we have a warning from RetainCountChecker regarding a memory leak *and*, in case 2, a warning from MallocChecker regarding use-after-free.