<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jul 15, 2017 at 4:39 AM, Devin Coughlin <span dir="ltr"><<a href="mailto:dcoughlin@apple.com" target="_blank">dcoughlin@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><div><div class="gmail-h5"><blockquote type="cite"><div>On Jul 14, 2017, at 12:31 PM, Malhar Thakkar <<a href="mailto:cs13b1031@iith.ac.in" target="_blank">cs13b1031@iith.ac.in</a>> wrote:</div><br class="gmail-m_-440615778087120094Apple-interchange-newline"><div><div dir="ltr">evalCall-ing a function based on annotations worked for the most part except for the following scenario.<div><br></div><div>If the definition of the annotated function is <i style="font-weight:bold">after </i>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).</div><div><br></div><div>Consider the following examples.</div><div><b><font><br></font></b></div><div>
  
  


<h2></h2>

<div class="gmail-m_-440615778087120094gmail-highlight" style="background:rgb(248,248,248)"><pre><b><font>// Definition of annotated function after it is called.</font></b></pre><pre><span style="color:rgb(188,122,0)">#define NULL 0</span>
<span style="color:rgb(0,128,0);font-weight:bold">typedef</span> <span style="color:rgb(0,128,0);font-weight:bold">struct</span>
{
        <span style="color:rgb(176,0,64)">int</span> ref;
} isl_basic_map;

<span style="color:rgb(176,0,64)">void</span> <span style="color:rgb(0,0,255)">free</span>(<span style="color:rgb(176,0,64)">void</span> <span style="color:rgb(102,102,102)">*</span>);
__isl_give isl_basic_map <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">foo</span>(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap);
isl_basic_map <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">isl_basic_map_free</span>(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap);

__isl_give isl_basic_map <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">bar</span>(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap) {
        bmap <span style="color:rgb(102,102,102)">=</span> foo(bmap);
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> isl_basic_map_free(bmap); <b>// Leak warning for 'bmap' raised here.</b>
}

__attribute__((annotate(<span style="color:rgb(186,33,33)">"rc_<wbr>ownership_trusted_<wbr>implementation"</span>))) isl_basic_map <span style="color:rgb(102,102,102)">*</span>isl_basic_map_free(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap)
{
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>bmap)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;

        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">--</span>bmap<span style="color:rgb(102,102,102)">-></span>ref <span style="color:rgb(102,102,102)">></span> <span style="color:rgb(102,102,102)">0</span>)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;

        free(bmap);
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;
}</pre></div></div><div class="gmail_extra"><b><font><br></font></b></div><div class="gmail_extra">
  
  


<h2></h2>

<div class="gmail-m_-440615778087120094gmail-highlight" style="background:rgb(248,248,248)"><pre><b><font>// Definition of annotated function before it is called.</font></b></pre><pre><span style="color:rgb(188,122,0)">#define NULL 0</span>
<span style="color:rgb(0,128,0);font-weight:bold">typedef</span> <span style="color:rgb(0,128,0);font-weight:bold">struct</span>
{
        <span style="color:rgb(176,0,64)">int</span> ref;
} isl_basic_map;

<span style="color:rgb(176,0,64)">void</span> <span style="color:rgb(0,0,255)">free</span>(<span style="color:rgb(176,0,64)">void</span> <span style="color:rgb(102,102,102)">*</span>);
__isl_give isl_basic_map <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">foo</span>(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap);
isl_basic_map <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">isl_basic_map_free</span>(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap);

__attribute__((annotate(<span style="color:rgb(186,33,33)">"rc_<wbr>ownership_trusted_<wbr>implementation"</span>))) isl_basic_map <span style="color:rgb(102,102,102)">*</span>isl_basic_map_free(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap)
{
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>bmap)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;

        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">--</span>bmap<span style="color:rgb(102,102,102)">-></span>ref <span style="color:rgb(102,102,102)">></span> <span style="color:rgb(102,102,102)">0</span>)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;

        free(bmap);
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;
}

__isl_give isl_basic_map <span style="color:rgb(102,102,102)">*</span>bar(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap) {
        bmap <span style="color:rgb(102,102,102)">=</span> foo(bmap);
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,0,255)">isl_basic_map_free</span>(bmap); <b>// No leak warning for 'bmap' raised here.</b>
}
</pre></div></div><div class="gmail_extra">It would really help me if someone could point out why the RetainCountChecker behaves this way.</div></div></div></blockquote><div><br></div></div></div><div>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.</div></div></div></blockquote><div><br></div><div>Yes, this works. I have uploaded a <a href="https://reviews.llvm.org/D34937">patch</a> on Phabricator for the same. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class="gmail-"><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra">Also, I have a few queries directed to Dr. Alexandre and Dr. Sven.</div><div class="gmail_extra">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). </div><div class="gmail_extra"><br></div><div class="gmail_extra">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? </div></div></div></blockquote><div><br></div></span><div>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?</div></div></div></blockquote><div><br></div><div>Generally, obj_alloc_* functions initialize all the fields (including initializing the reference counter to 1) of that particular isl object (obj) and then return obj as __isl_give. </div><div>However, there are certain scenarios in which the objects passed to obj_alloc_* functions are <i><b>reference counted objects</b></i> and are annotated with __isl_take in which case leak warnings are raised.</div><div><br></div><div>Example</div><div><br></div><div>
  
  


