On Mon, Nov 03, 2025 at 01:34:28PM -0500, Marek Polacek via Gcc wrote:
> I would like us to declare that C++20 is no longer experimental and
> change the default dialect to gnu++20. Last time we changed the default
> was over 5 years ago in GCC 11:
> <https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=
0801f419440c14f6772b28f763ad7d40f7f7a580>
> and before that in 2015 in GCC 6.1, so this happens roughly every 5 years.
>
> I had been hoping to move to C++20 in GCC 15 (see bug 113920), but at that time
> libstdc++ still had incomplete C++20 support and the compiler had issues to iron
> out (mangling of concepts, modules work, etc.). Are we ready now? Is anyone
> aware of any blockers? Presumably we still wouldn't enable Modules by default.
>
> I'm willing to do the work if we decide that it's time to switch the default
> C++ dialect (that includes updating cxx-status.html and adding a new caveat to
> changes.html).
I haven't seen a patch posted for this, so just that something is posted
during stage1 if we decide to do it, here is a patch.
The patch makes -std=gnu++20 the default C++ dialect and documents that
-fmodules is still not implied by that or -std=c++20 and modules support
is still experimental.
2025-11-26 Jakub Jelinek <jakub@redhat.com>
gcc/
* doc/invoke.texi (gnu++17): Remove comment about the default.
(c++20): Remove note about experimental support, except add a note
that modules are still experimental and need to be enabled separately.
(gnu++20): Likewise. Move here comment about the default.
(fcoroutines): Mention it is enabled by default for C++20 and later.
* doc/standards.texi: Document that the default for C++ is
-std=gnu++20.
gcc/c-family/
* c-opts.cc (c_common_init_options): Call set_std_cxx20 rather than
set_std_cxx17.
* c.opt (std=c++2a): Change description to deprecated option wording.
(std=c++20): Remove experimental support part.
(std=c++2b): Change description to deprecated option wording.
(std=gnu++2a): Likewise.
(std=gnu++20): Remove experimental support part.
(std=gnu++2b): Change description to deprecated option wording.
gcc/testsuite/
* lib/target-supports.exp: Set cxx_default to c++20 rather than
c++17.
* lib/g++-dg.exp (g++-std-flags): Reorder list to put 20 first
and 17 after 26.
* g++.dg/debug/pr80461.C (bar): Use v = v + 1; instead of ++v;.
* g++.dg/debug/pr94459.C: Add -std=gnu++17 to dg-options.
* g++.dg/diagnostic/virtual-constexpr.C: Remove dg-skip-if,
instead use { c++11 && c++17_down } effective target instead of
c++11.
* g++.dg/guality/pr67192.C: Add -std=gnu++17.
* g++.dg/torture/pr84961-1.C: Likewise.
* g++.dg/torture/pr84961-2.C: Likewise.
* g++.dg/torture/pr51482.C (anim_track_bez_wvect::tangent): Cast
key_class to int before multiplying it by float.
* g++.dg/torture/stackalign/unwind-4.C (foo): Use g_a = g_a + 1;
instead of g_a++;.
* g++.dg/tree-prof/partition1.C (bar): Use l = l + 1; return l;
instead of return ++l;.
* obj-c++.dg/exceptions-3.mm: Add -std=gnu++17.
* obj-c++.dg/exceptions-5.mm: Likewise.
libgomp/
* testsuite/libgomp.c++/atomic-12.C (main): Add ()s around array
reference index.
* testsuite/libgomp.c++/atomic-13.C: Likewise.
* testsuite/libgomp.c++/atomic-8.C: Likewise.
* testsuite/libgomp.c++/atomic-9.C: Likewise.
* testsuite/libgomp.c++/loop-6.C: Use count = count + 1;
return count > 0; instead of return ++count > 0;.
* testsuite/libgomp.c++/pr38650.C: Add -std=gnu++17.
* testsuite/libgomp.c++/target-lambda-1.C (merge_data_func):
Use [=,this] instead of just [=] in lambda captures.
* testsuite/libgomp.c-c++-common/target-40.c (f1): Use v += 1;
instead of v++;.
* testsuite/libgomp.c-c++-common/depend-iterator-2.c: Use v = v + 1;
instead of v++.
}
}
- /* Set C++ standard to C++17 if not specified on the command line. */
+ /* Set C++ standard to C++20 if not specified on the command line. */
if (c_dialect_cxx ())
- set_std_cxx17 (/*ISO*/false);
+ set_std_cxx20 (/*ISO*/false);
global_dc->get_source_printing_options ().colorize_source_p = true;
}
std=c++2a
C++ ObjC++ Alias(std=c++20) Undocumented
-Conform to the ISO 2020 C++ standard (experimental and incomplete support).
+Deprecated in favor of -std=c++20.
std=c++20
C++ ObjC++
-Conform to the ISO 2020 C++ standard (experimental and incomplete support).
+Conform to the ISO 2020 C++ standard.
std=c++2b
C++ ObjC++ Alias(std=c++23) Undocumented
-Conform to the ISO 2023 C++ standard (published in 2024; experimental and incomplete support).
+Deprecated in favor of -std=c++23.
std=c++23
C++ ObjC++
std=gnu++2a
C++ ObjC++ Alias(std=gnu++20) Undocumented
-Conform to the ISO 2020 C++ standard with GNU extensions (experimental and incomplete support).
+Deprecated in favor of -std=gnu++20.
std=gnu++20
C++ ObjC++
-Conform to the ISO 2020 C++ standard with GNU extensions (experimental and incomplete support).
+Conform to the ISO 2020 C++ standard with GNU extensions.
std=gnu++2b
C++ ObjC++ Alias(std=gnu++23) Undocumented
-Conform to the ISO 2023 C++ standard with GNU extensions (published in 2024; experimental and incomplete support).
+Deprecated in favor of -std=gnu++23.
std=gnu++23
C++ ObjC++
@item gnu++17
@itemx gnu++1z
GNU dialect of @option{-std=c++17}.
-This is the default for C++ code.
The name @samp{gnu++1z} is deprecated.
@item c++20
@itemx c++2a
The 2020 ISO C++ standard plus amendments.
-Support is experimental, and could change in incompatible ways in
-future releases.
+C++20 modules support is still experimental and needs to be
+enabled with @option{-fmodules} option.
The name @samp{c++2a} is deprecated.
@item gnu++20
@itemx gnu++2a
GNU dialect of @option{-std=c++20}.
-Support is experimental, and could change in incompatible ways in
-future releases.
+This is the default for C++ code.
+C++20 modules support is still experimental and needs to be
+enabled with @option{-fmodules} option.
The name @samp{gnu++2a} is deprecated.
@item c++23
@opindex fcoroutines
@item -fcoroutines
-Enable support for the C++ coroutines extension (experimental).
+Enable support for the C++ coroutines extension. With @option{-std=c++20}
+and above, coroutines are part of the language standard, so
+@option{-fcoroutines} defaults to on.
@opindex fdiagnostics-all-candidates
@item -fdiagnostics-all-candidates
@option{-std=gnu++23} (for C++23 with GNU extensions).
The default, if
-no C++ language dialect options are given, is @option{-std=gnu++17}.
+no C++ language dialect options are given, is @option{-std=gnu++20}.
@section Objective-C and Objective-C++ Languages
@cindex Objective-C
{
O q;
A<P> f = q;
- v++;
+ v = v + 1;
}
void
// PR debug/94459
// { dg-do compile { target c++14 } }
-// { dg-options "-g -dA" }
+// { dg-options "-g -dA -std=gnu++17" }
template <typename T>
struct S
// { dg-options "-fdiagnostics-show-caret -pedantic-errors" }
-// { dg-do compile { target c++11 } }
-// { dg-skip-if "virtual constexpr" { *-*-* } { "-std=gnu++2a" } { "" } }
+// { dg-do compile { target { c++11 && c++17_down } } }
struct S
{
/* PR debug/67192 */
/* { dg-do run } */
-/* { dg-options "-x c++ -g -Wmisleading-indentation" } */
+/* { dg-options "-x c++ -g -Wmisleading-indentation -std=gnu++17" } */
volatile int cnt = 0;
g1.y = (p_p1->y - p_p0->y)*bp1;
g1.z = (p_p1->z - p_p0->z)*bp1;
g1.w = (p_p1->w - p_p0->w)*bp1;
- bp1 = (0.5f + key_class*0.5f*continuity);
+ bp1 = (0.5f + ((int)key_class)*0.5f*continuity);
p_tn->x = (g1.x + g3.x*bp1)*tn1;
p_tn->y = (g1.y + g3.y*bp1)*tn1;
p_tn->z = (g1.z + g3.z*bp1)*tn1;
// PR c++/84961
// { dg-do compile }
+// { dg-options "-std=gnu++17" }
short a;
volatile int b;
// PR c++/84961
// { dg-do compile }
+// { dg-options "-std=gnu++17" }
short a;
volatile int b;
int i;
ALTER_REGS();
for (i=0; i < 10; i++)
- g_a++;
+ g_a = g_a + 1;
throw g_a;
}
#endif
void *p = __builtin_alloca (i);
asm volatile ("" : : "r" (i), "r" (p) : "memory");
if (k) throw 6;
- return ++l;
+ l = l + 1;
+ return l;
}
void foo ()
# The order of this list is significant: first $cxx_default,
# then the oldest and newest, then others in rough order of
# importance based on test coverage and usage.
- foreach ver { 17 98 26 11 20 14 23 } {
+ foreach ver { 20 98 26 17 11 14 23 } {
set cmpver $ver
if { $ver == 98 } { set cmpver 03 }
if { [llength $std_list] < 3
return 0
}
-set cxx_default "c++17"
+set cxx_default "c++20"
# Check whether the current active language standard supports the features
# of C++11/C++14 by checking for the presence of one of the -std flags.
# This assumes that the default for the compiler is $cxx_default, and that
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
-/* { dg-options "-fobjc-exceptions" } */
+/* { dg-options "-fobjc-exceptions -std=gnu++17" } */
/* { dg-do compile } */
// { dg-additional-options "-Wno-objc-root-class" }
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
-/* { dg-options "-fobjc-exceptions" } */
+/* { dg-options "-fobjc-exceptions -std=gnu++17" } */
/* { dg-do compile } */
// { dg-additional-options "-Wno-objc-root-class" }
int v, *p;
p = &x;
#pragma omp atomic update
- p[foo (), 0] = 16 + 6 - p[foo (), 0];
+ p[(foo (), 0)] = 16 + 6 - p[(foo (), 0)];
#pragma omp atomic read
v = x;
if (cnt != 2 || v != 16)
abort ();
#pragma omp atomic capture
- v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3;
+ v = p[(foo () + foo (), 0)] = p[(foo () + foo (), 0)] + 3;
if (cnt != 6 || v != 19)
abort ();
#pragma omp atomic capture
- v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0];
+ v = p[(foo (), 0)] = 12 * 1 / 2 + ((foo (), 0)) + p[(foo (), 0)];
if (cnt != 9 || v != 25)
abort ();
#pragma omp atomic capture
abort ();
#pragma omp atomic capture
{
- v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6;
+ v = p[(foo (), 0)]; p[(foo (), 0)] = (foo (), 7) ? 13 : foo () + 6;
}
if (cnt != 19 || v != 1)
abort ();
T v, *p;
p = &x;
#pragma omp atomic update
- p[foo (), 0] = 16 + 6 - p[foo (), 0];
+ p[(foo (), 0)] = 16 + 6 - p[(foo (), 0)];
#pragma omp atomic read
v = x;
if (cnt != 2 || v != 16)
abort ();
#pragma omp atomic capture
- v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3;
+ v = p[(foo () + foo (), 0)] = p[(foo () + foo (), 0)] + 3;
if (cnt != 6 || v != 19)
abort ();
#pragma omp atomic capture
- v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0];
+ v = p[(foo (), 0)] = 12 * 1 / 2 + ((foo (), 0)) + p[(foo (), 0)];
if (cnt != 9 || v != 25)
abort ();
#pragma omp atomic capture
abort ();
#pragma omp atomic capture
{
- v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6;
+ v = p[(foo (), 0)]; p[(foo (), 0)] = (foo (), 7) ? 13 : foo () + 6;
}
if (cnt != 19 || v != 1)
abort ();
abort ();
p = &x;
#pragma omp atomic update
- p[foo (), 0] = p[foo (), 0] - 16;
+ p[(foo (), 0)] = p[(foo (), 0)] - 16;
#pragma omp atomic read
v = x;
if (cnt != 2 || v != 0)
abort ();
#pragma omp atomic capture
{
- p[foo (), 0] += 6;
- v = p[foo (), 0];
+ p[(foo (), 0)] += 6;
+ v = p[(foo (), 0)];
}
if (cnt != 4 || v != 6)
abort ();
#pragma omp atomic capture
{
- v = p[foo (), 0];
- p[foo (), 0] += 6;
+ v = p[(foo (), 0)];
+ p[(foo (), 0)] += 6;
}
if (cnt != 6 || v != 6)
abort ();
abort ();
#pragma omp atomic capture
{
- p[foo (), 0] = p[foo (), 0] + 6;
- v = p[foo (), 0];
+ p[(foo (), 0)] = p[(foo (), 0)] + 6;
+ v = p[(foo (), 0)];
}
if (cnt != 9 || v != 18)
abort ();
#pragma omp atomic capture
{
- v = p[foo (), 0];
- p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[(foo (), 0)];
+ p[(foo (), 0)] = p[(foo (), 0)] + 6;
}
if (cnt != 12 || v != 18)
abort ();
if (v != 24)
abort ();
#pragma omp atomic capture
- { v = p[foo (), 0]; p[foo (), 0]++; }
+ { v = p[(foo (), 0)]; p[(foo (), 0)]++; }
#pragma omp atomic capture
- { v = p[foo (), 0]; ++p[foo (), 0]; }
+ { v = p[(foo (), 0)]; ++p[(foo (), 0)]; }
#pragma omp atomic capture
- { p[foo (), 0]++; v = p[foo (), 0]; }
+ { p[(foo (), 0)]++; v = p[(foo (), 0)]; }
#pragma omp atomic capture
- { ++p[foo (), 0]; v = p[foo (), 0]; }
+ { ++p[(foo (), 0)]; v = p[(foo (), 0)]; }
if (cnt != 20 || v != 28)
abort ();
#pragma omp atomic capture
- { v = p[foo (), 0]; p[foo (), 0]--; }
+ { v = p[(foo (), 0)]; p[(foo (), 0)]--; }
#pragma omp atomic capture
- { v = p[foo (), 0]; --p[foo (), 0]; }
+ { v = p[(foo (), 0)]; --p[(foo (), 0)]; }
#pragma omp atomic capture
- { p[foo (), 0]--; v = p[foo (), 0]; }
+ { p[(foo (), 0)]--; v = p[(foo (), 0)]; }
#pragma omp atomic capture
- { --p[foo (), 0]; v = p[foo (), 0]; }
+ { --p[(foo (), 0)]; v = p[(foo (), 0)]; }
if (cnt != 28 || v != 24)
abort ();
return 0;
abort ();
p = &x;
#pragma omp atomic update
- p[foo (), 0] = p[foo (), 0] - 16;
+ p[(foo (), 0)] = p[(foo (), 0)] - 16;
#pragma omp atomic read
v = x;
if (cnt != 2 || v != 0)
abort ();
#pragma omp atomic capture
{
- p[foo (), 0] += 6;
- v = p[foo (), 0];
+ p[(foo (), 0)] += 6;
+ v = p[(foo (), 0)];
}
if (cnt != 4 || v != 6)
abort ();
#pragma omp atomic capture
{
- v = p[foo (), 0];
- p[foo (), 0] += 6;
+ v = p[(foo (), 0)];
+ p[(foo (), 0)] += 6;
}
if (cnt != 6 || v != 6)
abort ();
abort ();
#pragma omp atomic capture
{
- p[foo (), 0] = p[foo (), 0] + 6;
- v = p[foo (), 0];
+ p[(foo (), 0)] = p[(foo (), 0)] + 6;
+ v = p[(foo (), 0)];
}
if (cnt != 9 || v != 18)
abort ();
#pragma omp atomic capture
{
- v = p[foo (), 0];
- p[foo (), 0] = p[foo (), 0] + 6;
+ v = p[(foo (), 0)];
+ p[(foo (), 0)] = p[(foo (), 0)] + 6;
}
if (cnt != 12 || v != 18)
abort ();
if (v != 24)
abort ();
#pragma omp atomic capture
- { v = p[foo (), 0]; p[foo (), 0]++; }
+ { v = p[(foo (), 0)]; p[(foo (), 0)]++; }
#pragma omp atomic capture
- { v = p[foo (), 0]; ++p[foo (), 0]; }
+ { v = p[(foo (), 0)]; ++p[(foo (), 0)]; }
#pragma omp atomic capture
- { p[foo (), 0]++; v = p[foo (), 0]; }
+ { p[(foo (), 0)]++; v = p[(foo (), 0)]; }
#pragma omp atomic capture
- { ++p[foo (), 0]; v = p[foo (), 0]; }
+ { ++p[(foo (), 0)]; v = p[(foo (), 0)]; }
if (cnt != 20 || v != 28)
abort ();
#pragma omp atomic capture
- { v = p[foo (), 0]; p[foo (), 0]--; }
+ { v = p[(foo (), 0)]; p[(foo (), 0)]--; }
#pragma omp atomic capture
- { v = p[foo (), 0]; --p[foo (), 0]; }
+ { v = p[(foo (), 0)]; --p[(foo (), 0)]; }
#pragma omp atomic capture
- { p[foo (), 0]--; v = p[foo (), 0]; }
+ { p[(foo (), 0)]--; v = p[(foo (), 0)]; }
#pragma omp atomic capture
- { --p[foo (), 0]; v = p[foo (), 0]; }
+ { --p[(foo (), 0)]; v = p[(foo (), 0)]; }
if (cnt != 28 || v != 24)
abort ();
}
volatile int count;
static int test(void)
{
- return ++count > 0;
+ count = count + 1;
+ return count > 0;
}
int i;
// PR c++/38650
// { dg-do run }
+// { dg-additional-options "-std=gnu++17" }
#include <cstdlib>
auto merge_data_func (int *iptr, int &b)
{
- auto fn = [=](void) -> bool
+ auto fn = [=,this](void) -> bool
{
bool mapped;
uintptr_t hostptr = (uintptr_t) ptr;
foo (int *p, int i)
{
#pragma omp task depend (out: p[0])
- v++;
+ v = v + 1;
#pragma omp task depend (in: p[0])
- v++;
+ v = v + 1;
#pragma omp task depend (inout: p[0])
- v++;
+ v = v + 1;
#pragma omp task depend (mutexinoutset: p[0])
- v++;
+ v = v + 1;
#pragma omp task depend (out: p[0]) depend (in: p[1])
- v++;
+ v = v + 1;
#pragma omp task depend (in: p[0]) depend (inout: p[1])
- v++;
+ v = v + 1;
#pragma omp task depend (inout: p[0]) depend (mutexinoutset: p[1])
- v++;
+ v = v + 1;
#pragma omp task depend (mutexinoutset: p[0]) depend (out: p[1])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , out : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , in : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , inout : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , mutexinoutset : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , out : p[j]) depend (iterator (j=0:2) , in : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , in : p[j]) depend (iterator (j=0:2) , inout : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , inout : p[j]) depend (iterator (j=0:2) , mutexinoutset : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:2) , mutexinoutset : p[j]) depend (iterator (j=0:2) , out : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , out : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , in : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , inout : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , mutexinoutset : p[j])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , out : p[j]) depend (iterator (j=0:i) , in : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , in : p[j]) depend (iterator (j=0:i) , inout : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , inout : p[j]) depend (iterator (j=0:i) , mutexinoutset : p[j + 2])
- v++;
+ v = v + 1;
#pragma omp task depend (iterator (j=0:i) , mutexinoutset : p[j]) depend (iterator (j=0:i) , out : p[j + 2])
- v++;
+ v = v + 1;
}
int
#pragma omp declare target to (v)
typedef void (*fnp1) (void);
typedef fnp1 (*fnp2) (void);
-void f1 (void) { v++; }
+void f1 (void) { v += 1; }
void f2 (void) { v += 4; }
void f3 (void) { v += 16; f1 (); }
fnp1 f4 (void) { v += 64; return f2; }