[cfe-dev] How to extract a symbol stored in LazyCompoundVal?

Artem Dergachev via cfe-dev cfe-dev at lists.llvm.org
Thu Jun 27 17:07:50 PDT 2019


Yes, totally, just take a MemRegionManager, construct the right 
FieldRegion of the LCV's parent region, and then do getBinding() of that 
region within the LCV's Store.

Small structures are unwrapped in RegionStoreManager::tryBindSmallStruct().



On 6/27/19 3:45 PM, Torry Chen wrote:
> I build my Clang in Release mode without assertions. For pos2, LCVal = 
> StoreMgr.getDefaultBinding(*LCV) indeed returns None. I'm surprised 
> LCVal->dump() didn't crash.
>
> So this seems to be an expected behavior for getDefaultBinding() due 
> to small struct optimization. Can I retrieve the two field symbols for 
> pos2 in this case (in evalCall or checkPreCall)? Or you could point me 
> to the code where the small struct optimization happens with unwrapped 
> binds.
>
> On Thu, 27 Jun 2019 at 14:32, Artem Dergachev <noqnoqneo at gmail.com 
> <mailto:noqnoqneo at gmail.com>> wrote:
>
>     (in my case it's None because of small struct optimization; you
>     see the value as lazyCompoundVal{0x5d4bb38,pos1} in checkBind but
>     during the actual bind it gets unwrapped into two symbols)
>
>     On 6/27/19 2:22 PM, Artem Dergachev wrote:
>>     Mmm, weird. I tried and for me it crashes unwrapping an empty
>>     optional. My only guess is - do you build your clang with
>>     assertions enabled? Otherwise your checker would behave in
>>     undefined manner in this scenario. Could you check if the
>>     optional actually does contain a value?
>>
>>     On 6/25/19 9:10 PM, Torry Chen wrote:
>>>     Thank you Artem! It seems StoreManager::getDefaultBinding()
>>>     won't work if the struct variable is copied. As shown below,
>>>     getDefaultBinding() returns an undefined SVal.
>>>
>>>     I could go down into fields to get the derived symbols for X and
>>>     Y respectively, and then use getParentSymbol() to get the symbol
>>>     for the whole struct. This looks cumbersome though. Is there a
>>>     more convenient way to get the symbol for the whole struct in
>>>     this case?
>>>
>>>     // checkBind: pos1 -> conj_$3{struct XY, LC1, S45418, #1}
>>>     struct XY pos1 = next_pos(10, 20);
>>>
>>>     // checkBind: pos2 -> lazyCompoundVal{0x5d4bb38,pos1}
>>>     struct XY pos2 = pos1;
>>>
>>>     move_to_pos(pos2);
>>>
>>>     /** evalCall for move_to_pos():
>>>       SVal Pos = C.getSVal(CE->getArg(0));
>>>       ProgramStateRef State = C.getState();
>>>       StoreManager &StoreMgr =
>>>     State->getStateManager().getStoreManager();
>>>       auto LCV = Pos.getAs<nonloc::LazyCompoundVal>();
>>>       SVal LCSVal = *StoreMgr.getDefaultBinding(*LCV);
>>>       LCSVal.dump() // <- Undefined
>>>       ...
>>>       const Store St = LCV->getCVData()->getStore();
>>>       const SVal FieldSVal = StoreMgr.getBinding(St,
>>>     loc::MemRegionVal(FieldReg));
>>>       FieldSVal.dump(); // <- derived_$4{conj_$3{struct XY, LC1,
>>>     S45418, #1},pos1->X}
>>>
>>>       const auto *SD = dyn_cast<SymbolDerived>(FieldSVal.getAsSymbol());
>>>       const auto ParentSym = SD->getParentSymbol();
>>>       ParentSym.dump(); // <- conj_$3{struct XY, LC1, S45418, #1}
>>>     **/
>>>
>>>     On Tue, 25 Jun 2019 at 14:06, Artem Dergachev
>>>     <noqnoqneo at gmail.com <mailto:noqnoqneo at gmail.com>> wrote:
>>>
>>>         The "0x4aa1c58" part of "lazyCompoundVal{0x4aa1c58,pos1}" is
>>>         a Store object. You can access it with getStore() and then
>>>         read it with the help of a StoreManager.
>>>
>>>         Hmm, we seem to already have a convenient API for that, you
>>>         can do
>>>         StoreManager::getDefaultBinding(nonloc::LazyCompoundVal)
>>>         directly if all you need is a default-bound conjured symbol.
>>>         But if you want to lookup, say, specific fields in the
>>>         structure (X and Y separately), you'll need to do
>>>         getBinding() on manually constructed FieldRegions (in your
>>>         case it doesn't look very useful because the whole structure
>>>         is conjured anyway).
>>>
>>>         I guess at this point you might like the chapter 5 of my old
>>>         workbook
>>>         (https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf),
>>>         as for now it seems to be the only place where different
>>>         kinds of values are explained.
>>>
>>>
>>>         On 6/25/19 2:35 AM, Torry Chen via cfe-dev wrote:
>>>>         My project has a struct type as follows and I'm writing a
>>>>         checker for some functions that take the struct value as an
>>>>         argument. In the checkPreCall function I see the argument
>>>>         is an LazyCompoundVal, not a symbol as it would be for a
>>>>         primitive type. I tried a few ways to extract the symbol
>>>>         from the LazyCompountVal with no luck. Hope to get some
>>>>         help here.
>>>>
>>>>         struct XY {
>>>>           uint64_t X;
>>>>           uint64_t Y;
>>>>         };
>>>>
>>>>         ...
>>>>         // checkBind: pos1 -> conj_$3{struct XY, LC1, S63346, #1}
>>>>         struct XY pos1 = next_pos(...);
>>>>
>>>>         // checkPreCall: Arg0: lazyCompoundVal{0x4aa1c58,pos1}
>>>>         move_to_pos(pos1);
>>>>
>>>>         _______________________________________________
>>>>         cfe-dev mailing list
>>>>         cfe-dev at lists.llvm.org  <mailto:cfe-dev at lists.llvm.org>
>>>>         https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>
>>
>

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


More information about the cfe-dev mailing list