The GCC 16 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 16. This document is an effort to identify common issues and provide solutions. Let us know if you have suggestions for improvements!
Since GCC 16, -Wunused-but-set-* warning options have been
extended to have multiple levels controlling what kinds of uses disable
the warnings for variables which are otherwise unused. Older versions of GCC
only implemented what has become -Wunused-but-set-variable=1
or -Wunused-but-set-parameter=1, while the new default
for -Wunused-but-set-variable or
-Wunused-but-set-parameter is =3 (the new defaults
are also used when these warnings are enabled by
-Wall or -Wextra, respectively).
=2 ignores pre/post inc/decrements on the variable,
=3 also ignores compound assignments if the LHS variable
is not also used on the RHS.
void foo (void) {
int a = 1; // -Wunused-variable warning
int b = 0; // Warning for -Wunused-but-set-variable=n n >= 1
b = 1; b = 2;
int c = 0; // Warning for -Wunused-but-set-variable=n n >= 2
++c; c--; --c; c++;
int d = 0; // Warning for -Wunused-but-set-variable=n n >= 3
d += 4;
int e = 0; // No warning, cast to void
(void) e;
int f = 0; // No warning, f used
int g = f = 5;
(void) g;
int h = 0; // No warning, preincrement result used
int i = ++h;
(void) i;
int j = 0; // No warning, postdecrement result used
int k = j--;
(void) k;
int l = 0; // No warning, l used
int m = l |= 2;
(void) m;
}
In order to avoid the warnings, one can either remove newly diagnosed
variables or parameters which aren't used except in pre/post inc/decrements
or compound assignments, make them used in some way, e.g. just
casting to (void), or lowering the level of the warning.
But note that an unused variable may indicate a coding error, where
some other object was mistakenly used in its place, or a larger change
was begun but left incomplete.
See
-Wunused-but-set-* documentation for more details.
All GCC releases make improvements to conformance which may reject non-conforming, legacy
codebases.
Other issues arise from C++20 becoming the default choice of published
Standard to follow (as might have been overridden with, e.g.,
-std=c++20), and changes in C++20 from previous Standards.
In the transition from C++17 to C++20, several features that had
been deprecated have been removed from the Standard. These are
summarized at the top of
Changes between C++17 and C++20 DIS ["Draft International Standard"].
Note that names removed from C++20 may still appear in headers when
building under -std=c++20, and only provoke 'deprecated'
warnings.
operator!=
In C++20, a type that defines operator== gets an
operator!= provided implicitly by the compiler. This can
cause ambiguities if the type also defines its own operator!=
with an unconventional signature, such as only supporting comparisons
of non-const types (often a mistake, because comparison typically does
not require altering its arguments). This provokes errors like:
error: ambiguous overload for 'operator!=' (operand types are 'daeStringRef' and 'long int')
Fixing argument-type signatures is often the simplest fix, but more complicated cases may require adding or removing overloads.
operator>>
In C++20, the operator>> overload for reading from an
istream into a char* was removed because it
offers no way to prevent buffer overrun when reading into a buffer of
unspecified size. This results in errors like:
error: no match for 'operator>>' (operand types are 'std::istream' {aka 'std::basic_istream<char>'} and 'char*')
A fix is to read into a native array, which uses the bound to prevent
overrun and leaves any extra characters unread, or to read into an
std::string, which grows as needed.
Many failures are caused by a spurious build option -std=gnu++11:
error: 'make_unique' is not a member of 'std'
This is usually a consequence of a bug in Autoconf prior to release 2.73
that adds this option to Makefiles when, acting on a directive
AC_PROG_CXX, it tries but fails to verify that GCC 16's
compiler supports C++11 language features by default. To work around that,
remove the AC_PROG_CXX directive from the program's
configure.ac file and regenerate the makefiles.
C++20 defines new keywords such as concept and requires,
which can no longer be used as identifiers:
error: expected identifier before 'concept'
The only solutions are to change the name of the identifier,
or build to an older standard with (e.g.) -std=c++17.
this'
C++20 deprecates implicitly capturing the value of the meta-variable
this in saved lambda state, provoking warnings if member
names from the surrounding context are used in the lambda body:
warning: implicit capture of 'this' via '[=]' is deprecated in C++20
These can be resolved by adding this or *this,
as appropriate, to the capture list, such as by [=,this].
In C++20, u8"str" and u8'c' literals changed
from type char to type char8_t, leading to
errors like:
error: invalid conversion from 'const char8_t*' to 'const char*' [-fpermissive]
The fix is most commonly a cast from the u8
literal to plain char or char const*.
Programs sometimes use names without having properly #included the header that declares them, relying instead on the name having being declared incidentally via some other header; until it no longer does, resulting in errors like:
error: 'uint64_t' was not declared in this scope
These are fixed by identifying which header declares the name, and including that. The compiler may suggest the header to include.
destroy
In C++20, many deprecated member functions and member typedefs of
std::allocator were removed because
std::allocator_traits has since C++11 provided better
defaults for those members that should be used instead. This applies
to former members
pointer,
const_pointer,
reference,
const_reference,
construct,
destroy,
rebind,
is_always_equal, and
max_size.
The solution is to use (e.g.) std::allocator_traits<A>::destroy
in place of A::destroy.
int8_t, int_fast8_t,
and int_least8_t types are defined as char
on Solaris. While this sort of works because char is
signed, it violates C99, 7.18.1.1, Exact-width integer types. This
requires int8_t etc. to be signed integer types,
which char is not. This standards violation repeatedly
caused compile or run-time failures with C++ code, so GCC 16
changes these types in a private copy of
the <sys/int_types.h> header. Unfortunately, this
is an incompatible, ABI-breaking change, but considered rare enough
for the benefit to outweigh the cost. This changes the mangling of
C++ functions taking int8_t arguments, resulting in link
failures. To avoid this, it's best to recompile affected code bases
with GCC 16. If this is not possible, the traditional types can
be restored by predefining _LEGACY_INT8_T. This is also
necessary when linking with code created by either the
Studio CC compiler with the
non-default -std=c++03, c++11,
or c++14 options or clang++, which still
use the definitions from the unpatched Solaris headers.-pthread and -pthreads options used to
link with libpthread and define the preprocessor
symbols _REENTRANT and
_PTHREADS. However, in
Solaris 10 libpthread has been folded into the
Solaris C library. In Solaris 11.4 _REENTRANT is
no longer used in system headers while _PTHREADS has
long been unused, so both options are now silently ignored. In the
rare cases that user code references them for its own purposes, it
has to define those symbols themselves. Background information can
be found
on Goodbye
(And Good Riddance) to -mt -and -D_REENTRANT.GCC's diagnostic machinery has been substantially cleaned up in GCC 16.
Most of the implementation has been moved to a new
gcc/diagnostics/ subdirectory and diagnostics::
namespace, with many fields becoming private. This should
not affect plugins that use just the diagnostic-core.h API,
but plugins making more sophisticated uses of diagnostics may need
updating. The following tables list the types that have been renamed
in GCC 16 and the header files that have been moved.
| GCC 15 type | GCC 16 type | Notes |
|---|---|---|
class diagnostic_buffer | class diagnostics::buffer | |
class diagnostic_client_data_hooks | class diagnostics::client_data_hooks | |
class diagnostic_client_plugin_info | class diagnostics::client_plugin_info | |
class diagnostic_column_policy | class diagnostics::column_policy | |
class diagnostic_context | class diagnostics::context | |
struct diagnostic_counters | struct diagnostics::counters | New header: diagnostics/counters.h |
class diagnostic_diagram | class diagnostics::diagram | |
class diagnostic_event | class diagnostics::paths::event | |
class diagnostic_event_id_t | class diagnostics::paths::event_id_t | |
struct diagnostic_info | struct diagnostics::diagnostic_info | Fields have gained m_ prefixes |
class diagnostic_location_print_policy | class diagnostics::location_print_policy | |
class diagnostic_metadata | class diagnostics::metadata | |
class diagnostic_option_classifier | class diagnostics::option_classifier | |
struct diagnostic_option_id | struct diagnostics::option_id | New header: diagnostics/option-id.h |
class diagnostic_option_manager | class diagnostics::option_manager | |
class diagnostic_output_file | class diagnostics::output_file | |
class diagnostic_output_format | class diagnostics::sink | |
class diagnostic_per_format_buffer | class diagnostics::per_sink_buffer | |
struct diagnostic_source_printing_options | struct diagnostics::source_printing_options | |
class diagnostic_source_print_policy | class diagnostics::source_print_policy | |
enum diagnostic_t | enum class diagnostics::kind | |
class diagnostic_text_output_format | class diagnostics::text_sink | |
class diagnostic_thread | class diagnostics::paths::thread | |
typedef diagnostic_thread_id_t | typedef diagnostics::paths::thread_id_t | |
class diagnostic_path | class diagnostics::paths::path | |
class edit_context | class diagnostics::changes::change_set | |
class logical_location | class diagnostics::logical_locations::key | |
enum logical_location_kind | enum diagnostics::logical_locations::kind | |
class logical_location_manager | class diagnostics::logical_locations::manager | |
class sarif_output_format | class diagnostics::sarif_sink | |
class diagnostic_sarif_format_buffer | class diagnostics::sarif_sink_buffer | |
class option_manager | class diagnostics::option_id_manager | New header: diagnostics/option-id-manager.h |
| GCC 15 header | GCC 16 header |
|---|---|
diagnostic-buffer.h | diagnostics/buffering.h |
diagnostic-client-data-hooks.h | diagnostics/client-data-hooks.h |
diagnostic-color.h | diagnostics/color.h |
diagnostic.def | diagnostics/kind.def |
diagnostic-diagram.h | diagnostics/diagram.h |
diagnostic-format-html.h | diagnostics/html-sink.h |
diagnostic-format-sarif.h | diagnostics/sarif-sink.h |
diagnostic-format-text.h | diagnostics/text-sink.h |
diagnostic-label-effects.h | diagnostics/source-printing-effects.h |
diagnostic-macro-unwinding.h | diagnostics/macro-unwinding.h |
diagnostic-metadata.h | diagnostics/metadata.h |
diagnostic-output-file.h | diagnostics/output-file.h |
diagnostic-path.h | diagnostics/paths.h |
diagnostic-url.h | diagnostics/url.h |
edit-context.h | diagnostics/changes.h |
File cache types of input.h | diagnostics/file-cache.h |
logical-locations.h | diagnostics/logical-locations.h |