P2590R2, Explicit lifetime management (PR106658)
This is for "std::start_lifetime_as<T>". If you have not heard of this before, it's the non-UB way to type-pun a pointer into a structured type.Nearly all zero-copy code that deals with external I/O buffers looks something like:
std::unique_ptr<char[]> buffer = stream->read();
if (buffer[0] == FOO)
processFoo(reinterpret_cast<Foo*>(buffer.get())); // undefined behavior
else
processBar(reinterpret_cast<Bar*>(buffer.get())); // undefined behaviour
With this merged, swap the reinterpret_cast for start_lifetime_as and you're no longer being naughty.The "start_lifetime_as" facility does one additional thing beyond providing a tidy standard name for the memory laundering incantation. Semantically it doesn't touch the memory whereas the no-op memmove intrinsically does. In practice, this makes little difference, since the compiler could see that the memmove was a no-op and optimized accordingly.
> Implicitly creates a complete object of type T (whose address is p) and objects nested within it. The value of each created object obj of TriviallyCopyable type U is determined in the same manner as for a call to std::bit_cast<U>(E) except that the storage is not actually accessed, where E is the lvalue of type U denoting obj. Otherwise, the values of such created objects are unspecified.
So T is the complete new object. It contains subobjects, and one of those subobjects has type U. U is initialized as if by bit_cast, and I presume they meant to say that bit_cast casted from the bits already present at the address in question. Since “obj” is mentioned without any definition of any sort, I’ll assume it means something at the correct address.
But what’s E? The page says “E is the lvalue of type U denoting obj,” but obj probably has type char or a similar type, and if it already had type U, there would be no need for bit_cast.
start_lifetime_as is useful when the buffer lifetime is transparent to the compiler and it can mess up aliasing assumptions.
You're allowed to access any type via a char buffer. But the converse is not true (quoting https://eel.is/c++draft/expr#basic.lval-11):
> An object of dynamic type Tobj is type-accessible through a glvalue of type Tref if Tref is similar ([conv.qual]) to: Tobj, a type that is the signed or unsigned type corresponding to Tobj, or a char, unsigned char, or std :: byte type. If a program attempts to access ([defns.access]) the stored value of an object through a glvalue through which it is not type-accessible, the behavior is undefined.
The dynamic type of a char buffer is, well, a char buffer, and can only be accessed via things that are the same type as a char buffer up to signedness and cv-qualification. The actual strict aliasing rules are not commutative!
Up until Java 9, they would release once features were complete. But that meant there were years between the 7 and 8 release and even more years between the 8 and 9 release.
The industry had gotten into the habit of always running old versions of Java (my company was on 6 for an uncomfortable amount of time. But others have had it worse).
More frequent smaller releases has gotten companies more into the habit of updating frequently which also, very helpfully, gives devs new features frequently.
It used to be slower and I've spent way too much time working around C++ bugs in GCC 2.95
(The fact that I remember the problematic version is telling :)
A big difference between the 2 is also the license. GCC uses the GPL while LLVM uses Apache License, hence the projects don't share code.
No
-static-libstdc++ -static-libgcc
?But:
> GCC can now output diagnostics in HTML form via -fdiagnostics-add-output=experimental-html
I wonder what drove the decision to remove JSON output and add HTML output?
Hopefully they fixed those issues. We all need stability and things-to-work.