From 375a56e2def366b838a79042b2c11e08dfbd8a4c Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 13 Oct 2025 23:59:16 +0100 Subject: [PATCH 1/6] [clang][Basic] Add helper APIs to get language version codes from LangOptions --- clang/include/clang/Basic/LangOptions.h | 31 +++++++++++++++++ clang/lib/Basic/LangOptions.cpp | 46 +++++++++++++++++++++++++ clang/lib/Frontend/InitPreprocessor.cpp | 37 +++----------------- clang/unittests/Basic/CMakeLists.txt | 1 + 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 41595ec2a060d..940e79634ccd5 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -184,6 +184,28 @@ class LangOptionsBase { HLSL_202y = 2029, }; + /// C language version codes as defined by the standard. + enum CLangStd : uint32_t { + // FIXME: Use correct value for C2y. + C_2y = 202400, + C_23 = 202311, + C_17 = 201710, + C_11 = 201112, + C_99 = 199901, + }; + + /// C++ language version codes as defined by the standard. + enum CPlusPlusLangStd : uint32_t { + // FIXME: Use correct value for C++26. + CPP_26 = 202400, + CPP_23 = 202302, + CPP_20 = 202002, + CPP_17 = 201703, + CPP_14 = 201402, + CPP_11 = 201103, + CPP_03 = 199711, + }; + /// Clang versions with different platform ABI conformance. enum class ClangABI { #define ABI_VER_MAJOR_MINOR(Major, Minor) Ver##Major##_##Minor, @@ -756,6 +778,15 @@ class LangOptions : public LangOptionsBase { bool isTargetDevice() const { return OpenMPIsTargetDevice || CUDAIsDevice || SYCLIsDevice; } + + /// Returns the most applicable C standard-compliant language version code. + /// If none could be determined, returns \ref std::nullopt. + std::optional GetCLangStd() const; + + /// Returns the most applicable C++ standard-compliant language + /// version code. + /// If none could be determined, returns \ref std::nullopt. + std::optional GetCPlusPlusLangStd() const; }; /// Floating point control options diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index f034514466d3f..6745427e2c223 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -243,3 +243,49 @@ LLVM_DUMP_METHOD void FPOptionsOverride::dump() { #include "clang/Basic/FPOptions.def" llvm::errs() << "\n"; } + +std::optional +LangOptions::GetCPlusPlusLangStd() const { + if (!CPlusPlus) + return std::nullopt; + + if (CPlusPlus26) + return clang::LangOptionsBase::CPP_26; + + if (CPlusPlus23) + return clang::LangOptionsBase::CPP_23; + + if (CPlusPlus20) + return clang::LangOptionsBase::CPP_20; + + if (CPlusPlus17) + return clang::LangOptionsBase::CPP_17; + + if (CPlusPlus14) + return clang::LangOptionsBase::CPP_14; + + if (CPlusPlus11) + return clang::LangOptionsBase::CPP_11; + + return clang::LangOptionsBase::CPP_03; +} + +std::optional +LangOptions::GetCLangStd() const { + if (C2y) + return clang::LangOptionsBase::C_2y; + + if (C23) + return clang::LangOptionsBase::C_23; + + if (C17) + return clang::LangOptionsBase::C_17; + + if (C11) + return clang::LangOptionsBase::C_11; + + if (C99) + return clang::LangOptionsBase::C_99; + + return std::nullopt; +} diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index b899fb9c6494a..27bc4cf7108cc 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -459,43 +459,14 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, // value is, are implementation-defined. // (Removed in C++20.) if (!LangOpts.CPlusPlus) { - if (LangOpts.C2y) - Builder.defineMacro("__STDC_VERSION__", "202400L"); - else if (LangOpts.C23) - Builder.defineMacro("__STDC_VERSION__", "202311L"); - else if (LangOpts.C17) - Builder.defineMacro("__STDC_VERSION__", "201710L"); - else if (LangOpts.C11) - Builder.defineMacro("__STDC_VERSION__", "201112L"); - else if (LangOpts.C99) - Builder.defineMacro("__STDC_VERSION__", "199901L"); + if (auto LangStd = LangOpts.GetCLangStd()) + Builder.defineMacro("__STDC_VERSION__", Twine(*LangStd) + "L"); else if (!LangOpts.GNUMode && LangOpts.Digraphs) Builder.defineMacro("__STDC_VERSION__", "199409L"); } else { // -- __cplusplus - if (LangOpts.CPlusPlus26) - // FIXME: Use correct value for C++26. - Builder.defineMacro("__cplusplus", "202400L"); - else if (LangOpts.CPlusPlus23) - Builder.defineMacro("__cplusplus", "202302L"); - // [C++20] The integer literal 202002L. - else if (LangOpts.CPlusPlus20) - Builder.defineMacro("__cplusplus", "202002L"); - // [C++17] The integer literal 201703L. - else if (LangOpts.CPlusPlus17) - Builder.defineMacro("__cplusplus", "201703L"); - // [C++14] The name __cplusplus is defined to the value 201402L when - // compiling a C++ translation unit. - else if (LangOpts.CPlusPlus14) - Builder.defineMacro("__cplusplus", "201402L"); - // [C++11] The name __cplusplus is defined to the value 201103L when - // compiling a C++ translation unit. - else if (LangOpts.CPlusPlus11) - Builder.defineMacro("__cplusplus", "201103L"); - // [C++03] The name __cplusplus is defined to the value 199711L when - // compiling a C++ translation unit. - else - Builder.defineMacro("__cplusplus", "199711L"); + Builder.defineMacro("__cplusplus", + Twine(*LangOpts.GetCPlusPlusLangStd()) + "L"); // -- __STDCPP_DEFAULT_NEW_ALIGNMENT__ // [C++17] An integer literal of type std::size_t whose value is the diff --git a/clang/unittests/Basic/CMakeLists.txt b/clang/unittests/Basic/CMakeLists.txt index 8c8baa57b64e7..f20c8db00a595 100644 --- a/clang/unittests/Basic/CMakeLists.txt +++ b/clang/unittests/Basic/CMakeLists.txt @@ -6,6 +6,7 @@ add_distinct_clang_unittest(BasicTests DiagnosticTest.cpp FileEntryTest.cpp FileManagerTest.cpp + LangOptionsTest.cpp LineOffsetMappingTest.cpp OffloadArchTest.cpp SanitizersTest.cpp From 1c64d14e7b418c1b039b3b8a5a554cfccf63d6a3 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 14 Oct 2025 11:51:08 +0100 Subject: [PATCH 2/6] fixup! add test file --- clang/unittests/Basic/LangOptionsTest.cpp | 55 +++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 clang/unittests/Basic/LangOptionsTest.cpp diff --git a/clang/unittests/Basic/LangOptionsTest.cpp b/clang/unittests/Basic/LangOptionsTest.cpp new file mode 100644 index 0000000000000..37ba4f19aa4bd --- /dev/null +++ b/clang/unittests/Basic/LangOptionsTest.cpp @@ -0,0 +1,55 @@ +//===- unittests/Basic/LangOptionsTest.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/LangOptions.h" +#include "clang/Testing/CommandLineArgs.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace clang; + +namespace { +TEST(LangOptsTest, CStdLang) { + LangOptions opts; + EXPECT_FALSE(opts.GetCLangStd()); + opts.C99 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_99); + opts.C11 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_11); + opts.C17 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_17); + opts.C23 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_23); + opts.C2y = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_2y); + + EXPECT_FALSE(opts.GetCPlusPlusLangStd()); +} + +TEST(LangOptsTest, CppStdLang) { + LangOptions opts; + EXPECT_FALSE(opts.GetCPlusPlusLangStd()); + opts.CPlusPlus = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_03); + opts.CPlusPlus11 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_11); + opts.CPlusPlus14 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_14); + opts.CPlusPlus17 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_17); + opts.CPlusPlus20 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_20); + opts.CPlusPlus23 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_23); + opts.CPlusPlus26 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_26); + + EXPECT_FALSE(opts.GetCLangStd()); +} +} From 79150a3781592adc2b56c3082752f96af671730c Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 14 Oct 2025 11:51:21 +0100 Subject: [PATCH 3/6] fixup! clang-format --- clang/unittests/Basic/LangOptionsTest.cpp | 69 +++++++++++++---------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/clang/unittests/Basic/LangOptionsTest.cpp b/clang/unittests/Basic/LangOptionsTest.cpp index 37ba4f19aa4bd..5abb2cd8498e6 100644 --- a/clang/unittests/Basic/LangOptionsTest.cpp +++ b/clang/unittests/Basic/LangOptionsTest.cpp @@ -16,40 +16,47 @@ using namespace clang; namespace { TEST(LangOptsTest, CStdLang) { - LangOptions opts; - EXPECT_FALSE(opts.GetCLangStd()); - opts.C99 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_99); - opts.C11 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_11); - opts.C17 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_17); - opts.C23 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_23); - opts.C2y = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_2y); + LangOptions opts; + EXPECT_FALSE(opts.GetCLangStd()); + opts.C99 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_99); + opts.C11 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_11); + opts.C17 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_17); + opts.C23 = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_23); + opts.C2y = 1; + EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_2y); - EXPECT_FALSE(opts.GetCPlusPlusLangStd()); + EXPECT_FALSE(opts.GetCPlusPlusLangStd()); } TEST(LangOptsTest, CppStdLang) { - LangOptions opts; - EXPECT_FALSE(opts.GetCPlusPlusLangStd()); - opts.CPlusPlus = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_03); - opts.CPlusPlus11 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_11); - opts.CPlusPlus14 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_14); - opts.CPlusPlus17 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_17); - opts.CPlusPlus20 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_20); - opts.CPlusPlus23 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_23); - opts.CPlusPlus26 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_26); + LangOptions opts; + EXPECT_FALSE(opts.GetCPlusPlusLangStd()); + opts.CPlusPlus = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_03); + opts.CPlusPlus11 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_11); + opts.CPlusPlus14 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_14); + opts.CPlusPlus17 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_17); + opts.CPlusPlus20 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_20); + opts.CPlusPlus23 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_23); + opts.CPlusPlus26 = 1; + EXPECT_EQ(opts.GetCPlusPlusLangStd(), + clang::LangOptionsBase::CPlusPlusLangStd::CPP_26); - EXPECT_FALSE(opts.GetCLangStd()); -} + EXPECT_FALSE(opts.GetCLangStd()); } +} // namespace From ab03eae2db6c0fa83ccbbfd3eb727bc93d746895 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 14 Oct 2025 12:15:17 +0100 Subject: [PATCH 4/6] fixup! lower-case function names --- clang/include/clang/Basic/LangOptions.h | 4 +-- clang/lib/Basic/LangOptions.cpp | 4 +-- clang/lib/Frontend/InitPreprocessor.cpp | 4 +-- clang/unittests/Basic/LangOptionsTest.cpp | 32 +++++++++++------------ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 940e79634ccd5..e4d08b599f6be 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -781,12 +781,12 @@ class LangOptions : public LangOptionsBase { /// Returns the most applicable C standard-compliant language version code. /// If none could be determined, returns \ref std::nullopt. - std::optional GetCLangStd() const; + std::optional getCLangStd() const; /// Returns the most applicable C++ standard-compliant language /// version code. /// If none could be determined, returns \ref std::nullopt. - std::optional GetCPlusPlusLangStd() const; + std::optional getCPlusPlusLangStd() const; }; /// Floating point control options diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index 6745427e2c223..0961004f93d4b 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -245,7 +245,7 @@ LLVM_DUMP_METHOD void FPOptionsOverride::dump() { } std::optional -LangOptions::GetCPlusPlusLangStd() const { +LangOptions::getCPlusPlusLangStd() const { if (!CPlusPlus) return std::nullopt; @@ -271,7 +271,7 @@ LangOptions::GetCPlusPlusLangStd() const { } std::optional -LangOptions::GetCLangStd() const { +LangOptions::getCLangStd() const { if (C2y) return clang::LangOptionsBase::C_2y; diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 27bc4cf7108cc..762e17b0f88a0 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -459,14 +459,14 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, // value is, are implementation-defined. // (Removed in C++20.) if (!LangOpts.CPlusPlus) { - if (auto LangStd = LangOpts.GetCLangStd()) + if (auto LangStd = LangOpts.getCLangStd()) Builder.defineMacro("__STDC_VERSION__", Twine(*LangStd) + "L"); else if (!LangOpts.GNUMode && LangOpts.Digraphs) Builder.defineMacro("__STDC_VERSION__", "199409L"); } else { // -- __cplusplus Builder.defineMacro("__cplusplus", - Twine(*LangOpts.GetCPlusPlusLangStd()) + "L"); + Twine(*LangOpts.getCPlusPlusLangStd()) + "L"); // -- __STDCPP_DEFAULT_NEW_ALIGNMENT__ // [C++17] An integer literal of type std::size_t whose value is the diff --git a/clang/unittests/Basic/LangOptionsTest.cpp b/clang/unittests/Basic/LangOptionsTest.cpp index 5abb2cd8498e6..393f0ee106705 100644 --- a/clang/unittests/Basic/LangOptionsTest.cpp +++ b/clang/unittests/Basic/LangOptionsTest.cpp @@ -17,46 +17,46 @@ using namespace clang; namespace { TEST(LangOptsTest, CStdLang) { LangOptions opts; - EXPECT_FALSE(opts.GetCLangStd()); + EXPECT_FALSE(opts.getCLangStd()); opts.C99 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_99); + EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_99); opts.C11 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_11); + EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_11); opts.C17 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_17); + EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_17); opts.C23 = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_23); + EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_23); opts.C2y = 1; - EXPECT_EQ(opts.GetCLangStd(), clang::LangOptionsBase::CLangStd::C_2y); + EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_2y); - EXPECT_FALSE(opts.GetCPlusPlusLangStd()); + EXPECT_FALSE(opts.getCPlusPlusLangStd()); } TEST(LangOptsTest, CppStdLang) { LangOptions opts; - EXPECT_FALSE(opts.GetCPlusPlusLangStd()); + EXPECT_FALSE(opts.getCPlusPlusLangStd()); opts.CPlusPlus = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_03); opts.CPlusPlus11 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_11); opts.CPlusPlus14 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_14); opts.CPlusPlus17 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_17); opts.CPlusPlus20 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_20); opts.CPlusPlus23 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_23); opts.CPlusPlus26 = 1; - EXPECT_EQ(opts.GetCPlusPlusLangStd(), + EXPECT_EQ(opts.getCPlusPlusLangStd(), clang::LangOptionsBase::CPlusPlusLangStd::CPP_26); - EXPECT_FALSE(opts.GetCLangStd()); + EXPECT_FALSE(opts.getCLangStd()); } } // namespace From bde7c0170fc4529cc12d425e40b6f1440d39ce83 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 15 Oct 2025 09:57:54 +0100 Subject: [PATCH 5/6] fixup! use LangStandard to defined version codes --- clang/include/clang/Basic/LangOptions.h | 26 +----- clang/include/clang/Basic/LangStandard.h | 7 +- clang/include/clang/Basic/LangStandards.def | 90 +++++++++++---------- clang/include/clang/Driver/Options.td | 9 ++- clang/lib/Basic/LangOptions.cpp | 70 ++++++++-------- clang/lib/Basic/LangStandards.cpp | 13 +-- clang/lib/Frontend/CompilerInvocation.cpp | 4 +- clang/lib/Frontend/InitPreprocessor.cpp | 6 +- clang/unittests/Basic/LangOptionsTest.cpp | 36 ++++----- 9 files changed, 120 insertions(+), 141 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index e4d08b599f6be..260a7537edb9d 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -184,28 +184,6 @@ class LangOptionsBase { HLSL_202y = 2029, }; - /// C language version codes as defined by the standard. - enum CLangStd : uint32_t { - // FIXME: Use correct value for C2y. - C_2y = 202400, - C_23 = 202311, - C_17 = 201710, - C_11 = 201112, - C_99 = 199901, - }; - - /// C++ language version codes as defined by the standard. - enum CPlusPlusLangStd : uint32_t { - // FIXME: Use correct value for C++26. - CPP_26 = 202400, - CPP_23 = 202302, - CPP_20 = 202002, - CPP_17 = 201703, - CPP_14 = 201402, - CPP_11 = 201103, - CPP_03 = 199711, - }; - /// Clang versions with different platform ABI conformance. enum class ClangABI { #define ABI_VER_MAJOR_MINOR(Major, Minor) Ver##Major##_##Minor, @@ -781,12 +759,12 @@ class LangOptions : public LangOptionsBase { /// Returns the most applicable C standard-compliant language version code. /// If none could be determined, returns \ref std::nullopt. - std::optional getCLangStd() const; + std::optional getCLangStd() const; /// Returns the most applicable C++ standard-compliant language /// version code. /// If none could be determined, returns \ref std::nullopt. - std::optional getCPlusPlusLangStd() const; + std::optional getCPlusPlusLangStd() const; }; /// Floating point control options diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h index 49412232c9c5e..64645fee933a5 100644 --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -70,8 +70,7 @@ enum LangFeatures { /// standard. struct LangStandard { enum Kind { -#define LANGSTANDARD(id, name, lang, desc, features) \ - lang_##id, +#define LANGSTANDARD(id, name, lang, desc, features, version) lang_##id, #include "clang/Basic/LangStandards.def" lang_unspecified }; @@ -80,6 +79,7 @@ struct LangStandard { const char *Description; unsigned Flags; clang::Language Language; + std::optional Version; public: /// getName - Get the name of this standard. @@ -91,6 +91,9 @@ struct LangStandard { /// Get the language that this standard describes. clang::Language getLanguage() const { return Language; } + /// Get the version code for this language standard. + std::optional getVersion() const { return Version; } + /// Language supports '//' comments. bool hasLineComments() const { return Flags & LineComment; } diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def index 244692ab4296a..4edc93503cdf5 100644 --- a/clang/include/clang/Basic/LangStandards.def +++ b/clang/include/clang/Basic/LangStandards.def @@ -10,7 +10,7 @@ #error "LANGSTANDARD must be defined before including this file" #endif -/// LANGSTANDARD(IDENT, NAME, LANG, DESC, FEATURES) +/// LANGSTANDARD(IDENT, NAME, LANG, DESC, FEATURES, VERSION) /// /// \param IDENT - The name of the standard as a C++ identifier. /// \param NAME - The name of the standard. @@ -18,6 +18,8 @@ /// \param DESC - A short description of the standard. /// \param FEATURES - The standard features as flags, these are enums from the /// clang::frontend namespace, which is assumed to be available. +/// \param VERSION - The official version code for this standard. +/// Has value 'std::nullopt' if no official version exists. /// LANGSTANDARD_ALIAS(IDENT, ALIAS) /// \param IDENT - The name of the standard as a C++ identifier. @@ -36,186 +38,188 @@ // C89-ish modes. LANGSTANDARD(c89, "c89", - C, "ISO C 1990", 0) + C, "ISO C 1990", 0, std::nullopt) LANGSTANDARD_ALIAS(c89, "c90") LANGSTANDARD_ALIAS(c89, "iso9899:1990") LANGSTANDARD(c94, "iso9899:199409", C, "ISO C 1990 with amendment 1", - Digraphs) + Digraphs, 199409) LANGSTANDARD(gnu89, "gnu89", C, "ISO C 1990 with GNU extensions", - LineComment | Digraphs | GNUMode) + LineComment | Digraphs | GNUMode, std::nullopt) LANGSTANDARD_ALIAS(gnu89, "gnu90") // C99-ish modes LANGSTANDARD(c99, "c99", C, "ISO C 1999", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat, 199901) LANGSTANDARD_ALIAS(c99, "iso9899:1999") LANGSTANDARD_ALIAS_DEPR(c99, "c9x") LANGSTANDARD_ALIAS_DEPR(c99, "iso9899:199x") LANGSTANDARD(gnu99, "gnu99", C, "ISO C 1999 with GNU extensions", - LineComment | C99 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | Digraphs | GNUMode | HexFloat, 199901) LANGSTANDARD_ALIAS_DEPR(gnu99, "gnu9x") // C11 modes LANGSTANDARD(c11, "c11", C, "ISO C 2011", - LineComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat, 201112) LANGSTANDARD_ALIAS(c11, "iso9899:2011") LANGSTANDARD_ALIAS_DEPR(c11, "c1x") LANGSTANDARD_ALIAS_DEPR(c11, "iso9899:201x") LANGSTANDARD(gnu11, "gnu11", C, "ISO C 2011 with GNU extensions", - LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat, 201112) LANGSTANDARD_ALIAS_DEPR(gnu11, "gnu1x") // C17 modes LANGSTANDARD(c17, "c17", C, "ISO C 2017", - LineComment | C99 | C11 | C17 | Digraphs | HexFloat) + LineComment | C99 | C11 | C17 | Digraphs | HexFloat, 201710) LANGSTANDARD_ALIAS(c17, "iso9899:2017") LANGSTANDARD_ALIAS(c17, "c18") LANGSTANDARD_ALIAS(c17, "iso9899:2018") LANGSTANDARD(gnu17, "gnu17", C, "ISO C 2017 with GNU extensions", - LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat, 201710) LANGSTANDARD_ALIAS(gnu17, "gnu18") // C23 modes LANGSTANDARD(c23, "c23", C, "ISO C 2023", - LineComment | C99 | C11 | C17 | C23 | Digraphs | HexFloat) + LineComment | C99 | C11 | C17 | C23 | Digraphs | HexFloat, 202311) LANGSTANDARD_ALIAS(c23, "iso9899:2024") LANGSTANDARD_ALIAS_DEPR(c23, "c2x") LANGSTANDARD(gnu23, "gnu23", C, "ISO C 2023 with GNU extensions", - LineComment | C99 | C11 | C17 | C23 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | C17 | C23 | Digraphs | GNUMode | HexFloat, 202311) LANGSTANDARD_ALIAS_DEPR(gnu23, "gnu2x") // C2y modes +// FIXME: Use correct version code for C2y once published. LANGSTANDARD(c2y, "c2y", C, "Working Draft for ISO C2y", - LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | HexFloat) + 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) + LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | GNUMode | HexFloat, 202400) // TODO: Add the iso9899:202y alias once ISO publishes the standard. // C++ modes LANGSTANDARD(cxx98, "c++98", CXX, "ISO C++ 1998 with amendments", - LineComment | CPlusPlus | Digraphs) + LineComment | CPlusPlus | Digraphs, 199711) LANGSTANDARD_ALIAS(cxx98, "c++03") LANGSTANDARD(gnucxx98, "gnu++98", CXX, "ISO C++ 1998 with amendments and GNU extensions", - LineComment | CPlusPlus | Digraphs | GNUMode) + LineComment | CPlusPlus | Digraphs | GNUMode, 199711) LANGSTANDARD_ALIAS(gnucxx98, "gnu++03") LANGSTANDARD(cxx11, "c++11", CXX, "ISO C++ 2011 with amendments", - LineComment | CPlusPlus | CPlusPlus11 | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | Digraphs, 201103) LANGSTANDARD_ALIAS_DEPR(cxx11, "c++0x") LANGSTANDARD(gnucxx11, "gnu++11", CXX, "ISO C++ 2011 with amendments and GNU extensions", - LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode) + LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode, 201103) LANGSTANDARD_ALIAS_DEPR(gnucxx11, "gnu++0x") LANGSTANDARD(cxx14, "c++14", CXX, "ISO C++ 2014 with amendments", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs, 201402) LANGSTANDARD_ALIAS_DEPR(cxx14, "c++1y") LANGSTANDARD(gnucxx14, "gnu++14", CXX, "ISO C++ 2014 with amendments and GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | - GNUMode) + GNUMode, 201402) LANGSTANDARD_ALIAS_DEPR(gnucxx14, "gnu++1y") LANGSTANDARD(cxx17, "c++17", CXX, "ISO C++ 2017 with amendments", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - Digraphs | HexFloat) + Digraphs | HexFloat, 201703) LANGSTANDARD_ALIAS_DEPR(cxx17, "c++1z") LANGSTANDARD(gnucxx17, "gnu++17", CXX, "ISO C++ 2017 with amendments and GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - Digraphs | HexFloat | GNUMode) + Digraphs | HexFloat | GNUMode, 201703) LANGSTANDARD_ALIAS_DEPR(gnucxx17, "gnu++1z") LANGSTANDARD(cxx20, "c++20", CXX, "ISO C++ 2020 DIS", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | Digraphs | HexFloat) + CPlusPlus20 | Digraphs | HexFloat, 202002) LANGSTANDARD_ALIAS_DEPR(cxx20, "c++2a") LANGSTANDARD(gnucxx20, "gnu++20", CXX, "ISO C++ 2020 DIS with GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | Digraphs | HexFloat | GNUMode) + CPlusPlus20 | Digraphs | HexFloat | GNUMode, 202002) LANGSTANDARD_ALIAS_DEPR(gnucxx20, "gnu++2a") LANGSTANDARD(cxx23, "c++23", CXX, "ISO C++ 2023 DIS", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | CPlusPlus23 | Digraphs | HexFloat) + CPlusPlus20 | CPlusPlus23 | Digraphs | HexFloat, 202302) LANGSTANDARD_ALIAS_DEPR(cxx23, "c++2b") LANGSTANDARD(gnucxx23, "gnu++23", CXX, "ISO C++ 2023 DIS with GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | CPlusPlus23 | Digraphs | HexFloat | GNUMode) + CPlusPlus20 | CPlusPlus23 | Digraphs | HexFloat | GNUMode, 202302) LANGSTANDARD_ALIAS_DEPR(gnucxx23, "gnu++2b") +// FIXME: Use correct version code for C++26 once published. LANGSTANDARD(cxx26, "c++2c", CXX, "Working draft for C++2c", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat) + CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat, 202400) LANGSTANDARD_ALIAS(cxx26, "c++26") LANGSTANDARD(gnucxx26, "gnu++2c", CXX, "Working draft for C++2c with GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat | GNUMode) + CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat | GNUMode, 202400) LANGSTANDARD_ALIAS(gnucxx26, "gnu++26") // OpenCL LANGSTANDARD(opencl10, "cl1.0", OpenCL, "OpenCL 1.0", - LineComment | C99 | Digraphs | HexFloat | OpenCL) + LineComment | C99 | Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD_ALIAS_DEPR(opencl10, "cl") LANGSTANDARD(opencl11, "cl1.1", OpenCL, "OpenCL 1.1", - LineComment | C99 | Digraphs | HexFloat | OpenCL) + LineComment | C99 | Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD(opencl12, "cl1.2", OpenCL, "OpenCL 1.2", - LineComment | C99 | Digraphs | HexFloat | OpenCL) + LineComment | C99 | Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD(opencl20, "cl2.0", OpenCL, "OpenCL 2.0", - LineComment | C99 | Digraphs | HexFloat | OpenCL) + LineComment | C99 | Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD(opencl30, "cl3.0", OpenCL, "OpenCL 3.0", - LineComment | C99 | Digraphs | HexFloat | OpenCL) + LineComment | C99 | Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD(openclcpp10, "clc++1.0", OpenCL, "C++ for OpenCL 1.0", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - Digraphs | HexFloat | OpenCL) + Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD_ALIAS(openclcpp10, "clc++") LANGSTANDARD(openclcpp2021, "clc++2021", OpenCL, "C++ for OpenCL 2021", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - Digraphs | HexFloat | OpenCL) + Digraphs | HexFloat | OpenCL, std::nullopt) LANGSTANDARD_ALIAS_DEPR(opencl10, "CL") LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1") @@ -229,35 +233,35 @@ LANGSTANDARD_ALIAS_DEPR(openclcpp2021, "CLC++2021") // HLSL LANGSTANDARD(hlsl, "hlsl", HLSL, "High Level Shader Language", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl2015, "hlsl2015", HLSL, "High Level Shader Language 2015", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl2016, "hlsl2016", HLSL, "High Level Shader Language 2016", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl2017, "hlsl2017", HLSL, "High Level Shader Language 2017", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl2018, "hlsl2018", HLSL, "High Level Shader Language 2018", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl2021, "hlsl2021", HLSL, "High Level Shader Language 2021", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl202x, "hlsl202x", HLSL, "High Level Shader Language 202x", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) LANGSTANDARD(hlsl202y, "hlsl202y", HLSL, "High Level Shader Language 202y", - LineComment | HLSL | CPlusPlus | CPlusPlus11) + LineComment | HLSL | CPlusPlus | CPlusPlus11, std::nullopt) #undef LANGSTANDARD diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index a55a5236b2da1..6a47e9ff90fe8 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6211,11 +6211,12 @@ def static : Flag<["-", "--"], "static">, Group, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<["-"], "std-default=">; def std_EQ : Joined<["-", "--"], "std=">, - Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, - Group, HelpText<"Language standard to compile for">, - ValuesCode<[{ + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, + Group, + HelpText<"Language standard to compile for">, + ValuesCode<[{ static constexpr const char VALUES_CODE [] = - #define LANGSTANDARD(id, name, lang, desc, features) name "," + #define LANGSTANDARD(id, name, lang, desc, features, version) name "," #define LANGSTANDARD_ALIAS(id, alias) alias "," #include "clang/Basic/LangStandards.def" ; diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index 0961004f93d4b..641a3dba0e67a 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/LangOptions.h" +#include "clang/Basic/LangStandard.h" #include "llvm/Support/Path.h" using namespace clang; @@ -244,48 +245,45 @@ LLVM_DUMP_METHOD void FPOptionsOverride::dump() { llvm::errs() << "\n"; } -std::optional -LangOptions::getCPlusPlusLangStd() const { +std::optional LangOptions::getCPlusPlusLangStd() const { if (!CPlusPlus) return std::nullopt; + LangStandard::Kind Std; if (CPlusPlus26) - return clang::LangOptionsBase::CPP_26; - - if (CPlusPlus23) - return clang::LangOptionsBase::CPP_23; - - if (CPlusPlus20) - return clang::LangOptionsBase::CPP_20; - - if (CPlusPlus17) - return clang::LangOptionsBase::CPP_17; - - if (CPlusPlus14) - return clang::LangOptionsBase::CPP_14; - - if (CPlusPlus11) - return clang::LangOptionsBase::CPP_11; - - return clang::LangOptionsBase::CPP_03; + Std = LangStandard::lang_cxx26; + else if (CPlusPlus23) + Std = LangStandard::lang_cxx23; + else if (CPlusPlus20) + Std = LangStandard::lang_cxx20; + else if (CPlusPlus17) + Std = LangStandard::lang_cxx17; + else if (CPlusPlus14) + Std = LangStandard::lang_cxx14; + else if (CPlusPlus11) + Std = LangStandard::lang_cxx11; + else + Std = LangStandard::lang_cxx98; + + return LangStandard::getLangStandardForKind(Std).getVersion(); } -std::optional -LangOptions::getCLangStd() const { +std::optional LangOptions::getCLangStd() const { + LangStandard::Kind Std; if (C2y) - return clang::LangOptionsBase::C_2y; - - if (C23) - return clang::LangOptionsBase::C_23; - - if (C17) - return clang::LangOptionsBase::C_17; - - if (C11) - return clang::LangOptionsBase::C_11; - - if (C99) - return clang::LangOptionsBase::C_99; + Std = LangStandard::lang_c2y; + else if (C23) + Std = LangStandard::lang_c23; + else if (C17) + Std = LangStandard::lang_c17; + else if (C11) + Std = LangStandard::lang_c11; + else if (C99) + Std = LangStandard::lang_c99; + else if (!GNUMode && Digraphs) + Std = LangStandard::lang_c94; + else + return std::nullopt; - return std::nullopt; + return LangStandard::getLangStandardForKind(Std).getVersion(); } diff --git a/clang/lib/Basic/LangStandards.cpp b/clang/lib/Basic/LangStandards.cpp index c49d095018b20..01c524b7220fb 100644 --- a/clang/lib/Basic/LangStandards.cpp +++ b/clang/lib/Basic/LangStandards.cpp @@ -46,16 +46,18 @@ StringRef clang::languageToString(Language L) { llvm_unreachable("unhandled language kind"); } -#define LANGSTANDARD(id, name, lang, desc, features) \ - static const LangStandard Lang_##id = {name, desc, features, Language::lang}; +#define LANGSTANDARD(id, name, lang, desc, features, version) \ + static const LangStandard Lang_##id = {name, desc, features, Language::lang, \ + version}; #include "clang/Basic/LangStandards.def" const LangStandard &LangStandard::getLangStandardForKind(Kind K) { switch (K) { case lang_unspecified: llvm::report_fatal_error("getLangStandardForKind() on unspecified kind"); -#define LANGSTANDARD(id, name, lang, desc, features) \ - case lang_##id: return Lang_##id; +#define LANGSTANDARD(id, name, lang, desc, features, version) \ + case lang_##id: \ + return Lang_##id; #include "clang/Basic/LangStandards.def" } llvm_unreachable("Invalid language kind!"); @@ -63,7 +65,8 @@ const LangStandard &LangStandard::getLangStandardForKind(Kind K) { LangStandard::Kind LangStandard::getLangKind(StringRef Name) { return llvm::StringSwitch(Name) -#define LANGSTANDARD(id, name, lang, desc, features) .Case(name, lang_##id) +#define LANGSTANDARD(id, name, lang, desc, features, version) \ + .Case(name, lang_##id) #define LANGSTANDARD_ALIAS(id, alias) .Case(alias, lang_##id) #include "clang/Basic/LangStandards.def" .Default(lang_unspecified); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 292adce8180bc..5bd15f5d4ca31 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4012,13 +4012,13 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, auto Diag = Diags.Report(diag::note_drv_use_standard); Diag << Std.getName() << Std.getDescription(); unsigned NumAliases = 0; -#define LANGSTANDARD(id, name, lang, desc, features) +#define LANGSTANDARD(id, name, lang, desc, features, version) #define LANGSTANDARD_ALIAS(id, alias) \ if (KindValue == LangStandard::lang_##id) ++NumAliases; #define LANGSTANDARD_ALIAS_DEPR(id, alias) #include "clang/Basic/LangStandards.def" Diag << NumAliases; -#define LANGSTANDARD(id, name, lang, desc, features) +#define LANGSTANDARD(id, name, lang, desc, features, version) #define LANGSTANDARD_ALIAS(id, alias) \ if (KindValue == LangStandard::lang_##id) Diag << alias; #define LANGSTANDARD_ALIAS_DEPR(id, alias) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 762e17b0f88a0..63da549da6a49 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -459,10 +459,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, // value is, are implementation-defined. // (Removed in C++20.) if (!LangOpts.CPlusPlus) { - if (auto LangStd = LangOpts.getCLangStd()) - Builder.defineMacro("__STDC_VERSION__", Twine(*LangStd) + "L"); - else if (!LangOpts.GNUMode && LangOpts.Digraphs) - Builder.defineMacro("__STDC_VERSION__", "199409L"); + Builder.defineMacro("__STDC_VERSION__", + Twine(*LangOpts.getCLangStd()) + "L"); } else { // -- __cplusplus Builder.defineMacro("__cplusplus", diff --git a/clang/unittests/Basic/LangOptionsTest.cpp b/clang/unittests/Basic/LangOptionsTest.cpp index 393f0ee106705..0d7d5ec86b0b8 100644 --- a/clang/unittests/Basic/LangOptionsTest.cpp +++ b/clang/unittests/Basic/LangOptionsTest.cpp @@ -7,8 +7,6 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/LangOptions.h" -#include "clang/Testing/CommandLineArgs.h" -#include "gmock/gmock.h" #include "gtest/gtest.h" using namespace llvm; @@ -18,16 +16,19 @@ namespace { TEST(LangOptsTest, CStdLang) { LangOptions opts; EXPECT_FALSE(opts.getCLangStd()); + opts.GNUMode = 0; + opts.Digraphs = 1; + EXPECT_EQ(opts.getCLangStd(), 199409); opts.C99 = 1; - EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_99); + EXPECT_EQ(opts.getCLangStd(), 199901); opts.C11 = 1; - EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_11); + EXPECT_EQ(opts.getCLangStd(), 201112); opts.C17 = 1; - EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_17); + EXPECT_EQ(opts.getCLangStd(), 201710); opts.C23 = 1; - EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_23); + EXPECT_EQ(opts.getCLangStd(), 202311); opts.C2y = 1; - EXPECT_EQ(opts.getCLangStd(), clang::LangOptionsBase::CLangStd::C_2y); + EXPECT_EQ(opts.getCLangStd(), 202400); EXPECT_FALSE(opts.getCPlusPlusLangStd()); } @@ -36,26 +37,19 @@ TEST(LangOptsTest, CppStdLang) { LangOptions opts; EXPECT_FALSE(opts.getCPlusPlusLangStd()); opts.CPlusPlus = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_03); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 199711); opts.CPlusPlus11 = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_11); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 201103); opts.CPlusPlus14 = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_14); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 201402); opts.CPlusPlus17 = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_17); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 201703); opts.CPlusPlus20 = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_20); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 202002); opts.CPlusPlus23 = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_23); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 202302); opts.CPlusPlus26 = 1; - EXPECT_EQ(opts.getCPlusPlusLangStd(), - clang::LangOptionsBase::CPlusPlusLangStd::CPP_26); + EXPECT_EQ(opts.getCPlusPlusLangStd(), 202400); EXPECT_FALSE(opts.getCLangStd()); } From 28ff3a416e6f0f0610714d242b2286282b5c3783 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 15 Oct 2025 11:22:36 +0100 Subject: [PATCH 6/6] fixup! check optional --- clang/lib/Frontend/InitPreprocessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 63da549da6a49..baad63179d89a 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -459,8 +459,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, // value is, are implementation-defined. // (Removed in C++20.) if (!LangOpts.CPlusPlus) { - Builder.defineMacro("__STDC_VERSION__", - Twine(*LangOpts.getCLangStd()) + "L"); + if (std::optional Lang = LangOpts.getCLangStd()) + Builder.defineMacro("__STDC_VERSION__", Twine(*Lang) + "L"); } else { // -- __cplusplus Builder.defineMacro("__cplusplus",