<div dir="ltr">Sorry for a mistake: I was trying both methods but pasted a wrong line in the previous email. The following is what I did with getDefaultBinding, still getting Undefined SVal when calling with pos2. Both pos1 and pos2 are used after the calls and they shouldn't be dead.<br><br>// evalCall for move_to_pos(struct XY pos):<br>ProgramStateRef State = C.getState();<br>const SVal Pos = C.getSVal(CE->getArg(0));<br>StoreManager &StoreMgr = State->getStateManager().getStoreManager();<br>auto LCV = Pos.getAs<nonloc::LazyCompoundVal>();<br>auto LCVal = StoreMgr.getDefaultBinding(*LCV);<br>LCVal->dump(); // --> conj_$3 when calling with pos1 but Undefined for pos2<br><div><br></div><div>// Code to check:<br>struct XY pos1 = next_pos(10, 20);<br>move_to_pos(pos1);<br>struct XY pos2 = pos1;<br>move_to_pos(pos2);<br>printf("X %ld Y %ld\n", pos1.X, pos1.Y);<br>printf("X %ld Y %ld\n", pos2.X, pos2.Y);<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 26 Jun 2019 at 17:31, 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">
    On 6/26/19 5:29 PM, Artem Dergachev wrote:<br>
    <blockquote type="cite">
      
      You shouldn't do the "StoreMgr.getBinding(St,
      loc::MemRegionVal(Arg0Reg)) --> Undefined" part; it's not what
      i suggested and it doesn't work because Arg0Reg is already "dead"
      and its value has been garbage-collected (i assume that by Arg0Reg
      you mean the VarRegion for pos2).<br>
      <br>
      Like, if pos2 is never used later in the program, then we don't
      need to remember its value. So if move_to_pos(pos2) is the last
      use of pos2, we'll drop the binding and the Store would be empty.<br>
      <br>
      Accessing dead regions will produce unexpected results; the code
      for getSVal()/getBinding() assumes that the region is live (or
      that the expression is active when you try to retrieve a value of
      an expression).<br>
      <br>
      In this case it's like "hmm, the user is reading from a local
      variable, but it has no bindings, which means it has never been
      written to (otherwise i would have remembered it), which means
      that it's undefined behavior and contents of the variable are
      undefined". The real reason why Store doesn't remember any
      bindings is because it has correctly forgot about them.<br>
      <br>
      This is why we include the (lazy) copy of the old Store with the
      LazyCompoundValue. In order to extract data from
      lazyCompoundVal{0x4182e58,pos2}, you need to load the variable
      from the Store 0x4182e58, *not* from the current Store. The region
      is still live in that old store, but in the current store it's no
      longer there.<br>
      <br>
      <br>
      This is why in order to obtain <br>
    </blockquote>
    <br>
    <br>
    Whoops, didn't finish my email :) I mean, the thing with
    `getDefaultBinding(LCV)` is that it knows that it needs to look up
    the value in the correct Store, so that's what you should use.<br>
    <br>
    <br>
    <blockquote type="cite"> <br>
      <div class="gmail-m_5602915233991053082moz-cite-prefix">On 6/26/19 3:22 PM, Torry Chen wrote:<br>
      </div>
      <blockquote type="cite">
        
        <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" 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"> 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_5602915233991053082gmail-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_5602915233991053082gmail-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_5602915233991053082gmail-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_5602915233991053082gmail-m_-910006867637439416gmail-m_-4861931114608865060mimeAttachmentHeader"></fieldset>
                        <pre class="gmail-m_5602915233991053082gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-quote-pre">_______________________________________________
cfe-dev mailing list
<a class="gmail-m_5602915233991053082gmail-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_5602915233991053082gmail-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>
      </blockquote>
      <br>
    </blockquote>
    <br>
  </div>

</blockquote></div>