[cfe-dev] Replacing the analyzer's CallOrObjCMessage with something more general
jordan_rose at apple.com
Thu Jun 21 13:28:32 PDT 2012
Basic performance testing (i.e., timing "TESTDIRS=Analysis make test" and "scan-build xcodebuild" on an existing Objective-C open source project) shows no change (within noise). I'm not sure of the best way to test the impact of this more deeply, but I would like to not be prematurely devirtualizing if there's no payoff for it.
On Jun 21, 2012, at 11:04 , Jordan Rose <jordan_rose at apple.com> wrote:
> Hi, Ted, Anna. In order to pave the way for proper handling of destructors and new-expressions, I'm working on replacing CallOrObjCMessage with a new class tree, CallAction. Like CallOrObjCMessage, CallAction bundles together a particular function/method/block invocation and a snapshot of where it occurred; unlike CallOrObjCMessage, it is done using "proper" OO and is a lot more maintainable.
> The idea is that in many cases, we don't really care /what/ is being called as long as we can do something useful with it. Currently there are a lot of places that either switch based on what's being called (ExprEngine::invalidateArguments), or funnel a bunch of other checks into a common method (CallAndMessageChecker, RetainCountChecker -- currently using CallOrObjCMessage). Other checks like AttrNonNullChecker would probably be useful for constructors and possibly Objective-C methods, but currently just check CallExprs.
> The other flaw with CallOrObjCMessage is that a lot of the checkers that use it assume that there is an expression in the source that corresponds to the call or for each argument, which is not true for destructors or operator new size arguments. CallAction will at least make it safe to ask for the SVal corresponding to an argument that isn't in the AST, and it should provide a source range for each argument that can be used for diagnostics.
> Currently I have it set up like this:
> |-AnyFunctionCall (things that might have FunctionDecls)
> | |-SimpleCall (things that are written as CallExprs)
> | | |-FunctionCall (simple C functions, and anything unknown)
> | | |-CXXMemberCall (calls to C++ non-static member functions)
> | | \-BlockCall (calls to blocks)***
> | |-CXXConstructorCall (calls to constructors)
> | |-*CXXDestructorCall
> | |-*CXXAllocator
> | |-*CXXDeallocator
> | \-*AttributeCleanup (__attribute__((cleanup))-style destructors)
> \-ObjCMessageInvocation (explicit sends, property accesses, and eventually subscripting, via ObjCMessage)
> The ones with * are not implemented yet. BlockCall is annotated with *** because while blocks are written as CallExprs, they do not have an associated FunctionDecl, meaning that SimpleCall's access to the arguments can be inherited by AnyFunctionCall's type-checking and such must be overridden. (Lambdas do not have this problem because they are actually objects with an operator(); they will show up in CXXMemberCall.)
> Eventually I'd like to completely eliminate CallOrObjCMessage. ObjCMessage might still be good to keep around, since it's a little lighter (it doesn't wrap state and location context in with the expressions). We can then have new checker callbacks preCall and postCall, which don't care how a function or method is being invoked. (evalCall would probably also use CallAction, but still not be called for Objective-C messages.)
> This first draft does use virtual methods. I haven't done any performance testing yet, but if it turns out to be an issue I can change to using "static dynamic" dispatch using a switch.
> Finally, the names are definitely tentative. Any better suggestions?
> Comments much appreciated,
> (attached: the base CallAction header file and one big diff of what I have so far)
More information about the cfe-dev