[cfe-dev] Prevent RetainCountChecker from Analyzing Function Bodies when They Have Certain Annotate Attribute

Devin Coughlin via cfe-dev cfe-dev at lists.llvm.org
Fri Jul 14 16:09:36 PDT 2017


> On Jul 14, 2017, at 12:31 PM, Malhar Thakkar <cs13b1031 at iith.ac.in> wrote:
> 
> evalCall-ing a function based on annotations worked for the most part except for the following scenario.
> 
> If the definition of the annotated function is after it is called somewhere in the code, the RetainCountChecker is unable to "see" the annotation on this function (I checked this by printing debug messages in evalCall to see if the RetainCountChecker is able to find the annotation).
> 
> Consider the following examples.
> 
> // Definition of annotated function after it is called.
> #define NULL 0
> typedef struct
> {
> 	int ref;
> } isl_basic_map;
> 
> void free(void *);
> __isl_give isl_basic_map *foo(__isl_take isl_basic_map *bmap);
> isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap);
> 
> __isl_give isl_basic_map *bar(__isl_take isl_basic_map *bmap) {
> 	bmap = foo(bmap);
> 	return isl_basic_map_free(bmap); // Leak warning for 'bmap' raised here.
> }
> 
> __attribute__((annotate("rc_ownership_trusted_implementation"))) isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
> {
> 	if (!bmap)
> 		return NULL;
> 
> 	if (--bmap->ref > 0)
> 		return NULL;
> 
> 	free(bmap);
> 	return NULL;
> }
> 
> // Definition of annotated function before it is called.
> #define NULL 0
> typedef struct
> {
> 	int ref;
> } isl_basic_map;
> 
> void free(void *);
> __isl_give isl_basic_map *foo(__isl_take isl_basic_map *bmap);
> isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap);
> 
> __attribute__((annotate("rc_ownership_trusted_implementation"))) isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
> {
> 	if (!bmap)
> 		return NULL;
> 
> 	if (--bmap->ref > 0)
> 		return NULL;
> 
> 	free(bmap);
> 	return NULL;
> }
> 
> __isl_give isl_basic_map *bar(__isl_take isl_basic_map *bmap) {
> 	bmap = foo(bmap);
> 	return isl_basic_map_free(bmap); // No leak warning for 'bmap' raised here.
> }
> It would really help me if someone could point out why the RetainCountChecker behaves this way.

I don’t know. One thing to note is that unlike most annotations, this one seems like it belongs on the definition of the function and not its interface, so you probably want to use getDefinition() to get the FuncDecl corresponding to the definition of the function body.

> Also, I have a few queries directed to Dr. Alexandre and Dr. Sven.
> I applied these trusted annotations to obj_free(), obj_cow() and obj_copy() as they have a pattern (__isl.*free, __isl.*cow and __isl.*copy). 
> 
> Do, functions of the type obj_alloc_* have the same pattern if at all they do? Also, are there any other functions which require such annotations? 

It would be helpful if you explained what the obj_alloc_* functions do. Do they malloc memory directly and return as __isl_give? Do they manipulate reference counts directly?

> I feel that I'll have to add annotations to obj_dup() as well because although adding an annotation to obj_cow() guarantees that the RetainCountChecker will not enter obj_cow's body when it is called, the analyzer might begin its analysis from obj_cow() which may lead it to call obj_dup() and result in leak warnings.

What does obj_dup() do?

Devin

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170714/de6963e9/attachment.html>


More information about the cfe-dev mailing list