The GCC 7 release series differs from previous GCC releases in a number of ways. Some of these are a result of bug fixing, and some old behaviors have been intentionally changed in order to support new standards, or relaxed in standards-conforming ways to facilitate compilation or run-time performance. Some of these changes are not visible to the naked eye and will not cause problems when updating from older versions.
However, some of these changes are user visible and can cause grief when porting to GCC 7. This document is an effort to identify common issues and provide solutions. Let us know if you have suggestions for improvements!
GCC 7 no longer accepts various ill-formed constructs involving the use of templates. The C++ standard says:
14.6/8: "If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required. If the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template, the program is ill-formed; no diagnostic is required."
As a consequence, the following examples are invalid and G++ will either
no longer compile them, or will warn. G++ used to treat
this->member
, where member has
a non-dependent type, as type-dependent and no longer does.
struct C;
struct A {
C fn1();
};
template <typename> class B : A {
void fn2() { fn1().x; }
};
results in
warning: invalid use of incomplete type 'struct C'
struct A {
int x;
};
template <typename> struct B : A {
void fn1() { foo (this->x); }
};
results in
error: there are no arguments to 'foo' that depend on a template parameter, so a declaration of 'foo' must be available
struct A {
void* a;
};
template <typename> class B : A {
void fn1() { this->a[0]; }
};
results in
error: 'void*' is not a pointer-to-object type
because there is no instantiation of that template that can be valid; it
will always dereference a void*
.
GCC 7 changes the name mangling for a conversion operator that returns a type
using the abi_tag
attribute, see
PR 71712.
This affects code that has conversions to std::string
,
for example:
struct A {
operator std::string() const;
};
Code using such conversions might fail to link if some objects are compiled with GCC 7 and some are compiled with older releases.
When compiling as C++11 or later, GCC 7 follows the revised definition of a null pointer constant. This means conversions to pointers from other types of constant (such as character literals and boolean literals) are now rejected.
void* f() {
char* p = '\0';
return false;
}
error: invalid conversion from 'char' to 'char*' [-fpermissive] char* p = '\0'; ^~~~ error: cannot convert 'bool' to 'void*' in return return false; ^~~~~
Such code should be fixed to use a valid null pointer constant such as
0
or nullptr
. Care should be taken when fixing
invalid uses of '\0'
as a pointer, as it may not be clear whether
the intention was to create a null pointer (p = 0;
), to create an
empty string (p = "";
), or to write a null terminator to the
string (*p = '\0';
).
Several C++ Standard Library headers have been changed to no longer include
the <functional>
header.
As such, C++ programs that used components defined in
<functional>
without explicitly including that header
will no longer compile.
Previously components such as std::bind
and std::function
were implicitly defined after including
unrelated headers such as <memory>
,
<future>
, <mutex>
, and
<regex>
.
Correct code should #include <functional>
to define them.
abs
As required by the latest C++ draft, all overloads of the abs
function are declared by including either of
<cstdlib>
or <cmath>
(and correspondingly by either of <stdlib.h>
or
<math.h>
). Previously <cmath>
only
declared the overloads for floating-point types, and
<cstdlib>
only declared the overloads for integral types.
As a result of this change, code which overloads abs
may no longer
compile if the custom overloads conflict with one of the additional overloads
in the standard headers. For example, this will not compile:
#include <stdlib.h>
float abs(float x) { return x < 0 ? -x : x; }
The solution is to use the standard functions, not define conflicting
overloads. For portability to previous versions of GCC and other
implementations the abs(float)
function can be brought into
scope by including <cmath
and adding a using-declaration:
#include <stdlib.h>
#include <cmath> // ensure std::abs(float) is declared
using std::abs;
Additionally, calling
abs
with an argument of unsigned type is now ill-formed after
inclusion of any standard abs
overload.
std::ios_base::failure
When iostream objects are requested to throw exceptions on stream buffer
errors, the type of exception thrown has changed to use the
new libstdc++ ABI
introduced in GCC 5. Code which does
catch (const std::ios::failure&)
or similar will not catch
the exception if it is built using the old ABI. To ensure the exception is
caught either compile the catch handler using the new ABI, or use a handler
of type std::exception
(which will catch the old and new versions
of std::ios_base::failure
) or a handler of type
std::system_error
.
std::function
constructed with std::reference_wrapper
Prior to GCC 7 a std::function
constructed with a
std::reference_wrapper<T>
would unwrap the argument and
store a target of type T
, and target_type()
would
return typeid(T)
. GCC 7 has been changed to match the behavior
of other implementations and not unwrap the argument. This means the target
will be a std::reference_wrapper<T>
and
target_type()
will return
typeid(std::reference_wrapper<T>)
.
Code which depends on the target type may need to be adjusted appropriately.
std::shared_ptr
The behavior of std::shared_ptr<T[]>
and
std::shared_ptr<T[N]>
has changed to match the semantics
in the C++17 draft. Previously specializations of std::shared_ptr
for array types had unhelpful semantics and were hard to use correctly, so the
semantics have changed to match the C++17 behavior in GCC 7. Code which uses
specializations for array types may continue to work in C++11 and C++14 modes,
but not in C++17 mode. It is possible, although unlikely, that some valid uses
of array specializations will no longer work with GCC 7 even in C++11 or C++14
modes. All uses of array specialization should be adjusted to match the C++17
semantics which will be standardized soon. Code which only uses specializations
of std::shared_ptr<T>
for non array-type is unaffected.
Marek Polacek Fedora mass rebuild 2017 on x86_64
Copyright (C) Free Software Foundation, Inc. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.
These pages are maintained by the GCC team. Last modified 2022-10-26.