<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    Again, *p is not a dereference. The result of this expression is
    still the location, not the value read from that location. You can
    easily convert this location back to the numeric value of the
    address: &*p. This is completely normal code with null pointers
    that does not constitute any UB and in fact has practical uses: for
    example, you can calculate offset of field x in struct S as
    (uintptr_t)&(((S *)0)->x), people have macros like this.<br>
    <br>
    On the contrary, *p in (*p + 1) or *p in (x = *p) or in your example
    are actual dereferences because they are contextually converted to
    rvalues in order to perform the surrounding operations. <i>This
      conversion is the dereference, not the operator* on its own.</i>
    The operator simply converts rvalue to lvalue - it still represents
    a location.<br>
    <br>
    Operators * and & are modeled in the static analyzer as no-op
    for the above reason: they really don't do anything on their own.
    The implicit cast from lvalue to rvalue is the read and this is what
    the checker reacts to. This is also why I'm nervous every time I see
    IgnoringParenImpCasts() in the code: some of these implicit casts
    are really important and shouldn't be missed most of the time.<br>
    <br>
    You should read AST dumps of these expressions for more clarity, it
    really helped me back in the day.<br>
    <br>
    <div class="moz-cite-prefix">On 9/20/21 6:44 AM, via cfe-dev wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:00d701d7ae25$9593e6c0$c0bbb440$@gmail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0cm;
        font-size:10.0pt;
        font-family:"Courier New";}span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;
        mso-fareast-language:EN-US;}span.EmailStyle22
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}div.WordSection1
        {page:WordSection1;}</style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
      <div class="WordSection1">
        <p class="MsoNormal"><span lang="EN-US">Thanks Harald,<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">I missed that.<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">On the other hand, I
            still think that we should be consistent. (Hereby thanks for
            Deep for the unique_ptr case.)<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">And, by definition we
            dereferenced a null pointer, so the abstract machine should
            halt.<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">That being said, a
            slightly modified version of the same code:<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><a
              href="https://godbolt.org/z/Eenavva8x"
              moz-do-not-send="true">https://godbolt.org/z/Eenavva8x</a><o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">constexpr void foo() {<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">  int *p = 0;<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">  *p = 44;<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">This code won’t compile,
            and reports an error:<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">error: constexpr
            function never produces a constant expression
            [-Winvalid-constexpr]<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">note: assignment to
            dereferenced null pointer is not allowed in a constant
            expression<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">So, in this sense, the
            abstract machine (aka. the analyzer) should recognize this
            null dereference IMO.<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">That way it would be
            consistent with the users expectation, also with the store
            (lvalue) case and with the unique_ptr case.<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">Balazs<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
        <div>
          <div style="border:none;border-top:solid #E1E1E1
            1.0pt;padding:3.0pt 0cm 0cm 0cm">
            <p class="MsoNormal"><b><span
                  style="mso-fareast-language:HU" lang="EN-US">From:</span></b><span
                style="mso-fareast-language:HU" lang="EN-US"> Harald van
                Dijk <a class="moz-txt-link-rfc2396E" href="mailto:harald@gigawatt.nl"><harald@gigawatt.nl></a> <br>
                <b>Sent:</b> 2021. szeptember 20., hétfő 14:53<br>
                <b>To:</b> <a class="moz-txt-link-abbreviated" href="mailto:benicsbalazs@gmail.com">benicsbalazs@gmail.com</a>;
                <a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
                <b>Subject:</b> Re: [cfe-dev] [analyzer] Questions about
                the null dereference checker<o:p></o:p></span></p>
          </div>
        </div>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p>Hi,<o:p></o:p></p>
        <div>
          <p class="MsoNormal">On 20/09/2021 13:33, via cfe-dev wrote:<o:p></o:p></p>
        </div>
        <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
          <p class="MsoNormal"><span lang="EN-US">Hi,</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">Let’s examine this
              code snippet:</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">  void
              simply_deref_null() {</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">    int *p = 0;</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">    *p ; // no
              warning?</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">    *p = 42; // warns!</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">  }</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">Turns out the
              NullDereference checker treats the two pointer derefs
              differently.</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">For simply reading
              through a null pointer is allowed but storing a value is
              prohibited.</span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
          <p class="MsoNormal"><span lang="EN-US">Why don't we prohibit
              reading through null pointers?</span><o:p></o:p></p>
        </blockquote>
        <p>Reads through null pointers do trigger the warning as well.
          However, there is no read through a null pointer here.
          Dereferencing a pointer produces an lvalue, not an rvalue, and
          discarding an lvalue expression does not cause a load.<o:p></o:p></p>
        <p>If you change the example to, for example,<o:p></o:p></p>
        <pre>int simply_deref_null() {<o:p></o:p></pre>
        <pre>  int *p = 0;<o:p></o:p></pre>
        <pre>  return *p;<o:p></o:p></pre>
        <pre>}<o:p></o:p></pre>
        <p>you will see:<o:p></o:p></p>
        <pre>test.cc:3:10: warning: Dereference of null pointer (loaded from variable 'p') [core.NullDereference]<o:p></o:p></pre>
        <pre>  return *p;<o:p></o:p></pre>
        <pre>         ^~<o:p></o:p></pre>
        <p>Cheers,<br>
          Harald van Dijk<o:p></o:p></p>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
cfe-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>
<a class="moz-txt-link-freetext" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>