<h2></h2>

<div class="gmail-highlight" style="background:rgb(248,248,248)"><pre><b>// In the below example, the reference counts of expr1 and expr2 are not decremented.</b></pre><pre><b>// Here, expr1 and expr2 are reference counted objects.</b></pre><pre><b>// Analysis starts from '</b>isl_ast_node_for_get_cond'</pre><pre><div class="gmail-highlight" style="background-image:initial;background-position:initial;background-size:initial;background-repeat:initial;background-origin:initial;background-clip:initial"><pre>__attribute__((annotate(<span style="color:rgb(186,33,33)">"rc_ownership_trusted_implementation"</span>))) __isl_give isl_ast_expr <span style="color:rgb(102,102,102)">*</span>isl_ast_expr_copy(__isl_keep isl_ast_expr <span style="color:rgb(102,102,102)">*</span>expr)
{
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>expr)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;

        expr<span style="color:rgb(102,102,102)">-></span>ref<span style="color:rgb(102,102,102)">++</span>;
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> expr;
}</pre></div></pre><pre>__isl_give isl_ast_expr <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">isl_ast_expr_alloc_binary</span>(<span style="color:rgb(0,128,0);font-weight:bold">enum</span> isl_ast_op_type type,
        __isl_take isl_ast_expr <span style="color:rgb(102,102,102)">*</span>expr1, __isl_take isl_ast_expr <span style="color:rgb(102,102,102)">*</span>expr2)
{
        isl_ctx <span style="color:rgb(102,102,102)">*</span>ctx;
        isl_ast_expr <span style="color:rgb(102,102,102)">*</span>expr <span style="color:rgb(102,102,102)">=</span> <span style="color:rgb(0,128,0)">NULL</span>;

        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>expr1 <span style="color:rgb(102,102,102)">||</span> <span style="color:rgb(102,102,102)">!</span>expr2)
                <span style="color:rgb(0,128,0);font-weight:bold">goto</span> error;

        ctx <span style="color:rgb(102,102,102)">=</span> isl_ast_expr_get_ctx(expr1);
        expr <span style="color:rgb(102,102,102)">=</span> isl_ast_expr_alloc_op(ctx, type, <span style="color:rgb(102,102,102)">2</span>);
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>expr)
                <span style="color:rgb(0,128,0);font-weight:bold">goto</span> error;

        expr<span style="color:rgb(102,102,102)">-></span>u.op.args[<span style="color:rgb(102,102,102)">0</span>] <span style="color:rgb(102,102,102)">=</span> expr1;
        expr<span style="color:rgb(102,102,102)">-></span>u.op.args[<span style="color:rgb(102,102,102)">1</span>] <span style="color:rgb(102,102,102)">=</span> expr2; <b>// Leak warning raised for expr1</b>

        <span style="color:rgb(0,128,0);font-weight:bold">return</span> expr; <b>// Leak warning raised for expr2</b>
