<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;"><br><div><div>On Apr 30, 2014, at 3:54 , Anders Rönnholm <<a href="mailto:Anders.Ronnholm@evidente.se">Anders.Ronnholm@evidente.se</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">< Clearing the map at the end of a function is a start, but you ought to make sure you don't clear it for the function that called this one. I suppose that's a refinement that can be made  later, since it only produces false negatives. (I'm not super happy about not being able to merge branches within the <function, though.)<br><br>No I don't like it either and would like to fix it but I haven't figured out how. Can I find out the current function somehow when the division occurs?<br></div></blockquote><div><br></div><div>I would just put the current StackFrameContext in as part of the key for the map, or make a two-tiered map. Then when you hit the end of the function, you can just drop things that match the current StackFrameContext.</div><br><blockquote type="cite"><div style="font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br>< +unsigned DivZeroChecker2::getBlockID(const Expr *B, CheckerContext &C) const {<br>< +  const CFG &cfg = C.getPredecessor()->getCFG();<br>< +  for (CFG::const_iterator I = cfg.begin(); I != cfg.end(); ++I) {<br>< +    for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();<br>< +         BI != BE; ++BI) {<br>< +      Optional<CFGStmt> stmt = BI->getAs<CFGStmt>();<br>< +      if (stmt && stmt->getStmt() == B)<br>< +        return (*I)->getBlockID();<br>< +    }<br>< +  }<br>< +  return 0;<br>< +}<br><br>< This is much too expensive. The CheckerContext has a NodeBuilder, which has a NodeBuilderContext, which has a CFGBlock. We should just expose that somewhere (probably on CheckerContext).<br><br>I have made a get function in CheckerContext to retrieve the NodeBuilder. Is there something better than blockid? Scope id would have been nice. Blockid creates false negatives like below when an if-statement that has nothing to do with the division comes in between.<br><br>void err_not(int x, int y) {<br> var = 77 / x;<br><br> if (y)<br>   int v = 0;<br><br> if (!x){}// should warn here but don't since this is a new blockid.<br>}<br></div></blockquote><div><br></div><div>We don't currently track scopes, but that still wouldn't eliminate all the false positives. I guess it would be closer, though—some day if we start tracking scopes again, we can switch to that.</div><div><br></div><div>I don't think it makes sense to expose the whole NodeBuilder through the CheckerContext, just the block ID.</div><div><br></div><br><blockquote type="cite"><div style="font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">< Finally, please include some test cases with inlining so that the clear-at-end-of-function logic is exercised.<br><br>What's the difference with inline and normal functions in this case? As I have understood it inline functions are still treated like normal functions when walking the ast.<br></div></blockquote><div><br></div><div>When doing path-sensitive checks, the analyzer can choose to inline any function call that it can see the definition for. I want to make sure that we still detect test-after-uses when the test and use are both within the inlined function and when there is an inlined function call between the test and use in the top-most function. (The latter would hit the first issue I noted, that clearing the entire state at the end of a function is a bit too destructive.)</div><div><br></div></div>Jordan</body></html>