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

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


I also just noticed that implicit destructors (i.e. compiler-generated or
defaulted) are ignored by the Static Analyzer. Is this intentional? This
makes it impossible to figure out when an object without an explicit
destructor is destroyed. Or am I missing something?


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

> 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/aed73f00/attachment.html>


More information about the cfe-dev mailing list