<span style="color:rgb(160,160,0)">error:</span>
        isl_ast_expr_free(expr1);
        isl_ast_expr_free(expr2);
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;
}</pre><pre><div class="gmail-highlight" style="background-image:initial;background-position:initial;background-size:initial;background-repeat:initial;background-origin:initial;background-clip:initial"><pre>__isl_give isl_ast_expr <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">isl_ast_node_for_get_cond</span>(
        __isl_keep isl_ast_node <span style="color:rgb(102,102,102)">*</span>node)
{
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>node)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (node<span style="color:rgb(102,102,102)">-></span>type <span style="color:rgb(102,102,102)">!=</span> isl_ast_node_for)
                isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
                        <span style="color:rgb(186,33,33)">"not a for node"</span>, <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>);
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>node<span style="color:rgb(102,102,102)">-></span>u.f.degenerate)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> isl_ast_expr_copy(node<span style="color:rgb(102,102,102)">-></span>u.f.cond);

        <span style="color:rgb(0,128,0);font-weight:bold">return</span> <b>isl_ast_expr_alloc_binary</b>(isl_ast_op_le,
                                <b>isl_ast_expr_copy</b>(node<span style="color:rgb(102,102,102)">-></span>u.f.iterator),
                                <b>isl_ast_expr_copy</b>(node<span style="color:rgb(102,102,102)">-></span>u.f.init));
}</pre></div></pre></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class="gmail-"><div><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra">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.</div></div></div></blockquote><div><br></div></span><div>What does obj_dup() do?</div></div></div></blockquote><div><br></div><div>obj_dup() duplicates the isl object passed to it in the sense that it copies the fiels of the passed isl object to a new object of the same type. However, it does not change the reference count. </div><div><br></div><div>Generally, obj_cow() calls obj_dup(). The summary of their functionalities is as follows.</div><div><br></div><div><span style="color:rgb(51,51,51);font-family:Arial,sans-serif,sans;font-size:13px">obj_dup: copy the data, don't actually touch obj->ref</span><br style="color:rgb(51,51,51);font-family:Arial,sans-serif,sans;font-size:13px"><span style="color:rgb(51,51,51);font-family:Arial,sans-serif,sans;font-size:13px">obj_cow: decrement reference count by 1 if it is > 1 and call obj_dup, or do nothing to the reference count.</span><br></div><div><br></div><div>Consider the following snippet of code to understand it better.</div><div><br></div>
  
  


<h2></h2>

<div class="gmail-highlight" style="background:rgb(248,248,248)"><pre>__isl_give isl_basic_map <span style="color:rgb(102,102,102)">*</span><span style="color:rgb(0,0,255)">isl_basic_map_dup</span>(__isl_keep isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap)
{
        <span style="color:rgb(0,128,0);font-weight:bold">struct</span> isl_basic_map <span style="color:rgb(102,102,102)">*</span>dup;

        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>bmap)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;
        dup <span style="color:rgb(102,102,102)">=</span> isl_basic_map_alloc_space(isl_space_copy(bmap<span style="color:rgb(102,102,102)">-></span>dim),
                        bmap<span style="color:rgb(102,102,102)">-></span>n_div, bmap<span style="color:rgb(102,102,102)">-></span>n_eq, bmap<span style="color:rgb(102,102,102)">-></span>n_ineq);
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>dup)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;
        dup_constraints(dup, bmap);
        dup<span style="color:rgb(102,102,102)">-></span>flags <span style="color:rgb(102,102,102)">=</span> bmap<span style="color:rgb(102,102,102)">-></span>flags;
        dup<span style="color:rgb(102,102,102)">-></span>sample <span style="color:rgb(102,102,102)">=</span> isl_vec_copy(bmap<span style="color:rgb(102,102,102)">-></span>sample);
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> dup; </pre><pre>}</pre>
  
  


<h2></h2>

<div class="gmail-highlight" style="background-image:initial;background-position:initial;background-size:initial;background-repeat:initial;background-origin:initial;background-clip:initial"><pre>__attribute__((annotate(<span style="color:rgb(186,33,33)">"rc_ownership_trusted_implementation"</span>))) __isl_give isl_basic_map <span style="color:rgb(102,102,102)">*</span>isl_basic_map_cow</pre><pre>(__isl_take isl_basic_map <span style="color:rgb(102,102,102)">*</span>bmap)
{
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (<span style="color:rgb(102,102,102)">!</span>bmap)
                <span style="color:rgb(0,128,0);font-weight:bold">return</span> <span style="color:rgb(0,128,0)">NULL</span>;

        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (bmap<span style="color:rgb(102,102,102)">-></span>ref <span style="color:rgb(102,102,102)">></span> <span style="color:rgb(102,102,102)">1</span>) {
                bmap<span style="color:rgb(102,102,102)">-></span>ref<span style="color:rgb(102,102,102)">--</span>;
                bmap <span style="color:rgb(102,102,102)">=</span> <b>isl_basic_map_dup</b>(bmap);
        }
        <span style="color:rgb(0,128,0);font-weight:bold">if</span> (bmap) {
                ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
                ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
        }
        <span style="color:rgb(0,128,0);font-weight:bold">return</span> bmap;
</pre></div><pre><span style="font-family:arial,sans-serif">}</span> </pre></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class="gmail-HOEnZb"><font color="#888888"><div><br></div><div>Devin</div><div><br></div></font></span></div></div></blockquote><div><br></div><div>Regards,</div><div>Malhar </div></div><br></div></div><div hspace="streak-pt-mark" style="max-height:1px"><img alt="" style="width:0px;max-height:0px;overflow:hidden" src="https://mailfoogae.appspot.com/t?sender=aY3MxM2IxMDMxQGlpdGguYWMuaW4%3D&type=zerocontent&guid=7d9f6045-e00e-4153-98ef-0ef5ff0e52d8"><font color="#ffffff" size="1">ᐧ</font></div>