The GCC 8 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 to support new standards, or relaxed in standards-conforming ways to facilitate compilation or run-time performance.
Some of these changes are user visible and can cause grief when porting to GCC 8. This document is an effort to identify common issues and provide solutions. Let us know if you have suggestions for improvements!
-Wreturn-type
is enabled by default
G++ now assumes that control never reaches the end of a non-void function
(i.e. without reaching a return
statement). This means that
you should always pay attention to -Wreturn-type
warnings,
as they indicate code that can misbehave when optimized.
To tell the compiler that control can never reach the end of a function
(e.g. because all callers enforce its preconditions) you can suppress
-Wreturn-type
warnings by adding
__builtin_unreachable
:
char signchar(int i) // precondition: i != 0
{
if (i > 0)
return '+';
else if (i < 0)
return '-';
__builtin_unreachable();
}
Because -Wreturn-type
is now enabled by default, G++ will
warn if main
is declared with an implicit int
return type (which is non-standard but allowed by GCC). To avoid the
warning simply add a return type to main
, which makes the
code more portable anyway.
G++ now diagnoses even more cases of ill-formed templates which can never
be instantiated (in addition to
the stricter
rules in GCC 7).
The following example will now be diagnosed by G++ because the type of
B<T>::a
does not depend on T
and so the
function B<T>::f
is ill-formed for every possible
instantiation of the template:
class A { };
template <typename T> struct B {
bool f() const { return a; }
A a;
};
In member function 'bool B<T>::f() const': error: cannot convert 'const A' to 'bool' in return bool f() const { return a; } ^
Ill-formed template code that has never been tested and can never be instantiated should be fixed or removed.
alignof
results
The alignof
operator has been changed to return the minimum
alignment required by the target ABI, instead of the preferred alignment
(consistent with _Alignof
in C).
Previously the following assertions could fail on 32-bit x86 but will now
pass. GCC's preferred alignment for standalone variables of type
double
or long long
is 8 bytes, but the minimum
alignment required by the ABI (and so used for non-static data members)
is 4 bytes:
struct D { double val; };
static_assert(alignof(D) == alignof(double), "...");
struct L { long long val; };
static_assert(alignof(L) == alignof(long long), "...");
Code which uses alignof
to obtain the preferred
alignment can use __alignof__
instead.
The associative containers (std::map
,
std::multimap
, std::set
, and
std::multiset
) now use static assertions to check that their
comparison functions support the necessary operations.
In C++17 mode this includes enforcing that the function can be called
when const
-qualified:
struct Cmp {
bool operator()(int l, int r) /* not const */ { return l < r; }
};
std::set<int, Cmp> s;
In member function 'bool B<T>::f() const': error: static assertion failed: comparison object must be invocable as const static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool f() const { return a; } ^
This can be fixed by adding const
to the call operator:
struct Cmp {
bool operator()(int l, int r) const { return l < r; }
};
The library ABI version has been increased, necessitating a recompilation of all Fortran code.
Character lengths are now handled as
an INTEGER(kind=C_SIZE_T)
variable whose size is
dependent on the target system, allowing characters longer than
2**31 on 64-bit targets. Prior to GCC 8, the character length was
an INTEGER(kind=4)
variable on all targets. If calling
a Fortran procedure with character arguments from C (or vice versa)
without using the standard ISO_C_BINDING feature, the hidden
character length argument at the end of the argument list must thus
be modified to be of type size_t
rather than of
type int
. For instance, calling the Fortran subroutine
subroutine foo (s, a)
character(len=*) :: s
integer :: a
! Code here
end subroutine foo
from C in a way that is compatible with older GFortran versions can be done by defining the prototype as follows:
#if __GNUC__ > 7
typedef size_t fortran_charlen_t;
#else
typedef int fortran_charlen_t;
#endif
void foo_ (char*, int*, fortran_charlen_t);
Versions of gfortran prior to 8.1 wrongly accepted CHARACTER variables with a length type parameter other than one as C interoperable. For example, the code
module mod
use iso_c_binding
type, bind(C) :: a
character(len=2,kind=c_char) :: b ! Wrong
end type a
character(len=2), bind(C) :: c ! Also wrong
end module mod
was accepted. To achieve similar functionality, an array of LEN=1 characters can be used, for example
module mod
use iso_c_binding
type, bind(C) :: a
character(kind=c_char) :: b(2)
end type a
character(kind=c_char), bind(C) :: c(2)
end module mod
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.