<div dir="ltr"><div dir="ltr">On Mon, 22 Aug 2022 at 07:55, David Ledger &lt;<a href="mailto:davidledger@live.com.au">davidledger@live.com.au</a>&gt; wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

  
  <div>
    <p>Well, the dynamic type of the object is unchanging and this
      appears glaring inconsistancy with other static_cast behaviour:<br>
      ```CPP<br>
      consteval void fromp()<br>
      {<br>
          int v = 10;<br>
          auto lambda = [v](int)<br>
          {<br>
              return v + 32;<br>
          };<br>
          void const * ptr = &amp;lambda;<br>
          auto const * reverse = static_cast&lt;decltype(lambda) const
      *&gt;(ptr); // Error: cast from &#39;const void*&#39; is not allowed<br>
      }<br>
      <br>
      void glump()<br>
      {<br>
          int v = 10;<br>
          auto lambda = [v](int)<br>
          {<br>
              return v + 32;<br>
          };<br>
          void const * ptr = &amp;lambda;<br>
          auto const * reverse = static_cast&lt;decltype(lambda) const
      *&gt;(ptr); // Perfectly fine.<br>
      }<br>
      <br>
      int main()<br>
      {<br>
          glump();<br>
          fromp();<br>
      }<br>
      ```<br>
      <br>
      To a non-standardese expert, this behaviour seems unexpected.
      Inverse conversion sequence isn&#39;t changing the dynamic type,
      before dismissing it offhand please consider that type erasure
      through virtual functions is already achieved through constexpr
      virtual calls. This appears just an odd inconcistancy with 5.14.<br></p></div></blockquote><div>I&#39;m sure it&#39;s feasible (and thanks for correcting me about virtual functions); I&#39;m just saying that static_cast from void* to an object&#39;s dynamic type is going to require a paper. The lack of a feature is not grounds for a DR. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p>Regarding impact:<br>
      <br>
      Clang appears to already support this in some special cases,
      making exceptions for calls for allocate and source_location, a
      check for dynamic type can be made with the existing call to
      ComputeDynamicType:<br>
      <br>
      clang/lib/AST/ExprConstant.cpp:8877<br>
      ```CPP<br>
            // 1. We&#39;ll allow it in std::allocator::allocate, and
      anything which that<br>
            //    calls.<br>
            // 2. HACK 2022-03-28: Work around an issue with libstdc++&#39;s<br>
            //    &lt;source_location&gt; header. Fixed in GCC 12 and
      later (2022-04-??).<br>
            //    We&#39;ll allow it in the body of
      std::source_location::current.  GCC&#39;s<br>
            //    implementation had a parameter of type `void*`, and
      casts from<br>
            //    that back to `const __impl*` in its body.<br>
            if (VoidPtrCastMaybeOK &amp;&amp;<br>
                (Info.getStdAllocatorCaller(&quot;allocate&quot;) ||<br>
                
      IsDeclSourceLocationCurrent(Info.CurrentCall-&gt;Callee))) {<br>
              // Permitted.<br>
            } else {<br>
      ```<br>
      <br>
      GCC similarly also has to special case to work around the over
      constrained clause:<br>
      gcc\cp\constexpr.cc:7390<br>
      ```CPP<br>
          /* [expr.const]: a conversion from type cv void* to a
      pointer-to-object<br>
             type cannot be part of a core constant expression as a
      resolution to<br>
             DR 1312.  */<br>
          if (TYPE_PTROB_P(type) &amp;&amp; TYPE_PTR_P(TREE_TYPE(op))
      &amp;&amp; VOID_TYPE_P(TREE_TYPE(TREE_TYPE(op)))<br>
              /* Inside a call to std::construct_at or to<br>
                 std::allocator&lt;T&gt;::{,de}allocate, we permit
      casting from void*<br>
                 because that is compiler-generated code.  */<br>
              &amp;&amp; !is_std_construct_at(ctx-&gt;call) &amp;&amp;
      !is_std_allocator_allocate(ctx-&gt;call))<br>
          {<br>
            /* Likewise, don&#39;t error when casting from void* when OP is<br>
               &amp;heap uninit and similar.  */<br>
            tree sop = tree_strip_nop_conversions(op);<br>
      ```<br>
      GCC also has the ability to evaluate dynamic type, atleast
      according to this comment:<br>
      ```CPP<br>
      auto obj = cxx_eval_constant_expression (ctx, obj, vc_prvalue,
      non_constant_p, overflow_p);<br>
      const tree dynamic_type = TREE_TYPE (obj);<br>
      ```<br>
      For example.</p></div></blockquote><div>Great, hopefully this should smooth the way.</div><div><br></div><div>However, I can see some potential issues; just off the top of my head:</div><div><br></div><div>- doesn&#39;t this allow bypassing access checks on inheritance - cast to void* then to a private first base? Perhaps this should be restricted to casting back to the most derived type?</div><div>- what if there is more than one object with the same type at an address (specifically, if one provides storage for the other) - which object is referenced by the converted pointer?</div><div><br></div><div>Or when you say that the cast should be the &quot;inverse of a standard conversion sequence&quot;, do you mean that the void* pointer should track its provenance and allow only conversions that unwind that provenance? Because I&#39;m not sure that compilers implement that currently.</div><div><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>
    <div>On 22/08/2022 2:21 pm, Edward Catmur
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="auto">
        <div><br>
          <div class="gmail_quote">
            <div dir="ltr" class="gmail_attr">On Mon, 22 Aug 2022, 02:00
              Brian Bi via Std-Proposals, &lt;<a href="mailto:std-proposals@lists.isocpp.org" target="_blank">std-proposals@lists.isocpp.org</a>&gt;
              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 dir="ltr">
                <div dir="ltr"><br>
                </div>
                <br>
                <div class="gmail_quote">
                  <div dir="ltr" class="gmail_attr">On Sun, Aug 21, 2022
                    at 6:06 AM David Ledger via Std-Proposals &lt;<a href="mailto:std-proposals@lists.isocpp.org" rel="noreferrer" target="_blank">std-proposals@lists.isocpp.org</a>&gt;
                    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> Hello W21,<br>
                      <div>
                        <p>The following example shows a static_cast as
                          per [expr.static.cast#7]:<br>
                        </p>
                        <p>```CPP<br>
                          int v = 10;<br>
                          auto lambda = [v](int)<br>
                          {<br>
                              return v + 32;<br>
                          };<br>
                          void * ptr = &amp;lambda;<br>
                          auto * reverse =
                          static_cast&lt;decltype(lambda) *&gt;(ptr);<br>
                          ```</p>
                        <p>In a constant expression, this is invalid
                          because of [expr.const-5.14].</p>
                        <p>However, in this case it is an inverse of a
                          conversion sequence. Since this causes issues
                          when implementing a constexpr
                          `std::function_ref` and similar usages I
                          believe the clause should be modified to the
                          following:<br>
                        </p>
                        <div>&gt; (5.14) a conversion from type cv void*
                          to a pointer-to-object type&lt;ins&gt;<u>,
                            other than when this conversion is the
                            inverse of any standard conversion sequence</u>&lt;/ins&gt;;</div>
                      </div>
                    </div>
                  </blockquote>
                  <div><br>
                  </div>
                  <div>I seem to recall some discussion on the
                    predecessor of this mailing list about
                    implementation difficulty of allowing casts from
                    void* in constant expressions, but I keep failing to
                    find the thread.</div>
                  <div><br>
                  </div>
                  <div>I&#39;m not sure if your proposed restriction makes
                    it any easier to implement. I wish whoever
                    originally posted the post that I&#39;m thinking about
                    would post a reply :)</div>
                </div>
              </div>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Yes, you&#39;re not going to get compile time type
          erasure via function pointers in as a defect report. Even
          virtual functions would be a full on proposal. </div>
        <div dir="auto">
          <div class="gmail_quote">
            <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
  </div>

</blockquote></div></div>

