[cfe-dev] Troubles tracking a function parameter with the static analyzer

Jordan Rose jordan_rose at apple.com
Wed May 14 08:29:59 PDT 2014


On May 12, 2014, at 20:09 , Ivan Reche <ivan.reche at gmail.com> wrote:

> Hey all,
> 
> Suppose I'm working with the following C snippet:
> 
> void inc(int *num) {*num++;}
> void dec(int *num) {*num--;}
> 
> void f(int var) {
>     inc(&var);
>     dec(&var);
> }
> 
> By using a static analyzer, I want to be able to tell if the value of var didn't change during the function's execution. I know I have to keep its state on my own (that's the point of writing a Clang checker), but I'm having troubles getting a unique reference of this variable.
> 
> For example: if I use the following API
> 
> void MySimpleChecker::checkPostCall(const CallEvent &Call,
>                                     CheckerContext &C) const {
>     SymbolRef MyArg = Call.getArgSVal(0).getAsSymbol();
> }
> 
> I'd expect it to return a pointer to this symbol's representation in my checker's context. However, I always get 0 into MyArg by using it this way. This happens for both inc and dec functions in the pre and post callbacks.
> 
> What am I missing here? What concepts did I get wrong?
> 
> Note: I'm currently reading the Clang CFE Internals Manual and I've read the excellent How to Write a Checker in 24 Hours material. I still couldn't find my answer so far.

Hi, Ivan. The value that gets passed to 'inc' or 'dec' is the address of 'var', yes? And 'var' is a parameter to the function 'f'. While the value of 'var' could be anything, the memory for the parameter itself is something the analyzer can model perfectly, as a VarRegion. The address of that memory would be a loc::MemRegionVal pointing to that VarRegion. And that's the SVal that gets passed to 'inc' and 'dec'. No symbols involved.

Now, as it turns out the analyzer does track the contents of memory regions (conservatively), so you don't have to keep the state on your own. This is what the Store is for, and you can get at the analyzer's current representation of the contents by using "ProgramState::getSVal", specifically the overload that takes a Loc or a MemRegion. If you pass the region for the parameter here, you'll get the symbolic value representing its contents. If the value for the contents changes between the start and the end of the function, one of three things could have happened:

- Someone has stored something to the region.
- Someone has added constraints to the value in the region, and now the analyzer has more information about it.
- The region has "escaped", and we don't know whether another function is going to modify it. (For example, if you pass the address of the region to a function whose body the analyzer cannot see.)

That's not bad, but depending on what you want, there's an even more targeted way to do this: the checkBind and checkRegionChanges callbacks. These tell you when any value is assign to a region and when a region changes for any reason, respectively. Using those together might give you a good chance at tracking the information you need.

Hope that helps,
Jordan

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140514/d16b89f9/attachment.html>


More information about the cfe-dev mailing list