[cfe-dev] Static Analyzer: immortal objects and getting the symbol for 'this'

Gábor Kozár kozargabor at gmail.com
Tue Jul 16 05:20:09 PDT 2013


In the meanwhile, I figured out how to get the FieldRegion that is the
argument of the CXXDeleteExpr:

ProgramStateRef state = context.getState();
ASTContext& astContext = context.getASTContext();
MemRegionManager& memRegionManager =
context.getStoreManager().getRegionManager();

if(const MemberExpr* memberExpr =
llvm::dyn_cast<MemberExpr>(delExpr->getArgument()->IgnoreImpCasts()))
{
    const FieldDecl* fieldDecl =
llvm::dyn_cast<FieldDecl>(memberExpr->getMemberDecl());
    const CXXThisRegion* thisRegion =
context.getStoreManager().getRegionManager().getCXXThisRegion(

astContext.getPointerType(astContext.getRecordType(fieldDecl->getParent())),
        context.getLocationContext());

    MemRegionRef thisObjectRegion =
context.getState()->getSVal(thisRegion).getAsRegion();

    const FieldRegion* fieldRegion =
memRegionManager.getFieldRegion(fieldDecl, thisObjectRegion); // this is
what I needed
}

(Hope this helps someone, someday.)

This MemRegionManager class is really useful, but this code still has been
a headache to put together. (e.g. I got numerous assertion failures until I
realized getCXXThisRegion wants a QualType that is a pointer type.) What I
was trying to do is working now, but I'm still interested in how to do it
more easily...


2013/7/16 Gábor Kozár <kozargabor at gmail.com>

> Hi Jordan,
>
> Thanks for the answer!
>
> > *Objects that live on the stack don't have symbols; the properties of a
> stack object's region is entirely known and doesn't need to be symbolic.
> It's a VarRegion, not a SymbolicRegion.*
>
> I'm kind of confused about the difference between SVal and SymExpr. I
> understand that a MemRegion models a region of the memory, i.e. this
> contains a value that can be obtained using
> context.getState()->getSVal(memRegion). My impression is that SVal is just
> a bridge between SymExpr and MemRegion, where SymExpr actually represents
> the symbolic values assigned during analysis. Is this about right?
>
>
> > *Additionally, symbol death is not quite the same as local variable
> death. If the value of a local variable is symbolic, and that value gets
> copied somewhere else, the symbol won't die when the local variable does.*
>
> This is the kind of code I'm talking about:
>
> void foo()
> {
>       Foo f;
> }
>
> As far as I can tell, 'f' here is actually a MemRegion, which seems
> counter-intuitive to me. I want to be notified when the 'f' object dies.
> checkDeadSymbols doesn't seem to work, I dump everything every time it's
> called and I don't get anything resembling what I'm looking for. I also
> tried checkRegionChanges, but that doesn't seem to tell me either.
>
> What I'm left doing is looking when a dtor is called. checkPostCall is
> actually a good idea on that, although I've also figured out how to get the
> 'this' region from only a CheckerContext:
>
>
> const CXXThisRegion* thisRegion =
> context.getStoreManager().getRegionManager().getCXXThisRegion(
>             dtor->getThisType(context.getASTContext()),
>             context.getLocationContext());
>
>  SVal thisVal = context.getState()->getSVal(thisRegion);
> const MemRegion* objectRegion = thisVal.getAsRegion(); // this is 'f'
>
> What I'm trying to do here is to check what resources the object
> destructor deallocates. checkDeadSymbols does tell me when a member pointer
> is freed using delete, but this unfortunately happens after both
> checkEndFunction and checkPostCall for the destructor, so it is not useful
> for me. Or it would be, if I had been able to get the MemRegion that
> contains the SymExpr that died - this would get me the FieldRegion, in
> which the pointer was stored, and that would be enough.
> Unfortunately, I get UnknownSpaceRegion if I try to do this:
> context.getStoreManager().getRegionManager().getSymbolicRegion(deadSymbol)->getSuperRegion().
> This kind of makes sense, since the symbol is dead, so the information
> about where it has been is probably already lost.
>
> I also tried to do checkPreStmt for CXXDeleteExpr, but here I have no clue
> as to how to get the SVal/SymExpr/MemRegion that is being deleted.
>
> So I'm kind of running out of ideas here. Could you give me some pointers?
>
> Thanks!
>
> Gabor
>
> 2013/7/15 Jordan Rose <jordan_rose at apple.com>
>
>> Hi, Gabor. Objects that live on the stack don't have symbols; the
>> properties of a stack object's region is entirely known and doesn't need to
>> be symbolic. It's a VarRegion, not a SymbolicRegion.
>>
>> The good news is that regions are also uniqued, and so if you're just
>> looking to identify an object, using the region as the key is often
>> reasonable as well, possibly with a call to stripCasts().
>>
>> Additionally, symbol death is not *quite* the same as local variable
>> death. If the value of a local variable is symbolic, and that value gets
>> copied somewhere else, the symbol won't die when the local variable does.
>> (Symbol information is basically garbage collected—each cleanup starts by
>> crawling through all the live regions and values to see what's still
>> accessible.) Local variables have very well-defined scope rules, so all of
>> their control is in the CFG.
>>
>> Rather than using the 'this' region and checkEndFunction, why not use
>> checkPostCall and CXXDestructorCall's getCXXThisVal? (What are you actually
>> trying to do?)
>>
>> Jordan
>>
>>
>> On Jul 13, 2013, at 10:30 , Gábor Kozár <kozargabor at gmail.com> wrote:
>>
>> Hi,
>>
>>
>> I'm using the Clang Static Analyzer from Clang 3.3. I want to check
>> object's state when they die. I tried using checkDeadSymbols, but according
>> to the SymbolReaper, the objects of interest never die. This is my test
>> code:
>>
>> struct Foo
>> {
>>      int* x;
>>      Foo() { x = new int(10); }
>> };
>>
>> int main(int argc, const char** argv)
>> {
>>       Foo f;
>>       return 0;
>> }
>>
>> The int* does die, but f does not. (I cannot check this directly: I just
>> made the SymbolReaper print all symbols are regions that died, using the
>> dead_begin(), etc. and region_begin() etc. methods). Why is this, and how
>> can I work around it?
>>
>> Even when there is a user-made destructor, which I can get using
>> checkEndFunction, I'm unable to get back the symbol that represents 'f'. I
>> spent like an hour digging through clang::ento's reference, and this was my
>> best tip:
>>
>> const CXXThisRegion* thisRegion =
>> context.getStoreManager().getRegionManager().getCXXThisRegion(
>>             dtor->getThisType(context.getASTContext()),
>>             context.getLocationContext());
>>
>> Unfortunately, this gives something that doesn't seem to have anything to
>> do with 'f'. How can I get the symbol representing 'f', using only the
>> CheckerContext and the const CXXDestructorDecl* I can obtain from the
>> LocationContext?
>>
>> I'm really stuck, and any help would be greatly appreciated. Thank you!
>>
>> Gabor
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130716/bc635a3d/attachment.html>


More information about the cfe-dev mailing list