<div dir="auto"><div><div class="gmail_extra"><div class="gmail_quote">On 17 Aug 2017 4:24 am, "Kenneth Camann via cfe-dev" <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-size:12.8px">Hi all,</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">I found some cases where clang accepts some invalid code. To give some context, here is what I was trying to do:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Given a pointer to a member subobject that I know lives inside an object of class type `S`, I would like to get a pointer to the enclosing `S` in a constexpr function. This seems like a reasonable thing to want to do, but I could not think of a way to do it that is standard-conforming, and the ways I did think of have the problems described below.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">clang currently allows expressions in constexpr contexts that are explicitly excluded from being core constantant expressions in [expr.const] item (2.13) -- i.e., "a conversion from type cv void * to a pointer-to-object type" cannot be a core constant expression.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">gcc allows these too, and is actually far more liberal in what it accepts (it will accept a reinterpret_cast in a constexpr function). They track this as a bug although some code in libstdc++ apparently relies on it: <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49171" target="_blank">https://gcc.gnu.org/<wbr>bugzilla/show_bug.cgi?id=49171</a></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">It seems that clang never allows a reinterpret_cast in constexpr function, but sometimes accepts a sneaky equivalent, i.e. this trick:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">static_cast<char *>(static_cast<void *>(&x)) [and then back again]</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">But whether it accepts this or not seems random. The following compiles with clang 4.0:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">struct S {</div><div style="font-size:12.8px">  int a;</div><div style="font-size:12.8px">  int b;</div><div style="font-size:12.8px">};</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">constexpr S *getS(int *pb) { // Note: pb is a pointer to a `b` inside `S`</div><div style="font-size:12.8px">  char *pbC = static_cast<char *>(static_cast<void *>(pb)) -</div><div style="font-size:12.8px">      __builtin_offsetof(S, b);</div><div style="font-size:12.8px">  return static_cast<S *>(static_cast<void *>(pbC));</div><div style="font-size:12.8px">};</div></div></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">Did you try actually calling getS in a context that requires a constant expression? The "constexpr function never produces a constant expression" diagnostic is strictly best-effort.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-size:12.8px">But the following does not compile:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">constexpr S *getS(int *pb) {</div><div style="font-size:12.8px">  int S::*memb = &S::b;</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">  // Try to do something like the offsetof stuff above,</div><div style="font-size:12.8px">  // but by deriving the offset from a member pointer</div><div style="font-size:12.8px">  const auto pdiff = static_cast<char *>(static_cast<void *>(</div><div style="font-size:12.8px">    &(static_cast(nullptr)->*memb)<wbr>)) - static_cast<char *>(nullptr);</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">  char *pbC = static_cast<char *>(static_cast<void *>(pb)) - pdiff;</div><div style="font-size:12.8px">  return static_cast<S *>(static_cast<void *>(pbC));</div><div style="font-size:12.8px">}</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">> error: constexpr function never produces a constant expression</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">> note: cast from 'void *' is not allowed in a constant expression</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">I could probably dig through libclangSema to find out why this is, but what I'm after is a bit more high level:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">1) Like the gcc guys, is there some reason (maybe specifically related to offsetof magic?) that you want to accept certain forms of this trick, or do you consider it a bug? I'm willing to rely on UB, but not a bug.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">2) There was a proposal I found on github to allow "limited reinterpret_cast" in constexpr (<a href="http://apolukhin.github.io/constexpr_algorithms/reinterpret.html" target="_blank">http://apolukhin.github.io/co<wbr>nstexpr_algorithms/reinterpret<wbr>.html</a>) but it was never mailed out. Since many you of are involved with WG21: is this an issue anyone is interesting in pursuing, i.e., ""reasonable" limited use of casting for doing simple pointer math against the structure layout?</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Thanks for your help,</div><div style="font-size:12.8px">Ken</div></div>
<br>______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div></div>