<div dir="ltr">I tried State->dump() and it shows there is no default binding for a struct variable that copies another. See below. I certainly can (and should) use the field symbols for my work. I was curious about the internals of the analyzer engine. Thank you for the detailed explanation!<br><br>struct XY pos1 = next_pos(10, 20); // Binding: pos1 -> conj_$3{struct XY, LC1, S45538, #1}<br>move_to_pos(pos1);<br>// evalCall, State->dump():<br>//<br>// Store (direct and default bindings), 0x4176b88 :<br>// (GlobalInternalSpaceRegion,0,default) : conj_$1{int, LC1, S45538, #1}<br>// (GlobalSystemSpaceRegion,0,default) : conj_$2{int, LC1, S45538, #1}<br>// (pos1,0,default) : conj_$3{struct XY, LC1, S45538, #1}<br>//<br>// Expressions by stack frame:<br>// #0 Calling main                                                                                         <br>// (LC1, S45573) move_to_pos : &code{move_to_pos}<br>// (LC1, S45581) pos1 : lazyCompoundVal{0x4176b88,pos1}<br>//<br>// Ranges are empty.<br>//<br>// StoreMgr.getBinding(St, loc::MemRegionVal(Arg0Reg)) --> <b>conj_$3{struct XY, LC1, S45538, #1}</b><br><br>struct XY pos2 = pos1; // Binding: pos2 -> lazyCompoundVal{0x4176b88,pos1}<br>move_to_pos(pos2);<br>// evalCall, State->dump():<br>//<br>// Store (direct and default bindings), 0x4176b88 :<br>// (GlobalInternalSpaceRegion,0,default) : conj_$1{int, LC1, S45538, #1}<br>// (GlobalSystemSpaceRegion,0,default) : conj_$2{int, LC1, S45538, #1}<br>// (pos1,0,default) : conj_$3{struct XY, LC1, S45538, #1}<br>//<br>// Expressions by stack frame:<br>// #0 Calling main<br>// (LC1, S45618) move_to_pos : &code{move_to_pos}<br>// (LC1, S45626) pos2 : lazyCompoundVal{0x4182e58,pos2}<br>//<br>// Ranges are empty.<br>//<br>// StoreMgr.getBinding(St, loc::MemRegionVal(Arg0Reg)) --> <b>Undefined</b><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 26 Jun 2019 at 12:15, Artem Dergachev <<a href="mailto:noqnoqneo@gmail.com">noqnoqneo@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF">
    Hmm, weird.<br>
    <br>
    I suspect that assignment was handled with "small struct
    optimization", i.e. field-by-field rather than lazily (cf.
    RegionStoreManager::tryBindSmallStruct).<br>
    <br>
    Could you do a State->dump() to verify that? If it shows that
    there's no default binding but instead there are two derived symbols
    bound to two different offsets, then the information about the
    "whole struct symbol" is already more or less lost: the static
    analyzer no longer remembers that this whole structure is the same
    as pos1, but it does remember that its fields, separately, are
    exactly the same as they were in pos1, which is what you see by
    looking at the fields separately.<br>
    <br>
    Generally we don't have many checkers that track structures as a
    whole and we don't really know how *should* the checker API look
    like in order to make such checkers easy to implement. The only such
    checker that we have is IteratorChecker and it kinda tries to do
    something but it's not very convenient. For C++ objects i'm thinking
    of tracking a "whole structure symbol" artificially, so that it
    didn't have anything to do with the actual contents of the structure
    but more with its semantic meaning: it would be preserved by const
    operations (even if they mutate memory contents of mutable fields)
    or through copies/moves and additionally you would be able to attach
    state traits to it without thinking about manually modeling
    copies/moves.<br>
    <br>
    I guess in your case, which seems to be more like a C world, the
    ad-hoc solution would be to do something like<br>
    <br>
        let's see...<br>
        pos2.x comes from pos1...<br>
        pos2.y also comes from pos1...<br>
        aha, got it!<br>
        the whole pos2 comes from pos1!<br>
    <br>
    You will *anyway* have to do this because the programmer is free to
    copy the structure field-by-field manually instead of just assigning
    the structure. This would also happen in C++ if the structure has a
    non-trivial constructor. For the same reason it's not enough to
    check only 'x' but skip 'y': the programmer can easily overwrite one
    field but not the other field.<br>
    <br>
    Finally, i'm surprised that it returns a UndefinedVal (i.e., in
    particular, it allows you to unwrap the Optional) instead of None.
    This sounds like a bug. But it might be because the structure does
    indeed have an undefined default binding (eg., this happens when
    it's allocated by malloc() or operator new). It'd make sense because
    assigning every field wouldn't overwrite the default binding. Which,
    in turn, should remind you that relying on the "structure symbol" in
    order to figure out what the contents of the structure are is not a
    good idea unless your structure is immutable and completely opaque
    or you somehow know that it's freshly created. But direct bindings
    to fields are actually always trustworthy. That's how our memory
    model works.<br>
    <br>
    <br>
    <div class="gmail-m_-910006867637439416moz-cite-prefix">On 6/25/19 9:10 PM, Torry Chen wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">Thank you Artem! It seems
        StoreManager::getDefaultBinding() won't work if the struct
        variable is copied. As shown below, getDefaultBinding() returns
        an undefined SVal.<br>
        <br>
        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?<br>
        <br>
        <font face="courier new, monospace">// checkBind: pos1 ->
          conj_$3{struct XY, LC1, S45418, #1}<br>
          struct XY pos1 = next_pos(10, 20);<br>
          <br>
          // checkBind: pos2 -> lazyCompoundVal{0x5d4bb38,pos1}<br>
          struct XY pos2 = pos1;<br>
          <br>
          move_to_pos(pos2);</font><br>
        <br>
        <font face="courier new, monospace">/** evalCall for
          move_to_pos():<br>
            SVal Pos = C.getSVal(CE->getArg(0));<br>
            ProgramStateRef State = C.getState();<br>
            StoreManager &StoreMgr =
          State->getStateManager().getStoreManager();<br>
            auto LCV = Pos.getAs<nonloc::LazyCompoundVal>();<br>
            SVal LCSVal = *StoreMgr.getDefaultBinding(*LCV);<br>
            LCSVal.dump() // <- Undefined<br>
            ...<br>
            const Store St = LCV->getCVData()->getStore();<br>
            const SVal FieldSVal = StoreMgr.getBinding(St,
          loc::MemRegionVal(FieldReg));<br>
            FieldSVal.dump(); // <- derived_$4{conj_$3{struct XY,
          LC1, S45418, #1},pos1->X}<br>
          <br>
            const auto *SD =
          dyn_cast<SymbolDerived>(FieldSVal.getAsSymbol());<br>
            const auto ParentSym = SD->getParentSymbol();<br>
            ParentSym.dump(); // <- conj_$3{struct XY, LC1, S45418,
          #1}<br>
          **/</font><br>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Tue, 25 Jun 2019 at 14:06,
          Artem Dergachev <<a href="mailto:noqnoqneo@gmail.com" target="_blank">noqnoqneo@gmail.com</a>> wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <div bgcolor="#FFFFFF"> 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.<br>
            <br>
            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).<br>
            <br>
            I guess at this point you might like the chapter 5 of my old
            workbook
            (<a class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-txt-link-freetext" href="https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf" target="_blank">https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf</a>),
            as for now it seems to be the only place where different
            kinds of values are explained.<br>
            <br>
            <br>
            <div class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-cite-prefix">On
              6/25/19 2:35 AM, Torry Chen via cfe-dev wrote:<br>
            </div>
            <blockquote type="cite">
              <div dir="ltr">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.<br>
                <br>
                <font face="courier new, monospace">struct XY {<br>
                    uint64_t X;<br>
                    uint64_t Y;<br>
                  };<br>
                  <br>
                  ...<br>
                  // checkBind: pos1 -> conj_$3{struct XY, LC1,
                  S63346, #1}</font>
                <div><span>struct XY pos1 = next_pos(...);</span>  <font face="courier new, monospace"><br>
                    <br>
                    // checkPreCall: Arg0:
                    lazyCompoundVal{0x4aa1c58,pos1}<br>
                    move_to_pos(pos1);</font><br>
                </div>
              </div>
              <br>
              <fieldset class="gmail-m_-910006867637439416gmail-m_-4861931114608865060mimeAttachmentHeader"></fieldset>
              <pre class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-quote-pre">_______________________________________________
cfe-dev mailing list
<a class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>
<a class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-txt-link-freetext" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>
</pre>
            </blockquote>
            <br>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </div>

</blockquote></div>