<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Austin,<div><br></div><div>I think the issue here is that in the example you provide, the analyzer is caching out and stops analyzing the path after the first loop (due to us imprecisely handling loops). </div><div><br></div><div>If you split test_alloca function into two, the checker will get called on both alloca and __builtin_alloca: </div><div><span class="Apple-style-span" style="font-family: Monaco; font-size: 11px; "><span style="color: #951067">void</span></span><span class="Apple-style-span" style="font-family: Monaco; font-size: 11px; "> test_alloca() {</span><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; color: rgb(75, 144, 115); "><span style="color: #000000"> </span><span style="color: #951067">char</span><span style="color: #000000"> *foo = alloca(0); </span>// expected-warning{{Call to '<span style="text-decoration: underline">alloca</span>' has an allocation size of 0 bytes}}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "> <span style="color: #951067">for</span>(<span style="color: #951067">unsigned</span> i = 0; i < 100; i++) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "> foo[i] = 0;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "> }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; ">}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "><span style="color: #951067">void</span> test_alloca2() {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; color: rgb(75, 144, 115); "><span style="color: #000000"> </span><span style="color: #951067">char</span><span style="color: #000000"> *foo2 = __builtin_alloca(0); </span>// expected-warning{{Call to '<span style="text-decoration: underline">alloca</span>' has an allocation size of 0 bytes}}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "> <span style="color: #951067">for</span>(<span style="color: #951067">unsigned</span> i = 0; i < 100; i++) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "> foo2[i] = 0;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; "> }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Monaco; ">}</div><div><br></div><div>Cheers,</div><div>Anna.</div><div><br></div><div><div>On Jan 6, 2012, at 3:45 PM, austin seipp wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Hi Ted,<br><br>Thanks for the reply. I just found BuiltinFunctionChecker and see that<br>it deals with both __builtin_alloca and __builtin_expect, but there's<br>still something awry here I think.<br><br>For one, as I said before, I modified checkPreStmt to tell me both<br>when getCalleeName returns an empty StringRef (i.e. it is ignored,)<br>and in the case it doesn't, output the callee name. But per the output<br>above, it neither says the call exists, or that it skipped it due to<br>the empty StringRef - so it seems checkPreStmt is in fact -never-<br>called in the case of __builtin_alloca! I played around with<br>BuiltinFunctionChecker's route of getting the FunctionDecl and looking<br>if it corresponds to a builtin's ID, but as you would expect - no<br>dice.<br><br>The other concerning thing is that BuiltinFunctionChecker also has<br>logic to deal with __builtin_expect, but despite that it appears<br>perfectly normally as you would expect when checkPreStmt is invoked in<br>the testcase. There is no difference semantically or AST-wise between<br>__builtin_expect and any other function call here - you can just look<br>at the textual name. So if there -is- a discrepancy, it most certainly<br>seems to concern itself only with __builtin_alloca. Or,<br>__builtin_alloca is being handled correctly, and __builtin_expect is<br>in fact the buggy case here (my brain tells me it is likely the<br>former, since as far as the analyzer is concerned, I think __builtin's<br>would be recognized as a regular call expression like any other.)<br>Either way something weird is going on that should be fixed.<br><br>I went ahead and added a simplistic evalCall callback to<br>UnixAPIChecker to see if it could identify the call to<br>__builtin_alloca, much in the same way BuiltinFunctionChecker does.<br>This *does not work either* in fact! So now I'm pretty darn confused.<br><br>I think there's very clearly a bug or something lurking here, but I'm<br>at a loss as to how to proceed. Attached is my patch to UnixAPIChecker<br>with some helper debugging output, and appropriate modifications to<br>the testsuite which should expose the problem (the compiler will<br>complain that there was an expected warning, but none was found.)<br>Since the crappy debug output will fudge up the 'make test' runner I'd<br>just advise checking unix-fns.c for the easy case.<br><br>Please excuse the inclusion of iostream - a blatant violation of LLVM<br>coding practice; I just needed a quick and simple dump. I also<br>apologize that I had to include the small refactoring and valloc<br>addition I mentioned as part of the patch, but the work was already<br>there. I hope you find it useful in making sense of things.<br><br>Thanks for the help, and sorry for the long-winded rant.<br><br>PS. There seems to be further weirdness upon review of my test output<br>that doesn't concern itself with builtins, but, I'll go ahead and<br>mention it and possibly put it into another cfe-dev thread, or a<br>bugzilla ticket - look closely at the unix-fns.c analysis test, and<br>then look at the output produced in my example with my little patch.<br>The weird part is how the analyzer identifies the first 4 calls being<br>'open, open, close, open', in that order, but in the source code, the<br>analyzer *should* be seeing open, close, open, close! In fact, it only<br>sees 1 close call, period! After those 4 calls, all further calls are<br>identified properly, 'in order' as you would expect to see. I may be<br>missing something, but that seems to indicate something Very Bad is<br>happening.<br><br>On Fri, Jan 6, 2012 at 4:51 PM, Ted Kremenek <<a href="mailto:kremenek@apple.com">kremenek@apple.com</a>> wrote:<br><blockquote type="cite">Hi Austin,<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">The logic for __builtin_alloca is being handled by BuiltinFunctionChecker, which explicitly models the semantics of the function. It does this by responding to 'evalCall()'. That should not interfere with the checkPreStmt() callback in UnixAPIChecker, and if that is the case there is a bug here.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">What is likely the case is that builtins are just modeled slightly differently in the AST. I suggest that you take a look at BuiltinFunctionChecker for how we recognize calls to __builtin_alloca and see if that approach works for you. In any case, please follow-up on the list to see if that fixes or doesn't fix the issue you are seeing.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Cheers,<br></blockquote><blockquote type="cite">Ted<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">On Jan 6, 2012, at 2:38 PM, austin seipp wrote:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><blockquote type="cite">Hello,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I was working on adding alloca/valloc checks (as well as a small<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">cleanup) to UnixAPIChecker following the recent changes to detect<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">zero-sized allocations in calloc/realloc (SVN r147500,) when I noticed<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">a strange issue when attempting to identify calls to __builtin_alloca.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">'alloca' seems to dissolve to __builtin_alloca via a CPP #define on OS<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">X, so for the check to work and be 'complete' it needs to identify<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">both names. However, it seems as if the checker callback -<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">checkPreStmt on a CallExpr - is not invoked for calls to<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">__builtin_alloca, but it does work just dandy in the case of say,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">__builtin_expect. So presumably I'm missing something important and<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">it's expected behavior, or this is a bug I guess.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">A little more concrete: I amended ./test/Analysis/unix-fns.c to<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">contain calls for alloca - with a prototyped definition so there<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">aren't complaints about implicit declarations - *and* calls to<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">__builtin_alloca, both of which should trigger a 0-sized allocation<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">warning. I also modified UnixAPIChecker to dump the name of every<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">callee it comes across, or dump some trivial output if it skips the<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">call due to getCalleeName returning an empty StringRef.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">The results look like this on my machine:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">$ /Users/a/code/llvm-build/Debug+Asserts/bin/clang -cc1<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-internal-isystem<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">/Users/a/code/llvm-build/Debug+Asserts/bin/../lib/clang/3.1/include<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-triple x86_64-apple-darwin10 -analyze<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-analyzer-checker=unix.API,osx.API<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">/Users/a/code/llvm/tools/clang/test/Analysis/unix-fns.c<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-analyzer-store=region -fblocks -verify<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = open<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = open<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = close<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = open<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = __builtin_expect<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = dispatch_once<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = __builtin_expect<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = dispatch_once<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = pthread_once<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = pthread_once<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = malloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = malloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = calloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = calloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = calloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = realloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = realloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = alloca<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = alloca<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = valloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">fname = valloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">The calls to __builtin_alloca should effectively appear in the same<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">spot as the 'alloca' calls, but they clearly aren't. There also isn't<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">any 'no name' output indicating the call was skipped as a result of an<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">empty StringRef from getCalleeName. So it seems as if checkPreStmt for<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">a CallExpr completely skips over __builtin_alloca. The calls do appear<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">in a dump of the CFG as you would likely expect.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Is __builtin_alloca handled specially in the analyzer somewhere, and<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">thus I'm missing something? If it is and this is unavoidable, I'll<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">just back out those changes and send a patch containing the valloc<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">addition as well as the small cleanup if they're worth it. But I don't<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">see off hand why it can't work for alloca as well, so I thought I'd<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">ask.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">--<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Regards,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Austin<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">_______________________________________________<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">cfe-dev mailing list<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br></blockquote></blockquote><blockquote type="cite"><br></blockquote><br><br><br>-- <br>Regards,<br>Austin<br><span><no-dana-only-zuul.patch></span>_______________________________________________<br>cfe-dev mailing list<br><a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev<br></div></blockquote></div><br></div></body></html>