[cfe-dev] [analyzer] Conjuring symbols in checkBeginFunction()

Artem Dergachev via cfe-dev cfe-dev at lists.llvm.org
Wed Jun 20 19:01:18 PDT 2018


On 6/20/18 2:56 AM, Julian Ganz via cfe-dev wrote:
> Hi List,
>
> For some time now I'm trying to use information attached to symbols created
> in a checker's `checkBeginFunction()`. Specifically, I'm trying to conjure
> symbols for fields of `this` for methods. Currently, my checker does this
> by:
>
> retrieving a symbolic value for the `this region`:
>      auto self = state->getSVal(C.getSValBuilder.getCXXThis(record,
> C.getStackFrame()));
> (with `state` being the `ProgramStateRef`, `C` being the `CheckerContext`
> and `record` being the `RecordDecl` of the object)
>
> retrieving a region from this symbolic value:
>      auto instanceRegion = dyn_cast_or_null<SubRegion>(self.getAsRegion());
>
> retrieving a region for the field:
>      auto fieldRegion =
> state->getStateManager().getRegionManager().getFieldRegion(fieldDecl,
> instanceRegion);
> (with `fieldDecl` being the declaration of the field within the `record`)
>
> and, finally, getting a symbol representing this region's value:
>      auto symbol = C.getSymbolManager().getRegionValueSymbol(fieldRegion);

You shouldn't be doing this. You can obtain the same result by using 
State->getSVal(fieldRegion), which would simply retrieve the value 
that's already bound to the region before the analysis begins. It's not 
printed or explicitly written out in the RegionStore's maps, but it's 
"just there".

Generally, you shouldn't be constructing symbols yourself, at all, in 
the checker. Checkers aren't responsible for this, it is fully automated 
by the analyzer core, you should just take values that are already 
there, because the core already knows what values are there.

>
> This gives me a symbol, which I tried to use in other checker callbacks:
>      reg_$1<TypeOfField SymRegion{reg_$0<ObjType * this>}->field>
>
> Note: I don't use ` ProgramState::getLValue (const FieldDecl*, SVal) `
> because it did not work (either). I don't really remember why.
>
> In callbacks executed afterwards, I indeed see that some symbol is bound to
> the field. However, it appears not to be the one I created. E.g.
> `state->dump()` prints:
>      Expressions:
>        (0xf5e7470,0x931a828) this->field :
> &base{SymRegion{derived_$224{conj_$221{int},base{base{base{base{SymRegion{re
> g_$0<class ObjType * this>}->field,somethig}, somethig }, somethig else},
> somethig else }-> somethig else }}, somethig else }

It means that the field was overwritten during analysis and now contains 
a different unknown value that's denoted by a different symbol.

> When given either a `MemberExpr` expression referring to that field or a
> `ImplicitCastExpr` wrapping the former, I just get an ` UnknownVal ` from
> `state->getSVal(expr)` (neither expression is at `0x931a828`).

 From your dump, you should be able to retrieve the &base{...} region 
from the expression 0x931a828 with location context 0xf5e7470.

It might be that you're supplying a wrong LocationContext (which 
represents a stack frame, eg. during recursion the same active 
expression may have different values on different stack frames in the 
backtrace).

It might also be that MemberExpr is not an active expression. 
Environment maintains only expressions that are currently under 
evaluation, because you can't even define what a value of an expression 
is if you aren't in the process of evaluating it. That's why we have 
symbols and regions that are distinct from expressions and actually have 
any sort of meaning in more than just one moment of time. If you need to 
recover a value of an expression that was evaluated long time ago, you 
most likely should use program state traits to track the information 
your checker needs.

>
> Is there actually any way to make this work with the (current) clang static
> analyzer? E.g. to create symbols wich are not (yet) "backed" by an
> expression encountered in the AST?

I didn't fully understand what are your final goals with this, but it 
definitely sounds like you're on a wrong track with these attempts. I 
might be able to help if you explain what sort of check are you trying 
to implement and what sort of code you're running it on (based on your 
dump, it's a large piece of code, so you might have to reduce it).

> Btw: I'm not really surprised that this did not work for me, since the fresh
> symbol is not bound to any expression and hence can not be (trivially) found
> in later callbacks. I could work around the issue by trying to catch
> expressions referring to `this`, but this is quite suboptimal in my
> use-case, especially given the fact that a ` check::PreStmt<CXXThisExpr>`
> apparently never get's invoked. Also. considering that support for
> contract-based programming made it into the draft for C++20 this week, I
> suspect that there will be other developers trying to construct and use
> symbols for expressions which may not be in the function body at all.
>
> Regards,
> Julian
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev




More information about the cfe-dev mailing list