[clang] [Clang] Add flags and lang option for C++2d (PR #203992)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 29 11:01:36 PDT 2026
https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/203992
>From f490b0f3019d6f9838f085716254ac3771be2a8b Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 15 Jun 2026 23:02:34 +0200
Subject: [PATCH 1/6] [Clang] Add flags and lang option for C++2d
---
clang/docs/CommandGuide/clang.rst | 8 ++++++++
clang/docs/ReleaseNotes.rst | 5 +++++
clang/docs/ReleaseNotesTemplate.txt | 3 +++
clang/docs/UsersManual.rst | 2 +-
clang/include/clang/Basic/Diagnostic.td | 1 +
clang/include/clang/Basic/DiagnosticGroups.td | 10 ++++++++++
clang/include/clang/Basic/LangOptions.def | 1 +
clang/include/clang/Basic/LangStandard.h | 14 +++++++++-----
clang/include/clang/Basic/LangStandards.def | 13 +++++++++++++
clang/include/clang/Testing/TestLanguage.def | 1 +
clang/lib/Basic/LangOptions.cpp | 5 ++++-
clang/lib/CrossTU/CrossTranslationUnit.cpp | 2 ++
clang/lib/Driver/Driver.cpp | 1 +
clang/lib/Driver/ToolChains/Clang.cpp | 9 ++++++---
.../InterpolatingCompilationDatabase.cpp | 4 ++--
clang/test/Driver/cl-options.c | 2 +-
clang/test/Driver/unknown-std.cpp | 2 ++
clang/test/Preprocessor/init.c | 18 ++++++++++++++++++
clang/www/OpenProjects.html | 2 +-
19 files changed, 89 insertions(+), 14 deletions(-)
diff --git a/clang/docs/CommandGuide/clang.rst b/clang/docs/CommandGuide/clang.rst
index d8c70bdc43b18..c4dcca3d093fd 100644
--- a/clang/docs/CommandGuide/clang.rst
+++ b/clang/docs/CommandGuide/clang.rst
@@ -226,6 +226,14 @@ Language Selection and Mode Options
Working draft for C++2c with GNU extensions
+ | ``c++2d``
+
+ Working draft for C++2d
+
+ | ``gnu++2d``
+
+ Working draft for C++2d with GNU extensions
+
The default C++ language standard is ``gnu++17``.
Supported values for the OpenCL language are:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7828135a6edbc..ca81b67c1be66 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -193,6 +193,11 @@ C++ Language Changes
- ``__is_trivially_equality_comparable`` no longer returns false for all enum types. (#GH132672)
- ``auto`` parameters are now available in all C++ language modes as an extension.
+C++2d Feature Support
+^^^^^^^^^^^^^^^^^^^^^
+
+- Added compiler flags ``-std=c++2d`` and ``-std=gnu++2d`` for experimental C++2d implementation work.
+
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/docs/ReleaseNotesTemplate.txt b/clang/docs/ReleaseNotesTemplate.txt
index b5664dcf3b212..0c588c3b4f43a 100644
--- a/clang/docs/ReleaseNotesTemplate.txt
+++ b/clang/docs/ReleaseNotesTemplate.txt
@@ -61,6 +61,9 @@ What's New in Clang |release|?
C++ Language Changes
--------------------
+C++2d Feature Support
+^^^^^^^^^^^^^^^^^^^^^
+
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 3f4b1585e5935..b715caed5bd4c 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -40,7 +40,7 @@ specific section:
- :ref:`Objective-C Language <objc>`: ObjC 1, ObjC 2, ObjC 2.1, plus
variants depending on base language.
- :ref:`C++ Language <cxx>`: C++98, C++03, C++11, C++14, C++17, C++20, C++23,
- and C++26.
+ C++26, and C++29.
- :ref:`Objective C++ Language <objcxx>`
- :ref:`OpenCL Kernel Language <opencl>`: OpenCL C 1.0, 1.1, 1.2, 2.0, 3.0,
and C++ for OpenCL 1.0 and 2021.
diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td
index d56fb22b2f539..693984d8241f0 100644
--- a/clang/include/clang/Basic/Diagnostic.td
+++ b/clang/include/clang/Basic/Diagnostic.td
@@ -244,6 +244,7 @@ multiclass CXX17Compat<string message, bit ext_warn = true> : CXXCompat<message,
multiclass CXX20Compat<string message, bit ext_warn = true> : CXXCompat<message, 20, ext_warn>;
multiclass CXX23Compat<string message, bit ext_warn = true> : CXXCompat<message, 23, ext_warn>;
multiclass CXX26Compat<string message, bit ext_warn = true> : CXXCompat<message, 26, ext_warn, "2c">;
+multiclass CXX29Compat<string message, bit ext_warn = true> : CXXCompat<message, 29, ext_warn, "2d">;
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 244cd3630bb11..f49ad84751761 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -412,6 +412,11 @@ def CXXPre26CompatPedantic :
DiagGroup<"pre-c++26-compat-pedantic", [CXXPre26Compat]>;
def : DiagGroup<"pre-c++2c-compat", [CXXPre26Compat]>;
def : DiagGroup<"pre-c++2c-compat-pedantic", [CXXPre26CompatPedantic]>;
+def CXXPre29Compat : DiagGroup<"pre-c++29-compat">;
+def CXXPre29CompatPedantic :
+ DiagGroup<"pre-c++29-compat-pedantic", [CXXPre29Compat]>;
+def : DiagGroup<"pre-c++2d-compat", [CXXPre29Compat]>;
+def : DiagGroup<"pre-c++2d-compat-pedantic", [CXXPre29CompatPedantic]>;
def CXX98CompatBindToTemporaryCopy :
DiagGroup<"c++98-compat-bind-to-temporary-copy">;
@@ -1572,12 +1577,17 @@ def CXX23 : DiagGroup<"c++23-extensions", [CXX23AttrsOnLambda]>;
// earlier C++ versions.
def CXX26 : DiagGroup<"c++26-extensions">;
+// A warning group for warnings about using C++29 features as extensions in
+// earlier C++ versions.
+def CXX29 : DiagGroup<"c++29-extensions">;
+
def : DiagGroup<"c++0x-extensions", [CXX11]>;
def : DiagGroup<"c++1y-extensions", [CXX14]>;
def : DiagGroup<"c++1z-extensions", [CXX17]>;
def : DiagGroup<"c++2a-extensions", [CXX20]>;
def : DiagGroup<"c++2b-extensions", [CXX23]>;
def : DiagGroup<"c++2c-extensions", [CXX26]>;
+def : DiagGroup<"c++2d-extensions", [CXX29]>;
def DelegatingCtorCycles :
DiagGroup<"delegating-ctor-cycles">;
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 4a3e3b7c04822..21079dbe870cb 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -57,6 +57,7 @@ LANGOPT(CPlusPlus17 , 1, 0, NotCompatible, "C++17")
LANGOPT(CPlusPlus20 , 1, 0, NotCompatible, "C++20")
LANGOPT(CPlusPlus23 , 1, 0, NotCompatible, "C++23")
LANGOPT(CPlusPlus26 , 1, 0, NotCompatible, "C++26")
+LANGOPT(CPlusPlus29 , 1, 0, NotCompatible, "C++29")
LANGOPT(ObjC , 1, 0, NotCompatible, "Objective-C")
LANGOPT(ObjCDefaultSynthProperties , 1, 0, Benign,
"Objective-C auto-synthesized properties")
diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h
index 1eef3a6339299..8f42cc1566dd9 100644
--- a/clang/include/clang/Basic/LangStandard.h
+++ b/clang/include/clang/Basic/LangStandard.h
@@ -59,11 +59,12 @@ enum LangFeatures {
CPlusPlus20 = (1 << 10),
CPlusPlus23 = (1 << 11),
CPlusPlus26 = (1 << 12),
- Digraphs = (1 << 13),
- GNUMode = (1 << 14),
- HexFloat = (1 << 15),
- OpenCL = (1 << 16),
- HLSL = (1 << 17)
+ CPlusPlus29 = (1 << 13),
+ Digraphs = (1 << 14),
+ GNUMode = (1 << 15),
+ HexFloat = (1 << 16),
+ OpenCL = (1 << 17),
+ HLSL = (1 << 18)
};
/// LangStandard - Information about the properties of a particular language
@@ -133,6 +134,9 @@ struct LangStandard {
/// isCPlusPlus26 - Language is a post-C++26 variant (or later).
bool isCPlusPlus26() const { return Flags & CPlusPlus26; }
+ /// isCPlusPlus29 - Language is a post-C++29 variant (or later).
+ bool isCPlusPlus29() const { return Flags & CPlusPlus29; }
+
/// hasDigraphs - Language supports digraphs.
bool hasDigraphs() const { return Flags & Digraphs; }
diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def
index 4edc93503cdf5..19a5a932e2ef1 100644
--- a/clang/include/clang/Basic/LangStandards.def
+++ b/clang/include/clang/Basic/LangStandards.def
@@ -191,6 +191,19 @@ LANGSTANDARD(gnucxx26, "gnu++2c",
CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat | GNUMode, 202400)
LANGSTANDARD_ALIAS(gnucxx26, "gnu++26")
+// FIXME: Use correct version code for C++29 once published.
+LANGSTANDARD(cxx29, "c++2d",
+ CXX, "Working draft for C++2d",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
+ CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | CPlusPlus29 | Digraphs | HexFloat, 202700)
+LANGSTANDARD_ALIAS(cxx29, "c++29")
+
+LANGSTANDARD(gnucxx29, "gnu++2d",
+ CXX, "Working draft for C++2d with GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
+ CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | CPlusPlus29 | Digraphs | HexFloat | GNUMode, 202700)
+LANGSTANDARD_ALIAS(gnucxx29, "gnu++29")
+
// OpenCL
LANGSTANDARD(opencl10, "cl1.0",
OpenCL, "OpenCL 1.0",
diff --git a/clang/include/clang/Testing/TestLanguage.def b/clang/include/clang/Testing/TestLanguage.def
index ac62b176a0b87..5fe3a5f04d755 100644
--- a/clang/include/clang/Testing/TestLanguage.def
+++ b/clang/include/clang/Testing/TestLanguage.def
@@ -41,6 +41,7 @@ TESTLANGUAGE_CXX(CXX, 17, c++17, 4)
TESTLANGUAGE_CXX(CXX, 20, c++20, 5)
TESTLANGUAGE_CXX(CXX, 23, c++23, 6)
TESTLANGUAGE_CXX(CXX, 26, c++26, 7)
+TESTLANGUAGE_CXX(CXX, 29, c++29, 8)
#undef TESTLANGUAGE_CXX
#undef TESTLANGUAGE_C
diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp
index 7e75bf1221eb7..ea5bfa09b4df2 100644
--- a/clang/lib/Basic/LangOptions.cpp
+++ b/clang/lib/Basic/LangOptions.cpp
@@ -124,6 +124,7 @@ void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang,
Opts.CPlusPlus20 = Std.isCPlusPlus20();
Opts.CPlusPlus23 = Std.isCPlusPlus23();
Opts.CPlusPlus26 = Std.isCPlusPlus26();
+ Opts.CPlusPlus29 = Std.isCPlusPlus29();
Opts.GNUMode = Std.isGNUMode();
Opts.GNUCVersion = 0;
Opts.HexFloats = Std.hasHexFloats();
@@ -256,7 +257,9 @@ std::optional<uint32_t> LangOptions::getCPlusPlusLangStd() const {
return std::nullopt;
LangStandard::Kind Std;
- if (CPlusPlus26)
+ if (CPlusPlus29)
+ Std = LangStandard::lang_cxx29;
+ else if (CPlusPlus26)
Std = LangStandard::lang_cxx26;
else if (CPlusPlus23)
Std = LangStandard::lang_cxx23;
diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp
index f5c3e27698bd0..2239d54d591bf 100644
--- a/clang/lib/CrossTU/CrossTranslationUnit.cpp
+++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp
@@ -150,6 +150,8 @@ static llvm::ManagedStatic<IndexErrorCategory> Category;
static std::string getLangDescription(const LangOptions &LO) {
if (!LO.CPlusPlus)
return "non-C++";
+ if (LO.CPlusPlus29)
+ return "C++29";
if (LO.CPlusPlus26)
return "C++26";
if (LO.CPlusPlus23)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8f189ea189408..1dd55397f2e05 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1668,6 +1668,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
(Std->containsValue("c++20") || Std->containsValue("c++2a") ||
Std->containsValue("c++23") || Std->containsValue("c++2b") ||
Std->containsValue("c++26") || Std->containsValue("c++2c") ||
+ Std->containsValue("c++29") || Std->containsValue("c++2d") ||
Std->containsValue("c++latest"));
// Process -fmodule-header{=} flags.
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 312e8f8c69f0a..9ce2fd1ddcf56 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7533,9 +7533,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// TransferableCommand::tryParseStdArg() in
// lib/Tooling/InterpolatingCompilationDatabase.cpp
// to match.
- // TODO add c++23 and c++26 when MSVC supports it.
+ // TODO add c++23, c++26, c++29 when MSVC supports
+ // it.
.Case("c++23preview", "-std=c++23")
- .Case("c++latest", "-std=c++26")
+ .Case("c++latest", "-std=c++29")
.Default("");
if (IsSYCL) {
const LangStandard *LangStd =
@@ -7625,7 +7626,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Std->containsValue("c++23") || Std->containsValue("gnu++23") ||
Std->containsValue("c++23preview") || Std->containsValue("c++2c") ||
Std->containsValue("gnu++2c") || Std->containsValue("c++26") ||
- Std->containsValue("gnu++26") || Std->containsValue("c++latest") ||
+ Std->containsValue("gnu++26") || Std->containsValue("c++2d") ||
+ Std->containsValue("gnu++2d") || Std->containsValue("c++29") ||
+ Std->containsValue("gnu++29") || Std->containsValue("c++latest") ||
Std->containsValue("gnu++latest"));
bool HaveModules =
RenderModulesOptions(C, D, Args, Input, Output, HaveCxx20, CmdArgs);
diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
index 36d0775a80708..e228ef6512611 100644
--- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -148,9 +148,9 @@ static LangStandard::Kind latestLangStandardC() {
// flag in clang-CL mode.
static LangStandard::Kind latestLangStandardCXX() {
// FIXME: Have a single source of truth for the mapping from
- // c++latest --> c++26 that's shared by the driver code
+ // c++latest --> c++29 that's shared by the driver code
// (clang/lib/Driver/ToolChains/Clang.cpp) and this file.
- return LangStandard::lang_cxx26;
+ return LangStandard::lang_cxx29;
}
// A CompileCommand that can be applied to another file.
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index 63a423f5b3114..cad42dda9e992 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -625,7 +625,7 @@
// STDCXX23PREVIEW: -std=c++23
// RUN: %clang_cl -fmsc-version=1900 -TP -std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=STDCXXLATEST %s
-// STDCXXLATEST: -std=c++26
+// STDCXXLATEST: -std=c++29
// RUN: env CL="/Gy" %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=ENV-CL %s
// ENV-CL: "-ffunction-sections"
diff --git a/clang/test/Driver/unknown-std.cpp b/clang/test/Driver/unknown-std.cpp
index 5c58042a0a2c7..0d230fad1aa0b 100644
--- a/clang/test/Driver/unknown-std.cpp
+++ b/clang/test/Driver/unknown-std.cpp
@@ -24,6 +24,8 @@
// CHECK-NEXT: note: use 'gnu++23' for 'ISO C++ 2023 DIS with GNU extensions' standard
// CHECK-NEXT: note: use 'c++2c' or 'c++26' for 'Working draft for C++2c' standard
// CHECK-NEXT: note: use 'gnu++2c' or 'gnu++26' for 'Working draft for C++2c with GNU extensions' standard
+// CHECK-NEXT: note: use 'c++2d' or 'c++29' for 'Working draft for C++2d' standard
+// CHECK-NEXT: note: use 'gnu++2d' or 'gnu++29' for 'Working draft for C++2d with GNU extensions' standard
// Make sure that no other output is present.
// CHECK-NOT: {{^.+$}}
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 80b7a6399e5f4..7e6b854719287 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -15,6 +15,16 @@
// BLOCKS:#define __BLOCKS__ 1
// BLOCKS:#define __block __attribute__((__blocks__(byref)))
//
+// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++2d -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX29 %s
+// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++29 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX29 %s
+//
+// CXX29:#define __GNUG__ 4
+// CXX29:#define __GXX_EXPERIMENTAL_CXX0X__ 1
+// CXX29:#define __GXX_RTTI 1
+// CXX29:#define __GXX_WEAK__ 1
+// CXX29:#define __cplusplus 202700L
+// CXX29:#define __private_extern__ extern
+//
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++26 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX26 %s
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++2c -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX26 %s
//
@@ -214,6 +224,14 @@
// RUN: %clang_cc1 -ffreestanding -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix FREESTANDING %s
// FREESTANDING:#define __STDC_HOSTED__ 0
//
+// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++29 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
+// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2d -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
+//
+// GXX26:#define __GNUG__ 4
+// GXX26:#define __GXX_WEAK__ 1
+// GXX26:#define __cplusplus 202700L
+// GXX26:#define __private_extern__ extern
+//
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++26 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2c -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
//
diff --git a/clang/www/OpenProjects.html b/clang/www/OpenProjects.html
index 3e5e84b5b2ed4..71ce7ecf416d8 100755
--- a/clang/www/OpenProjects.html
+++ b/clang/www/OpenProjects.html
@@ -112,7 +112,7 @@ <h1>Open Clang Projects</h1>
</ul>
</li>
-<li><b>Continue work on C++20, C++23, C++2c, and C23 support</b>:
+<li><b>Continue work on C++20, C++23, C++2c, C++2d, and C23 support</b>:
There are still several C++20 features to complete, and work has begun on
supporting the latest language standards. Please see the
<a href="cxx_status.html">C++ status report page</a> to find out what is
>From a69daed075b078f1e4bb490c51b42c9b6dd5c8c7 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 15 Jun 2026 23:10:59 +0200
Subject: [PATCH 2/6] Update some more instances of CPlusPlus26 that I missed
---
clang/include/clang/Options/Options.td | 1 +
clang/lib/Basic/DiagnosticIDs.cpp | 2 ++
clang/lib/Basic/Module.cpp | 1 +
clang/lib/Basic/Targets/OSTargets.cpp | 5 ++++-
clang/unittests/Basic/LangOptionsTest.cpp | 2 ++
5 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index a4b9cb802af4d..48074ae7e52bb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -632,6 +632,7 @@ defvar cpp17 = LangOpts<"CPlusPlus17">;
defvar cpp20 = LangOpts<"CPlusPlus20">;
defvar cpp23 = LangOpts<"CPlusPlus23">;
defvar cpp26 = LangOpts<"CPlusPlus26">;
+defvar cpp29 = LangOpts<"CPlusPlus29">;
defvar c99 = LangOpts<"C99">;
defvar c23 = LangOpts<"C23">;
defvar lang_std = LangOpts<"LangStd">;
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index d9c5e4082c1a7..6445aa6f4ecb1 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -902,6 +902,8 @@ unsigned DiagnosticIDs::getCXXCompatDiagId(const LangOptions &LangOpts,
assert(CompatDiagId < std::size(Diags) && "Invalid compat diag id");
unsigned StdVer = [&] {
+ if (LangOpts.CPlusPlus29)
+ return 2029;
if (LangOpts.CPlusPlus26)
return 2026;
if (LangOpts.CPlusPlus23)
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index d27abb1153c72..3e2f66f27a518 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -105,6 +105,7 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
.Case("cplusplus20", LangOpts.CPlusPlus20)
.Case("cplusplus23", LangOpts.CPlusPlus23)
.Case("cplusplus26", LangOpts.CPlusPlus26)
+ .Case("cplusplus29", LangOpts.CPlusPlus29)
.Case("c99", LangOpts.C99)
.Case("c11", LangOpts.C11)
.Case("c17", LangOpts.C17)
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp
index 08f69bdc4b365..915cd566ed6e4 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -228,7 +228,10 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) {
Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
- if (Opts.CPlusPlus26)
+ if (Opts.CPlusPlus29)
+ // TODO update to the proper value.
+ Builder.defineMacro("_MSVC_LANG", "202700L");
+ else if (Opts.CPlusPlus26)
// TODO update to the proper value.
Builder.defineMacro("_MSVC_LANG", "202400L");
else if (Opts.CPlusPlus23)
diff --git a/clang/unittests/Basic/LangOptionsTest.cpp b/clang/unittests/Basic/LangOptionsTest.cpp
index 0d7d5ec86b0b8..341ec7ba51b6e 100644
--- a/clang/unittests/Basic/LangOptionsTest.cpp
+++ b/clang/unittests/Basic/LangOptionsTest.cpp
@@ -50,6 +50,8 @@ TEST(LangOptsTest, CppStdLang) {
EXPECT_EQ(opts.getCPlusPlusLangStd(), 202302);
opts.CPlusPlus26 = 1;
EXPECT_EQ(opts.getCPlusPlusLangStd(), 202400);
+ opts.CPlusPlus29 = 1;
+ EXPECT_EQ(opts.getCPlusPlusLangStd(), 202700);
EXPECT_FALSE(opts.getCLangStd());
}
>From 2e2b85bc3f870dffed4e601570e564de5a54d4f1 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 15 Jun 2026 23:52:03 +0200
Subject: [PATCH 3/6] fix copy-paste error
---
clang/test/Preprocessor/init.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 7e6b854719287..2a4760b6ea8fd 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -224,13 +224,13 @@
// RUN: %clang_cc1 -ffreestanding -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix FREESTANDING %s
// FREESTANDING:#define __STDC_HOSTED__ 0
//
-// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++29 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
-// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2d -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
+// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++29 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX29 %s
+// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2d -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX29 %s
//
-// GXX26:#define __GNUG__ 4
-// GXX26:#define __GXX_WEAK__ 1
-// GXX26:#define __cplusplus 202700L
-// GXX26:#define __private_extern__ extern
+// GXX29:#define __GNUG__ 4
+// GXX29:#define __GXX_WEAK__ 1
+// GXX29:#define __cplusplus 202700L
+// GXX29:#define __private_extern__ extern
//
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++26 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2c -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX26 %s
>From 8f8aeb1d4f26efc2da712df9ba41c6ec007a9421 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 15 Jun 2026 23:52:43 +0200
Subject: [PATCH 4/6] update make_cxx_dr_status.py
---
clang/www/make_cxx_dr_status | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/www/make_cxx_dr_status b/clang/www/make_cxx_dr_status
index 3ba12e13a7354..439f3d879771d 100755
--- a/clang/www/make_cxx_dr_status
+++ b/clang/www/make_cxx_dr_status
@@ -186,6 +186,9 @@ def availability(issue):
elif status.endswith(' c++26'):
status = status[:-6]
avail_suffix = ' (C++26 onwards)'
+ elif status.endswith(' c++29'):
+ status = status[:-6]
+ avail_suffix = ' (C++29 onwards)'
if status == 'unknown':
avail = 'Unknown'
avail_style = 'unknown'
>From 287562421f4a9debc5d8c049cb48b077703ab5ef Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 29 Jun 2026 18:50:07 +0200
Subject: [PATCH 5/6] reformat
---
clang/include/clang/Basic/LangStandards.def | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def
index 19a5a932e2ef1..04724445c2169 100644
--- a/clang/include/clang/Basic/LangStandards.def
+++ b/clang/include/clang/Basic/LangStandards.def
@@ -107,7 +107,8 @@ LANGSTANDARD(c2y, "c2y",
LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | HexFloat, 202400)
LANGSTANDARD(gnu2y, "gnu2y",
C, "Working Draft for ISO C2y with GNU extensions",
- LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | GNUMode | HexFloat, 202400)
+ LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | GNUMode
+ | HexFloat, 202400)
// TODO: Add the iso9899:202y alias once ISO publishes the standard.
// C++ modes
>From cf2254b751078a47bdc9e721fd069f0e9e660f73 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 29 Jun 2026 20:01:21 +0200
Subject: [PATCH 6/6] remove -std=c++29 for now
---
clang/include/clang/Basic/LangStandards.def | 4 ++--
clang/lib/Driver/Driver.cpp | 3 +--
clang/lib/Driver/ToolChains/Clang.cpp | 5 ++---
clang/test/Driver/cl-options.c | 2 +-
clang/test/Driver/unknown-std.cpp | 4 ++--
clang/test/Preprocessor/init.c | 2 --
6 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def
index 04724445c2169..60eb738f545df 100644
--- a/clang/include/clang/Basic/LangStandards.def
+++ b/clang/include/clang/Basic/LangStandards.def
@@ -193,17 +193,17 @@ LANGSTANDARD(gnucxx26, "gnu++2c",
LANGSTANDARD_ALIAS(gnucxx26, "gnu++26")
// FIXME: Use correct version code for C++29 once published.
+// TODO: Add LANGSTANDARD_ALIAS() for "c++29" once C++29 is ratified.
LANGSTANDARD(cxx29, "c++2d",
CXX, "Working draft for C++2d",
LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | CPlusPlus29 | Digraphs | HexFloat, 202700)
-LANGSTANDARD_ALIAS(cxx29, "c++29")
+// TODO: Add LANGSTANDARD_ALIAS() for "gnu++29" once C++29 is ratified.
LANGSTANDARD(gnucxx29, "gnu++2d",
CXX, "Working draft for C++2d with GNU extensions",
LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | CPlusPlus29 | Digraphs | HexFloat | GNUMode, 202700)
-LANGSTANDARD_ALIAS(gnucxx29, "gnu++29")
// OpenCL
LANGSTANDARD(opencl10, "cl1.0",
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 1dd55397f2e05..bc9fb91942b1c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1668,8 +1668,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
(Std->containsValue("c++20") || Std->containsValue("c++2a") ||
Std->containsValue("c++23") || Std->containsValue("c++2b") ||
Std->containsValue("c++26") || Std->containsValue("c++2c") ||
- Std->containsValue("c++29") || Std->containsValue("c++2d") ||
- Std->containsValue("c++latest"));
+ Std->containsValue("c++2d") || Std->containsValue("c++latest"));
// Process -fmodule-header{=} flags.
if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 9ce2fd1ddcf56..392e66ad8a55d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7536,7 +7536,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// TODO add c++23, c++26, c++29 when MSVC supports
// it.
.Case("c++23preview", "-std=c++23")
- .Case("c++latest", "-std=c++29")
+ .Case("c++latest", "-std=c++2d")
.Default("");
if (IsSYCL) {
const LangStandard *LangStd =
@@ -7627,8 +7627,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Std->containsValue("c++23preview") || Std->containsValue("c++2c") ||
Std->containsValue("gnu++2c") || Std->containsValue("c++26") ||
Std->containsValue("gnu++26") || Std->containsValue("c++2d") ||
- Std->containsValue("gnu++2d") || Std->containsValue("c++29") ||
- Std->containsValue("gnu++29") || Std->containsValue("c++latest") ||
+ Std->containsValue("gnu++2d") || Std->containsValue("c++latest") ||
Std->containsValue("gnu++latest"));
bool HaveModules =
RenderModulesOptions(C, D, Args, Input, Output, HaveCxx20, CmdArgs);
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index cad42dda9e992..1f16af5c43a3d 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -625,7 +625,7 @@
// STDCXX23PREVIEW: -std=c++23
// RUN: %clang_cl -fmsc-version=1900 -TP -std:c++latest -### -- %s 2>&1 | FileCheck -check-prefix=STDCXXLATEST %s
-// STDCXXLATEST: -std=c++29
+// STDCXXLATEST: -std=c++2d
// RUN: env CL="/Gy" %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=ENV-CL %s
// ENV-CL: "-ffunction-sections"
diff --git a/clang/test/Driver/unknown-std.cpp b/clang/test/Driver/unknown-std.cpp
index 0d230fad1aa0b..24e044f0bab76 100644
--- a/clang/test/Driver/unknown-std.cpp
+++ b/clang/test/Driver/unknown-std.cpp
@@ -24,8 +24,8 @@
// CHECK-NEXT: note: use 'gnu++23' for 'ISO C++ 2023 DIS with GNU extensions' standard
// CHECK-NEXT: note: use 'c++2c' or 'c++26' for 'Working draft for C++2c' standard
// CHECK-NEXT: note: use 'gnu++2c' or 'gnu++26' for 'Working draft for C++2c with GNU extensions' standard
-// CHECK-NEXT: note: use 'c++2d' or 'c++29' for 'Working draft for C++2d' standard
-// CHECK-NEXT: note: use 'gnu++2d' or 'gnu++29' for 'Working draft for C++2d with GNU extensions' standard
+// CHECK-NEXT: note: use 'c++2d' for 'Working draft for C++2d' standard
+// CHECK-NEXT: note: use 'gnu++2d' for 'Working draft for C++2d with GNU extensions' standard
// Make sure that no other output is present.
// CHECK-NOT: {{^.+$}}
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 2a4760b6ea8fd..ef7b76a29a1f5 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -16,7 +16,6 @@
// BLOCKS:#define __block __attribute__((__blocks__(byref)))
//
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++2d -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX29 %s
-// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++29 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX29 %s
//
// CXX29:#define __GNUG__ 4
// CXX29:#define __GXX_EXPERIMENTAL_CXX0X__ 1
@@ -224,7 +223,6 @@
// RUN: %clang_cc1 -ffreestanding -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix FREESTANDING %s
// FREESTANDING:#define __STDC_HOSTED__ 0
//
-// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++29 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX29 %s
// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2d -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX29 %s
//
// GXX29:#define __GNUG__ 4
More information about the cfe-commits
mailing list