GCC 16.1 is now available as the first stable release of the new GCC 16 series, a major update to the GNU Compiler Collection with relevant changes for developers working with C, C++, Fortran, Ada, OpenMP, x86-64 architectures, AMD GPUs, LoongArch, Windows and Solaris. This is not a minor revision: the release changes default behaviours, adds experimental support for new languages and architectures, improves vectorisation and updates important parts of the C++ standard library.
The most visible change for many projects will be in C++: GCC 16 now compiles in gnu++20 mode by default, instead of the previous gnu++17. For teams maintaining large codebases, especially projects with older dependencies or very strict build configurations, this change means reviewing scripts, CMake files, Makefiles and CI pipelines. Anyone who wants to keep the previous behaviour will need to set it explicitly with options such as -std=gnu++17 or -std=c++17.
A major step for C++ and its standard library
Making C++20 the default is an important decision. C++20 is no longer a distant promise inside GCC, but the starting point for C++ compilation when the developer does not specify otherwise. This may improve the experience in modern projects, but it can also expose errors, incompatibilities or old assumptions that previously went unnoticed.
GCC 16 also implements several C++26 features, some of them still experimental. Among the most notable are reflection, contracts, expansion statements, constexpr exceptions, constexpr virtual inheritance and improvements related to structured bindings. Reflection, enabled with -std=c++26 -freflection, is one of the most anticipated features in the community because it could change how metadata, serialisation, bindings, validation and code analysis tools are generated in C++.
There are also advances in C++23, including changes to the scope of lambda trailing return types, explicit lifetime management and the character encoding of diagnostic text. In parallel, C++ error messages are becoming more structured: GCC can now display hierarchical diagnostics, using indentation and bullet points, which is especially useful when errors involve complex templates. Those who prefer the old style can use -fno-diagnostics-show-nesting or -fdiagnostics-plain-output.
The libstdc++ standard library also receives important changes. GCC 16 states that its C++20 implementation is no longer experimental, although it warns of ABI changes in components that were experimental before. This affects areas such as atomic waiting and notification functions, semaphores, std::format, std::partial_ordering, some range adaptors and certain uses of std::variant.
One specific change affects std::variant, whose ABI has been updated to better conform to C++20 and later modes. It may affect class layouts in particular cases where std::variant is the first member and shares a type with an empty base class that has a non-trivial destructor. For projects that need to preserve the old behaviour in C++17, GCC allows _GLIBCXX_USE_VARIANT_CXX17_OLD_ABI to be defined.
std::regex execution has also been rewritten to use a heap-based stack instead of the system stack, avoiding stack overflows when matching large strings. Experimental support for C++23 and C++26 has also been expanded with features such as std::mdspan, std::simd, std::inplace_vector, std::optional<T&>, std::function_ref, std::copyable_function, std::philox_engine and new std::stringstream and std::bitset member functions accepting std::string_view.
More vectorisation, LTO and static analysis
Beyond language support, GCC 16 introduces general optimisation improvements. Vectorisation becomes more flexible when identifying in-loop parallelism in reductions, vectorising loops whose iteration count is unknown and generating more efficient code for loops with early exits. It also adds support for mutual peeling for alignment and alignment peeling for vector-length-agnostic loops using masking.
This matters because much of modern performance depends on the compiler’s ability to exploit vector instructions without forcing the programmer to write intrinsics manually. In numerical workloads, data processing, multimedia, simulation or traditional AI workloads, small improvements in the vectoriser can have a real impact when code is deployed at scale.
Link-Time Optimization also improves. LTO now includes better handling of top-level asm statements through -flto-toplevel-asm-heuristics. Speculative devirtualisation has also been expanded to handle general indirect function calls and to speculate more than one possible target. These are low-level changes, but they matter for large applications where the compiler can extract extra performance by seeing more of the full program.
GCC’s static analyser also moves forward. -fanalyzer is now usable on simple C++ examples, with support for Named Return Value Optimization and initial support for exceptions. The project itself warns that it is still unlikely to be practical for production C++ code because of scaling issues, but the move is significant. Until now, many external static analysis tools have had an advantage in C++; GCC continuing to strengthen its integrated analyser could improve early bug detection in normal builds.
The new -fanalyzer-assume-nothrow option makes it possible to disable the assumption that an external function not marked as nothrow may throw exceptions when -fexceptions is enabled. It is intended for projects where that assumption would generate too many warnings, such as C code compiled with exceptions for interoperability with C++ but where the C APIs in use are unlikely to throw.
OpenMP, OpenACC and new languages in the compiler
GCC 16 also updates its parallel programming support. OpenMP memory management has been improved, especially for allocators with the pinned trait, where the CUDA API can be used if available. This can improve performance when that memory is accessed from Nvidia GPUs. GCC also adds GNU extensions such as ompx_gnu_managed_mem_alloc and ompx_gnu_managed_mem_space, aimed at host memory that is accessible from the device.
Support for OpenMP 5.0, 5.1, 5.2 and 6.0 continues to grow. There is limited support for declare mapper in C and C++, support for uses_allocators, initial support for the iterator modifier in map clauses, support for the begin declare variant directive and new routines such as omp_target_memset and omp_target_memset_async. GCC also starts emitting warnings for deprecated OpenMP directives, clauses and APIs, with options to silence them when needed.
In OpenACC, GCC adds routines such as acc_memcpy_device and acc_memcpy_device_async for C, C++ and Fortran. It also expands support for OpenACC 3.0, 3.3 and 3.4, with relevant changes in Fortran.
Ada receives new GNAT extensions, including constructor and destructor mechanisms inspired by object-oriented languages such as C++, Implicit with, structural generic instantiation and the Extended_Access aspect for certain array access types. The semantic analysis of Ada 2022 reduction expressions has also been improved, Ada.Containers.Bounded_Indefinite_Holders has been added and Android support has been strengthened.
Fortran gains improvements in coarrays using native shared memory on single-node machines, better support for parameterised derived types, support for Fortran 2018 extensions such as IMPORT, REDUCE and the new GENERIC statement, as well as Fortran 2023 trigonometric functions such as sinpi. The new -fexternal-blas64 option is also available, useful for calling external BLAS routines with 64-bit integer arguments in MATMUL.
The historical surprise is Algol 68. GCC 16 now includes an experimental compiler for the language, ga68, which aims to implement the language described by the Revised Report, together with approved errata and some GNU extensions. It will not be a widely used feature, but it reflects GCC’s scope as a compiler collection and as a project for language preservation and experimentation.
New architectures: Zen 6, Nova Lake, LoongArch32 and MI300
On x86-64, GCC 16 adds support for AMD processors based on Zen 6 through -march=znver6. This option enables extensions such as AVX512_BMM, AVX_NE_CONVERT, AVX_IFMA, AVX_VNNI_INT8 and AVX512_FP16 on top of the Zen 5 baseline. For developers compiling software optimised for servers, workstations or HPC workloads, this support makes it possible to prepare binaries better tuned for AMD’s next CPU generation.
Targets are also added for Intel Wildcat Lake and Nova Lake. -march=wildcatlake is based on Panther Lake, while -march=novalake includes extensions such as APX_F, AVX10.1, AVX10.2 and PREFETCHI. At the same time, GCC 16 removes or changes the behaviour of some options related to AVX10 and AMX, so projects with very specific compilation flags should review the porting notes.
On AMD GPUs, OpenMP and OpenACC offloading now drastically reduces the launch overhead of compute regions. Experimental support also arrives for AMD Instinct MI300, gfx942, together with generic architectures such as gfx9-4-generic and the mostly compatible gfx950. The default multilib configuration changes and now requires LLVM 20 or newer assembler and linker tools for the new set.
LoongArch gains support for bit-precise integer types _BitInt(N) and unsigned _BitInt(N), Function Multi-Versioning with target_clones, and support for LoongArch32, including the ilp32d, ilp32f and ilp32s ABIs. For the Chinese hardware ecosystem and for embedded systems based on LoongArch, these changes matter because they broaden the range of code that can be compiled natively.
IBM z Systems also receives _BitInt(N), _Float16, global stack protector support and new options related to the stack canary. Support for -m31 is now deprecated and will be removed in a future release.
More useful diagnostics for tools and CI
GCC 16 dedicates an important part of its changes to diagnostics. The old “json” output for -fdiagnostics-format= has been removed, and the project recommends using SARIF for machine-readable diagnostics. This fits with the growing use of SARIF in analysis tools, CI/CD platforms, code review systems and security dashboards.
GCC can also generate diagnostics in HTML form with -fdiagnostics-add-output=experimental-html. SARIF output now better respects the dump directory, captures nesting of logical locations and adds richer information in fix objects. New values have also been added to represent non-standard control flow, such as throwing and catching exceptions, setjmp and longjmp.
One interesting change is that diagnostics can now be associated with directed graphs. Text sinks ignore them, but SARIF can capture them and the experimental HTML output can render them as SVG using dot. For compiler developers, plugin authors and teams analysing internal transformations, this can be very useful.
GCC also introduces a publish/subscribe framework for plugin authors, with typed messages between senders and receivers. In this release, plugins can subscribe to events related to optimisation passes and to the static analyser. libgdiagnostics adds 37 new entry points, including support for logical locations, directed graphs and message construction through buffers.
What developers should review before migrating
Upgrading to GCC 16.1 will be attractive for projects that want to take advantage of C++20 by default, better diagnostics, new architectures and vectorisation improvements. But it should not be done without testing. The change in the default C++ standard can break builds that depend on gnu++17 behaviour. ABI changes in parts of libstdc++ may require recompiling components, especially when mixing libraries built with different compiler versions.
It is also worth reviewing inherited compiler flags. Some options related to AVX10, AMX and Intel architectures no longer behave in the same way or have been removed. On Solaris, there are incompatible changes, such as int8_t and similar types now becoming signed char to conform to C99, and -pthread no longer predefining _REENTRANT. On Windows, GCC gains support for native TLS if configured with --enable-tls and recent binutils are used.
The removal of the old JSON diagnostics format may also affect internal tools. Teams consuming that output should migrate to SARIF. In modern CI environments, that change can be positive, but it requires adapting parsers, integrations and rules.
GCC 16.1 confirms that the project remains a central piece of free software and of systems toolchains. It compiles C and C++, but also Ada, Fortran, Modula-2, D, Objective-C, Go, Rust through specific parts of the GCC ecosystem, and now experiments with Algol 68. It remains a huge project, maintained by a distributed community, and every major release mixes improvements in performance, compatibility, languages, architectures and tooling.
For those managing Linux distributions, internal toolchains or high-performance build environments, GCC 16 is not just “another version”. It is an update that should be planned, tested and measured. For those writing modern C++, it marks a symbolic shift: C++20 is no longer an advanced option enabled manually, but the new starting point.
Frequently asked questions
What is the main new feature in GCC 16.1?
One of the most visible changes is that C++ now compiles by default in gnu++20 mode instead of gnu++17. There are also improvements in optimisation, diagnostics, OpenMP, OpenACC, Fortran, Ada and support for new architectures.
What should I do if my project still depends on C++17?
You should set the standard explicitly in your build, for example with -std=gnu++17 or -std=c++17, and review the porting notes before updating the compiler in production.
Does GCC 16 add support for new processors?
Yes. It adds support for AMD Zen 6 with -march=znver6, Intel Wildcat Lake and Nova Lake, as well as improvements for LoongArch, AMD GPUs and IBM z Systems.
What happens to GCC’s JSON diagnostics?
The previous JSON format for -fdiagnostics-format= has been removed. Users who need machine-readable diagnostics should migrate to SARIF, which receives several improvements in GCC 16.
