[cfe-dev] Removing "TransferFuncs" from the analyzer

Jordy Rose jediknil at belkadan.com
Mon Jun 27 19:35:56 PDT 2011


Hi Ted and cfe-dev. In my free time I've been looking into the issue of "transfer functions" in the analyzer — a supposedly swappable implementation of logic for evaluating function calls and Objective-C messages, among other things. As the Checker infrastructure has grown, almost all of the once-unique transfer function logic can now be implemented using essentially-pluggable Checkers.

That wouldn't be such a problem, except that in reality the implementation of TransferFuncs in the analyzer is CFRefCount, which mixes in a whole bunch of logic for tracking retain counts and Cocoa conventions. We shouldn't need to run that with every run of the analyzer (though most of the code will early-exit when it realizes it's not relevant). Some of the code has already been extracted to a class called RetainReleaseChecker, but at this point we can do a lot more.

This e-mail is recording my thoughts on this and how far I got; it's not intended as an immediate call to action.

In fact, the behavior of a hypothetical SimpleTransferFuncs only includes this:
- Invalidating ivars of ObjC message receiver
- Invalidating ivars of 'this' for C++ method call
- Invalidating function/method args
- Invalidating globals if necessary
- Conjuring return values

And these effects only happen if no checker claims "evalCall" for a given function call.


On the other hand, a fully-fledged RetainReleaseChecker with all existing functionality isn't quite possible because of four things:

- CFBugReports use function call summaries to show the retain/release history of a leaked object. Function summaries are currently associated with ExplodedNodes in a DenseMap. In addition to being somewhat inefficient (summaries for calls that have nothing to do with ref-counting are also saved), Checkers are const, and so can't store summaries in a mutable data structure. (Marking the map 'mutable' doesn't feel like the right solution.) I don't have a solution for this.

- There's no evalObjCMessage, for the very sensible reason that overriding a method can make its behavior totally different. Nevertheless, there are a few messages we /do/ want to model in a RetainReleaseChecker: -[NSAutoreleasePool init], -[NSAutoreleasePool addObject:], -retain, -release, and -autorelease. Fortunately, pretty much everything else would fit in a PostObjCMessage implementation.

- When function/method arguments are invalidated, their reference counts persist. But any other sort of invalidation does destroy reference count records. Currently this uses a whitelist built before invalidating the various regions referenced in a call, but with no special consideration given to RetainReleaseChecker, that'd be a little strange. I can think of two ways around this: reconstruct the whitelist on every region invalidation if we're in a function call (probably not a good idea) and reconstruct the reference bindings in a post-call check (by walking backwards through ExplodedNodes to the pre-call state).

- CFRefCount currently registers a GRState::Printer for printing the retain count info in a state. Checkers currently have no way to register printers for custom state info, and that should probably be fixed anyway.

Everything else that CFRefCount currently does can be done using the current Checker architecture. (For more detailed but less structured notes on this, see attached 
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: CFRefCount.txt
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110627/2212a1b4/attachment.txt>
-------------- next part --------------
.)


As for what I /did/ accomplish, evalBind and evalAssume can be migrated to RetainReleaseChecker almost without changes: 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CFRefCount.1.patch
Type: application/octet-stream
Size: 8634 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110627/2212a1b4/attachment.obj>
-------------- next part --------------


Everything /other/ than evalCall, evalObjCMessage, and evalSummary can be moved to RetainReleaseChecker, but that leaves plenty of hackery behind: 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CFRefCount.2.patch
Type: application/octet-stream
Size: 44139 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110627/2212a1b4/attachment-0001.obj>
-------------- next part --------------



I'm going to stop this work here...it's where it crosses the line from "simple migration" to "design decisions". Once the four issues above are resolved, it should actually be pretty straightforward to eliminate TransferFuncs and CFRefCount from the analyzer and make RetainReleaseChecker optional. Which would be great, right?

Jordy


More information about the cfe-dev mailing list