GCC 6.3 maintains a C++ compiler with stricter lifetime assumptions
GCC 6.3 fixes regressions on an established compiler branch. The branch's C++ porting guidance explains why object construction and language mode remain important when interpreting compiler changes.
Zeroing storage before a C++ constructor runs does not necessarily initialize the object that constructor creates. GCC 6's porting guide uses a custom allocation function to show why stores made before an object's lifetime can disappear under optimization. That is useful context for GCC 6.3, a maintenance release of the compiler that applies those rules. Its corrections concern the translator itself, while the porting questions concern what the source program is entitled to assume.
The release history dates GCC 6.3 to December 21. Jakub Jelinek's announcement describes important fixes for regressions and serious bugs in 6.2, with more than 79 bugs fixed since the previous release. It does not present 6.3 as a new C++ language revision or attribute the whole branch's feature list to this maintenance update.
I value C++'s ability to express resource lifetime through construction and destruction. Its difficulty is that the lifetime model also controls what the optimizer may discard. A program can look reasonable as a sequence of writes to addresses while failing to initialize the object whose value it later reads.
Construction establishes the object lifetime
The GCC 6 porting guide describes more aggressive lifetime-based dead-store elimination. Its example fills memory in a custom operator new, then runs an empty constructor and reads an integer member. The earlier fill is not an initializer for that member under the object-lifetime reasoning described in the guide.
The documented repair is to put required initialization in the constructor. A simple form makes the relevant relationship explicit without depending on the state of freshly allocated storage.
struct counter {
counter() : value(0) {}
int value;
};
The initializer states the object's value as part of construction. It does not rely on an allocation routine having previously filled bytes that happen to occupy the same address. That is the distinction the guide asks programs to preserve.
This optimization belongs to the GCC 6 branch, not a feature newly introduced by 6.3. The maintenance release matters because the same compiler implementation can have regressions while also correctly exposing application errors. Those cases need different explanations. A corrected compiler bug and a source change that removes an invalid lifetime assumption are not interchangeable remedies.
The default language mode exposes older assumptions
GCC 6 also changes its default C++ mode to gnu++14, as the series changes record. A build without an explicit language flag can therefore encounter rules that differ from the older default. The porting guide groups several resulting failures, making the language-mode change a concrete part of understanding the branch.
One example concerns destructors. Under the newer rules, a destructor normally has an implicit non-throwing specification unless the relevant base or member destructor changes that property. A throw that leaves such a destructor terminates the program. The guide describes a warning for a throw expression that immediately produces that result.
Another example concerns stream conversion. Code that returns a stream directly from a function returning bool can need an explicit conversion, while a condition can test the stream directly. Those contexts use different conversion rules. A compiler rejection can therefore reveal a source assumption about the old stream interface rather than a regression in the maintenance release.
An explicit -std option records which language mode the build intends to use. That separates choosing newer semantics from merely accepting a compiler's default. It also gives a diagnostic a defined language context when comparing the behavior of two compiler installations.
Headers and optimizer facts remain part of compatibility
The porting guide also documents reduced incidental includes from <algorithm>. A source file using a component from another standard header must include that header itself. Depending on a transitive include makes the program's declarations depend on library implementation details that the branch has changed.
GCC 6's optimizer assumes that a C++ member function's this pointer is nonnull. The guide warns that checks inside a member function cannot make a call through a null pointer valid. Removing such a check can expose an invalid call path even when the source appears to contain a defensive branch.
These examples explain why maintenance of a C++ compiler affects more than acceptance of syntax. The compiler translates object lifetimes and language rules into assumptions used by later passes. Diagnostic improvements can identify some violations, while regression fixes address defects in the implementation of translation itself.
I prefer reading GCC 6.3 as a specific set of compiler corrections within that established environment. Jelinek's announcement establishes the maintenance purpose and bug-fix scope. The branch's porting guide explains the source-level obligations that remain, including constructor initialization and explicit header dependencies. Keeping those accounts separate makes it possible to assess a changed build without attributing every new diagnostic or runtime difference to a newly introduced language rule.