<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@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:"Calisto MT";
        panose-1:2 4 6 3 5 5 5 3 3 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p
        {mso-style-priority:99;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calisto MT","serif";
        color:#7030A0;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
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]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-family:"Calisto MT","serif";color:#7030A0">I suspect I would have to strongly disagree with the model put forward. Even if we attempted to make C++ look more like C, I don’t see anything that would make p->i = 0; starts
the lifetime of a D object.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calisto MT","serif";color:#7030A0"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calisto MT","serif";color:#7030A0">It has been the very foundation of C++ since day 1 that an object’s lifetime starts after its constructors ends and ends right before its destructor starts. Then, there was a
little special case made for C. In my view, the way to resolve these questions isn’t to make C++ look more like C; it is to make the exceptions closer to the founding principle.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calisto MT","serif";color:#7030A0"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calisto MT","serif";color:#7030A0">-- Gaby<o:p></o:p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style="font-family:"Calisto MT","serif";color:#7030A0"><o:p> </o:p></span></a></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt">
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif"">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif""> ub-bounces@open-std.org [mailto:ub-bounces@open-std.org]
<b>On Behalf Of </b>Richard Smith<br>
<b>Sent:</b> Wednesday, January 15, 2014 3:09 PM<br>
<b>To:</b> WG21 UB study group<br>
<b>Subject:</b> Re: [ub] type punning through congruent base class?<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<div>
<p class="MsoNormal">On Wed, Jan 15, 2014 at 1:48 PM, Herb Sutter <<a href="mailto:hsutter@microsoft.com" target="_blank">hsutter@microsoft.com</a>> wrote:<o:p></o:p></p>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div name="divtagdefaultwrapper">
<p><span style="font-family:"Calibri","sans-serif"">Richard, I'm not sure I understand your position... Given the following complete program ...<o:p></o:p></span></p>
<p><span style="font-family:"Calibri","sans-serif""><o:p> </o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> struct B { int i; };<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> struct D : B { };<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> int main() {<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> B b; // line X<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> }<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif""><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif"">... are you actually saying that line X starts the lifetime of an object of type D? or just setting up a strawman? (Sorry, I really couldn't tell.)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif""><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif"">If yes, then given the following complete program ...<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif""><o:p> </o:p></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> struct C { long long i; };<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> int main() {<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> C c; // line Y<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> }<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
</div>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif"">... are you saying that line Y could start the lifetime of an object of type D (which is not mentioned in the code), double, shared_ptr<widget>, or any other type than C, as long as the size
of that other type is the same or less than sizeof(C)?<o:p></o:p></span></p>
</div>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I think my position is more nuanced. There are a set of cases that I think people expect to have defined behavior, and the standard does not currently distinguish those cases from your cases above, as far as I can tell -- if using malloc
to create an object "with trivial initialization" is acceptable, then it appears that *any* way of producing the appropriately-sized-and-aligned storage is acceptable.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I would expect that that we would have consensus that the lifetime of an object of type D *should* start at some point in this code (and more specifically that the code has defined behavior):<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"> B *p = (B*)malloc(sizeof(B));<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"> p->i = 0;<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I would expect to also have consensus that the same is true here:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"> alignof(B) char buffer[sizeof(B)];<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"> B *p = (B*)buffer;<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"> p->i = 0;<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">(These expectations are based on the vast amount of existing code that relies upon these behaviors, not on the wording of the standard.)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">So, that's "what people probably expect". Next, "what the standard says". Consider 3.8/1:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">"The lifetime of an object of type T begins when:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">— storage with the proper alignment and size for type T is obtained, and<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">— if the object has non-trivial initialization, its initialization is complete."<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">This requires us to answer three questions: (1) is there an object of type B in the above snippets, (2) when is storage for it obtained, and (3) does it have non-trivial initialization? It seems that "yes, before the storage is used as
an object of type B, no" is a self-consistent set of answers, and one that gives the program defined behavior. There are also sets of answers that give the program undefined behavior, and the standard doesn't give us direction in how we might pick a set of
answers to these questions.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">There seem to be two obvious ways forward: either (a) if we can pick answers to these questions such that the program has defined behavior, then the program has defined behavior, or (b) if we can pick answers to these questions such that
the program has undefined behavior, then the program has undefined behavior.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">If we want to align "what people probably expect" with "what the standard says", it seems we need to either change the above rule, or accept interpretation (a), under which the program above is valid, as is any other program where 'buffer'
obtains storage of the appropriate size and alignment for an object of type D. (Option (a) also matches the behavior of current optimizing compilers, as far as I'm aware.)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I've spent quite some time thinking about and discussing this problem and related issues (such as, under what circumstances does a pointer point to an object, when do two pointers alias, ...), and I personally think that the best approach
here is to embrace option (a) above: if there exist a consistent set of choices of object lifetimes such that the program has defined behavior, then the program has the behavior implied by that set. (I have a sketch proof that such behavior is the same for
*every* such consistent set, aside from deviations caused by unspecified values and other pre-existing sources of nondeterminism.) In essence, the implication of this is that objects' lifetimes would start just in time to avoid undefined behavior.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Put another way, yes, I personally think this code should have defined behavior:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">C c; // #1<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">static_assert(sizeof(C) >= sizeof(D) && alignof(C) >= alignof(D), "");<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">D *p = (D*)&c;<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">d->i = 0; // #2<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">... and the lifetime of a D object at address &c should start at some point between lines #1 and #2. (Naturally, the lifetime of the C object ended before this happened.) Moreover, this is something that plenty of existing C++ code relies
on.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div name="divtagdefaultwrapper">
<div>
<div>
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:black">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:black">
<a href="mailto:ub-bounces@open-std.org" target="_blank">ub-bounces@open-std.org</a> <<a href="mailto:ub-bounces@open-std.org" target="_blank">ub-bounces@open-std.org</a>> on behalf of Richard Smith <<a href="mailto:richardsmith@google.com" target="_blank">richardsmith@google.com</a>><br>
<b>Sent:</b> Monday, January 6, 2014 3:44 PM<o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:black"><br>
<b>To:</b> WG21 UB study group<br>
<b>Subject:</b> Re: [ub] type punning through congruent base class?<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> <o:p></o:p></span></p>
</div>
</div>
<div>
<div>
<div>
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">On Mon, Jan 6, 2014 at 10:22 AM, Jason Merrill <<a href="mailto:jason@redhat.com" target="_blank">jason@redhat.com</a>> wrote:<o:p></o:p></span></p>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-family:"Calibri","sans-serif";color:#282828">On 01/06/2014 04:26 AM, Fabio Fracassi wrote:<br>
> if it is not (legal): could we make it legal or would we run afoul of<br>
> the aliasing rules?<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">The access is not allowed by the aliasing rules in 3.10. But it seems<br>
that this would be:<o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><br>
struct B {<br>
int i;<br>
};<br>
<br>
struct D {<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> B bmem;<br>
void foo() { /* access bmem.i */ }<br>
};<br>
<br>
B b;<br>
reinterpret_cast<D&>(b).foo();<br>
<br>
because B is a non-static data member of D, and 9.2/19 guarantees that<br>
the address of D::bmem is the same as the address of the D object.<o:p></o:p></span></p>
</blockquote>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">How is that fundamentally different? 9.3.1/2 makes that UB too, if 'reinterpret_cast<D&>(b)' does not refer to an object of type 'b'. And within D::foo, the implicit this->bmem
would have the same problem.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">If I might play devil's advocate for a moment...<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> struct B { int i; };<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> struct D : B {<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> void foo();<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> };<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> B b;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">I claim this line starts the lifetime of an object of type D. Per [basic.life]p1, the lifetime of an object of type 'D' begins when storage with the proper alignment and size
for type T is obtained (which "B b" happens to satisfy). The object does not have non-trivial initialization, so the second bullet does not apply.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">(This is the same argument that makes this valid:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> D *p = (D*)malloc(sizeof(D));<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> p->foo();<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">... so any counterargument will need to explain why the two cases are fundamentally different.)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">Then:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"> reinterpret_cast<D&>(b).foo();<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Calibri","sans-serif";color:#282828">... is valid, because the cast produces the same memory address, and that memory address contains an object of type 'D' (as claimed above).<o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><br>
_______________________________________________<br>
ub mailing list<br>
<a href="mailto:ub@isocpp.open-std.org">ub@isocpp.open-std.org</a><br>
<a href="http://www.open-std.org/mailman/listinfo/ub" target="_blank">http://www.open-std.org/mailman/listinfo/ub</a><o:p></o:p></p>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</body>
</html>