Porting to GCC 11

The GCC 11 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 11. This document is an effort to identify common issues and provide solutions. Let us know if you have suggestions for improvements!

C++ language issues

Default standard is now GNU++17

GCC 11 defaults to -std=gnu++17 instead of -std=gnu++14: the C++17 standard, plus GNU extensions. This brings several changes that users should be aware of. The following paragraphs describe some of these changes and suggest how to deal with them.

Some users might prefer to stay with gnu++14, in which case we suggest to use the -std=gnu++14 command-line option, perhaps by putting it in CXXFLAGS or similar variables in Makefiles.

Template template parameter matching changes

G++, starting with G++ 7, implements C++17 P0522R0, Matching of template template-arguments excludes compatible templates. As a consequence, the following test is now rejected:


    template <int N, int M = N> class A;
    template <int N, int M> void fn(A<N, M> &) {}
    template <int N, template <int> class TT> void fn(TT<N> &);
    template void fn(A<3> &);

because A is now considered a valid argument for TT, so both function templates are valid candidates, and neither is more specialized than the other, so it's ambiguous.

The new behavior can be disabled independently of other C++17 features with -fno-new-ttp-matching.

Ordered pointer comparison with integer

GCC 11 now issues a diagnostic for ordered comparisons of pointers against constant integers. Commonly this is an ordered comparison against NULL or 0. These should be equality comparisons, not ordered comparisons.

Dynamic Exception Specifications

GCC 11 defaults to C++17 which does not allow dynamic exception specifications.

An exception specification like throw(std::runtime_error) should be removed or replaced with noexcept(false) (meaning the function can throw any type of exception). An exception specification like throw() can be replaced with noexcept or noexcept(true) (meaning the function does not throw exceptions).

Comparison Functions

GCC 11 now enforces that comparison objects be invocable as const.

Header dependency changes

Some C++ Standard Library headers have been changed to no longer include other headers that they do need to depend on. 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 compiled with GCC 11:

Old iostream Members

The deprecated iostream members ios_base::io_state, ios_base::open_mode, ios_base::seek_dir, and basic_streambuf::stossc are not available in C++17 mode. References to those members should be replaced by std::iostate, std::openmode, std::seekdir, and basic_streambuf::sbumpc respectively.

Call of overloaded 'bind(...)' is ambiguous

The placeholders for std::tr1::bind have been changed to use the same placeholder objects as std::bind. This means that following using std::tr1::bind; an unqualified call to bind(f, std::tr1::placeholders::_1) may be ambiguous. This happens because std::tr1::bind is brought into scope by the using-declaration and std::bind is found by Argument-Dependent Lookup due to the type of the _1 placeholder.

To resolve this ambiguity replace unqualified calls to bind with std::tr1::bind or std::bind. Alternatively, change the code to not include the <tr1/functional> header, so that only std::bind is declared.

Enable multithreading to use std::thread

Programs must be linked to libpthread in order for std::thread to create new threads of execution. It is not sufficient to use dlopen to dynamically load libpthread.so at run-time.

Do not undefine __STRICT_ANSI__

The __STRICT_ANSI__ macro is defined by the compiler to inform the C and C++ standard library headers when a strict language dialect is being used, e.g. -std=c++17 or -std=c11 rather than -std=gnu++17 or -std=gnu11.

If you undefine the __STRICT_ANSI__ macro then you create an inconsistent state where the compiler is using a strict dialect but the standard library headers think that GNU extensions are enabled. The libstdc++ headers in GCC 11 cannot be used in this state and are likely to produce compilation errors.

If you don't want the macro to be defined, don't use a -std option that causes it to be defined. Simply use a -std=gnu++NN option instead of -std=c++NN.