<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div><div>On Mar 28, 2013, at 6:32 , Sean Silva <<a href="mailto:silvas@purdue.edu">silvas@purdue.edu</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">Could you explain in a bit more detail why the "regular" noreturn attributes are insufficient for providing this information?</div></blockquote><br></div><div>Sure. As you know, "noreturn" affects compilation: the emitted function will not have an epilogue, and callers will consider code following a call to be unreachable. The analyzer couldn't care less about the former, but would like to model the latter to avoid infeasible paths, such as the one shown here:</div><div><br></div><div><font face="Courier">int *p = getPointerIfExists();</font></div><div><font face="Courier">if (!p)</font></div><div><font face="Courier">  exit(1);</font></div><div><font face="Courier">*p = 1; // no null dereference</font></div><div><br></div><div>Although the assignment to *p looks accessible from both branches of the 'if', we recognize that exit() and functions marked noreturn won't actually reach that assignment.</div><div><br></div><div>We get a problem, however, in cases like this (simplified from AsmParser):</div><div><br></div><div><font face="Courier">void readRegister(int *x) {</font></div><div><font face="Courier">  // try to read register</font></div><div><font face="Courier">  if (failure)</font></div><div><font face="Courier">    return Error("Could not read register.");</font></div><div><font face="Courier">  *x = parsedRegister;</font></div><div><font face="Courier">}</font></div><div><font face="Courier"><br></font></div><div><font face="Courier">  int x;</font></div><div><font face="Courier">  if (readRegister(&x))</font></div><div><font face="Courier">    return true;</font></div><div><font face="Courier">  use(x); // no use of uninitialized memory</font></div><div><br></div><div>Here, the 'Error' method is always going to return 'true', so we know execution won't actually reach the use of 'x'. Because 'Error' is defined in another translation unit, however, the analyzer does <i>not</i> know this. We can't mark 'Error' as 'noreturn' because in the real program it <i>does</i> return—an error in parsing assembly does not immediately exit the whole program, just the AsmParser.</div><div><br></div><div>The best thing would be to have some form of whole-program analysis, but that's a ways off right now.</div><div><br></div><div>The next best thing would be to have a general postcondition annotation language that could say "this function always returns true", but that's a sort of language extension even if we implement it with attributes or comments.</div><div><br></div><div>So the next best thing after <i>that</i> would be to tell the analyzer that it should stop analyzing this path, because it's "like" a noreturn path—that's what 'analyzer_noreturn' does. This does mean we might miss some warnings that would only occur <i>on</i> the error path, but it also cuts down on false positives that basically come from the interprocedural CFG not reflecting reality. There won't ever <i>be</i> a branch on which Error returns false and 'x' is actually uninitialized.</div><div><br></div><div>If/when we get either of the better two solutions, I'll take this back out.</div><div><br></div><div>Hope that's a solid enough explanation of the analyzer's limitations.</div><div>Jordan</div></body></html>