<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-08-11 13:47 GMT+02:00 Jens Maurer <span dir="ltr"><<a href="mailto:Jens.Maurer@gmx.net" target="_blank">Jens.Maurer@gmx.net</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">On 08/11/2017 09:58 AM, Andrzej Krzemienski wrote:<br>
> Hi SG12 Members,<br>
><br>
</span>> I already asked this question in ISO C++ Standard - Discussion (<a href="https://groups.google.com/a/isocpp.org/forum/?fromgroups=#%21topic/std-discussion/UbROFU6Fs0E" rel="noreferrer" target="_blank">https://groups.google.com/a/<wbr>isocpp.org/forum/?fromgroups=#<wbr>!topic/std-discussion/<wbr>UbROFU6Fs0E</a> <<a href="https://groups.google.com/a/isocpp.org/forum/?fromgroups=#%21topic/std-discussion/UbROFU6Fs0E" rel="noreferrer" target="_blank">https://groups.google.com/a/<wbr>isocpp.org/forum/?fromgroups=#<wbr>%21topic/std-discussion/<wbr>UbROFU6Fs0E</a>>), but maybe this list is better suited.<br>
<span class="gmail-">><br>
> UB-sanitizer reports a runtime error for the following program:<br>
><br>
> ```<br>
> struct B;<br>
><br>
> struct I {<br>
> virtual void f() {}; // <- virtual<br>
> };<br>
><br>
> struct A : I {<br>
> A();<br>
> };<br>
><br>
> struct B : A {<br>
> };<br>
><br>
> A::A() { *static_cast<B*>(this); } // <- UB in static_cast<br>
><br>
> int main()<br>
> {<br>
> B{};<br>
> }<br>
> ```<br>
><br>
> My question: is UB-sanitizer correct? Is this a UB according to the standard? And if so, could you point me to the relevant sections?<br>
<br>
</span>The dereference here is immaterial; it just converts a pointer to an lvalue,<br>
neither of which accesses the pointed-to value per se.<br>
<br>
The conversion happens while A and B are being constructed, and we have<br>
special rules in 15.7 [class.cdtor] for that. Of particular interest<br>
is p2, which discusses conversions from B* to A*, but 8.2.9 [expr.static.cast]<br>
indirectly refers to that case when discussing the A* to B* case.<br>
<br>
Both the construction of B and A have started at the point in question,<br>
so it seems to me the pointer conversion is, in fact, valid.<br></blockquote><div><br></div><div>Thanks for your analysis. Interestingly, I have now arrived at the opposite conclusion, based on [expr.static.cast]/p11 and [class.dtor]/p16, and some interpolation of my own. Let me share my reasoning, and tell me what you make of it.<br><br>[class.cdtor]/p2 talks about the upcast, so I would rather go with [expr.static.cast]/p11 which talks about the downcast. The latter says the downcast is UB-free if the casted-from object O is casted to an object that contains O as its subobject. Term "object" implies a relation to run-time (life-time), there is just the question whether we mean "object lifetime (after non-delegating constructor finishes and before the destructor starts) or the "extended object time" (after constructor starts and before destructor finishes).<br><br></div><div>Now, [class.dtor]/p16 says, "Once a destructor is invoked for an object, the object no longer exists". This "exists" I find applicable to the definition of class.cdtor]/p2. If we were considering the same downcast in the *destructor* of A, I would have a clear answer. Now, there is no similar statement when the object starts to "exist", but by analogy to destructor, I would conclude that it starts to exist when the constructor finises. Untill then, there is no object B in existence and therefore the the static_cast condition that "the casted-from object O is casted to an object that contains O as its subobject" is not satisfied.<br><br></div><div>Is the above reasoning correct?<br><br></div><div>Regards,<br></div><div>&rzej;<br></div><div><br></div></div><br></div></div>