The GCC 13 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 13. This document is an effort to identify common issues and provide solutions. Let us know if you have suggestions for improvements!
Some C++ Standard Library headers have been changed to no longer include other headers that were being used internally by the library. As such, C++ programs that used standard library components without including the right headers will no longer compile.
The following headers are used less widely in libstdc++ and may need to be included explicitly when compiling with GCC 13:
<string>
(for std::string
, std::to_string
,
std::stoi
etc.)
<system_error>
(for std::error_code
, std::error_category
,
std::system_error
).
<cstdint>
(for std::int8_t
, std::int32_t
etc.)
<cstdio>
(for std::printf
, std::fopen
etc.)
<cstdlib>
(for std::strtol
, std::malloc
etc.)
GCC 13 implements C++23 P2266 which simplified the rules for implicit move. As a consequence, valid C++20 code that relies on a returned id-expression's being an lvalue may change behavior or fail to compile in C++23. For example:
decltype(auto) f(int&& x) { return (x); } // returns int&&; previously returned int&
int& g(int&& x) { return x; } // ill-formed; previously well-formed
GCC 13 removed the two-stage overload resolution when performing implicit move, whereby the compiler does two separate overload resolutions: one treating the operand as an rvalue, and then (if that resolution fails) another one treating the operand as an lvalue. In the standard this was introduced in C++11 and implemented in GCC in r251035. In r11-2412, the fallback overload resolution was disabled in C++20 (but not in C++17). Then C++23 P2266 removed the fallback overload resolution, and changed the implicit move rules once again.
The two overload resolutions approach was complicated and quirky, so users should transition to the newer model. This change means that code that previously didn't compile in C++17 will now compile, for example:
struct S1 { S1(S1 &&); };
struct S2 : S1 {};
S1
f (S2 s)
{
return s; // OK, derived-to-base, use S1::S1(S1&&)
}
Conversely, code that used to work in C++17 may not compile anymore.
For example, the following example used to compile in C++11...17 because
we performed two separate overload resolutions: one treating the operand
as an rvalue, and then (if that resolution failed) another one treating
the operand as an lvalue.
struct W {
W();
};
struct F {
F(W&);
F(W&&) = delete;
};
F fn ()
{
W w;
return w; // use w as rvalue -> use of deleted function F::F(W&&)
}
GCC 13 implements excess precision
support, which was implemented just in the C front end before,
in C++. The new behavior is enabled by default in
-std=c++
NN modes and when
FLT_EVAL_METHOD
is 1 or 2 and affects the behavior of
floating point constants and expressions.
E.g. for FLT_EVAL_METHOD
equal to 2 on ia32
#include <stdlib.h>
void foo (void) { if (1.1f + 3.3f != 1.1L + 3.3L) abort (); }
void bar (void) { double d = 4.2; if (d == 4.2) abort (); }
will not abort with standard excess precision, because constants and expressions
in float
or double
are evaluated in precision of
long double
and demoted only on casts or assignments, but will
abort with fast excess precision, where whether something is evaluated in
long double
precision depends on what evaluations are
done in the i387 floating point stack or are spilled from it.
The -fexcess-precision=fast
option can be used to
request the previous behavior.
GCC 13 now checks that allocators used with the standard library
can be "rebound" to allocate memory for a different type,
as required by the allocator requirements in the C++ standard.
If an allocator type Alloc<T>
cannot be correctly rebound to another type Alloc<U>
,
you will get an error like this:
.../bits/alloc_traits.h:70:31: error: static assertion failed: allocator_traits<A>::rebind_alloc<A::value_type> must be A
The assertion checks that rebinding an allocator to its own value type is a
no-op, which will be true if its rebind
member is defined correctly.
If rebinding it to its own value type produces a different type,
then the allocator cannot be used with the standard library.
The most common cause of this error is an allocator type
Alloc<T>
that derives from
std::allocator<T>
but does not provide its own
rebind
member. When the standard library attempts to rebind the
allocator using Alloc<T>::rebind<U>
it finds the
std::allocator<T>::rebind<U>
member from the base
class, and the result is std::allocator<U>
instead of
Alloc<U>
.
The solution is to provide a correct rebind
member as shown
below. A converting constructor must also be provided, so that that an
Alloc<U>
can be constructed from an
Alloc<T>
, and vice versa:
template<class T>
class Alloc
{
Alloc();
template<class U> Alloc(const Alloc<U>);
template<class U> struct rebind { using other = Alloc<U>; };
// ...
};
Since C++20, there is no rebind
member in
std::allocator
, so deriving your own allocator types from
std::allocator
is simpler and does not require the derived
allocator to provide its own rebind
.
For compatibility with previous C++ standards, the member should still be
provided. The converting constructor is still required even in C++20.
GCC 13 includes new optimizations which may change behavior on
integer overflow. Traditional code, like linear congruential
pseudo-random number generators in old programs and relying on a
specific, non-standard behavior may now generate unexpected results.
The option -fsanitize=undefined
can be used to detect
such code at runtime.
It is recommended to use the intrinsic subroutine
RANDOM_NUMBER
for random number generators
or, if the old behavior is desired, to use the -fwrapv
option. Note that this option can impact performance.
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 2023-11-25.