Porting to GCC 15

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

C language issues

C23 by default

GCC 15 changes the default language version for C compilation from -std=gnu17 to -std=gnu23. If your code relies on older versions of the C standard, you will need to either add -std= to your build flags, or port your code to C23. C23 brings the following changes:

Function declarations without parameters

The meaning of function declarations of the form rettype identifier (); such as char *strstr (); changed in C23.

In C17 and earlier, such function declarators specified no information about the number or types of the parameters of the function (C17 6.7.6.3), requiring users to know the correct number of arguments, with each passed argument going through default argument promotion.

In C23 such declarations mean (void) i.e. a function taking no arguments, which can lead to build failures on code that relied on the earlier meaning, such as in this example:


#include <signal.h>
void test()
{
 void (*handler)();
 handler = signal(SIGQUIT, SIG_IGN);
}
<source>: In function 'test':
<source>:6:11: error: assignment to 'void (*)(void)' from incompatible pointer type '__sighandler_t' {aka 'void (*)(int)'} [-Wincompatible-pointer-types]
 6 | handler = signal(SIGQUIT, SIG_IGN);
 | ^
In file included from <source>:1:
/usr/include/signal.h:72:16: note: '__sighandler_t' declared here
 72 | typedef void (*__sighandler_t) (int);
 | ^~~~~~~~~~~~~~

Code such as the above relying on a non-zero number of parameters (such as a single int) can be fixed for C23 by adding the correct parameters to the function declarator, such as via:


 void (*handler)(int);

In other cases the code is simply missing a #include of the correct header, such as with:


 void *malloc();

These can be fixed by including the correct header and removing the non-prototype declaration.

Alternatively you can use -std= to select an earlier version of the C standard.

New keywords

C23 added various new keywords, including bool, true, false, nullptr, and thread_local. Code that uses these for identifiers will need changing. For example typedef int bool; will fail with:


<source>:1:13: error: 'bool' cannot be defined via 'typedef'
 1 | typedef int bool;
 | ^~~~
<source>:1:13: note: 'bool' is a keyword with '-std=c23' onwards
<source>:1:1: warning: useless type name in empty declaration
 1 | typedef int bool;
 | ^~~~~~~

In C99 and later you can use #include <stdbool.h> which provides definitions of bool, true, and false compatible with C23.

Note that the bool type is not the same as int at ABI level, and so care may be needed porting declarations that appear at an ABI boundary (or serialized to the filesystem).

C++ language issues

Note that all GCC releases make improvements to conformance which may reject non-conforming, legacy codebases.

Header dependency changes

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.

In particular, the following headers are used less widely within libstdc++ and may need to be included explicitly when compiling with GCC 15:

Deprecated headers

Some C++ Standard Library headers now produce deprecation warnings when included. The warnings suggest how to adjust the code to avoid the warning, for example all uses of <cstdbool> and <cstdalign> can simply be removed, because they serve no purpose and are unnecessary in C++ programs. Most uses of <ccomplex> can be adjusted to use <complex> instead, and uses of <ctgmath> can use <cmath> and/or <complex>.

C++20 iterator support in std::vector

In GCC 15.1 (and GCC 14.3) std::vector has been extended so that the vector(InputIterator, InputIterator) constructor recognizes iterators that satisfy the C++20 iterator concepts, such as std::random_access_iterator. This can give significant performance improvements for some types of iterator which satisfy the new C++20 concepts but which were only considered to be a Cpp17InputIterator under the rules of C++17 (and earlier standards). However, it can also cause problems for iterator adaptors or iterator facades implemented as templates that wrap another iterator class.

If an adaptor template declares all the possible operators supported for any iterator category (e.g. operator--, operator+, operator[], etc.) but does not constrain those operators to only be present when the wrapped iterator supports them, then the C++20 standard library will incorrectly deduce that the adaptor satisfies the new C++20 iterator concepts. This means the library might attempt to use operator-- on a non-bidirectional iterator, or operator[] on a non-random access iterator, resulting in compilation errors.

Code which encounters these errors should be fixed by constraining the iterator adaptors using concepts (or std::enable_if) so that the operator functions don't appear to be usable unless they will actually compile. For example, the following additions could be used to prevent IteratorAdaptor<Iter> from looking like it supports operator--, operator[], and operator- when Iter doesn't support those:

template<class Iter>
class IteratorAdaptor
{
 Iter m_iter; // The underlying iterator that is being adapted.
public:
 // ...
 IteratorAdaptor& operator--()
(追記) #ifdef __cpp_lib_ranges
 requires std::bidirectional_iterator<Iter>
#endif (追記ここまで)
 { --m_iter; return *this; }
 reference operator[](difference_type n) const
(追記) #ifdef __cpp_lib_ranges
 requires std::random_access_iterator<Iter>
#endif (追記ここまで)
 { return m_iter[n]; }
 friend difference_type operator-(const IteratorAdaptor& lhs, const IteratorAdaptor& rhs)
(追記) #ifdef __cpp_lib_ranges
 requires std::sized_sentinel_for<Iter, Iter>
#endif (追記ここまで)
 { return lhs.m_iter - rhs.m_iter; }
};

For questions related to the use of GCC, please consult these web pages and the GCC manuals. If that fails, the gcc-help@gcc.gnu.org mailing list might help. Comments on these web pages and the development of GCC are welcome on our developer list at gcc@gcc.gnu.org. All of our lists have public archives.

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 2025年05月23日.

AltStyle によって変換されたページ (->オリジナル) /