Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C2y instead of C_2y?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, C2y seems more make sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applicable now that we use LangStandards.def

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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cpp26 or Cxx26 instead of the underscore?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applicable now that we use LangStandards.def

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,
Expand Down Expand Up @@ -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<CLangStd> GetCLangStd() const;

/// Returns the most applicable C++ standard-compliant language
/// version code.
/// If none could be determined, returns \ref std::nullopt.
std::optional<CPlusPlusLangStd> GetCPlusPlusLangStd() const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we are very inconsistent about this, but functions should start with a lowercase letter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, it's an LLDB convention I carried over

};

/// Floating point control options
Expand Down
46 changes: 46 additions & 0 deletions clang/lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,49 @@ LLVM_DUMP_METHOD void FPOptionsOverride::dump() {
#include "clang/Basic/FPOptions.def"
llvm::errs() << "\n";
}

std::optional<clang::LangOptionsBase::CPlusPlusLangStd>
LangOptions::GetCPlusPlusLangStd() const {
if (!CPlusPlus)
return std::nullopt;

if (CPlusPlus26)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we could also generate this mapping if we hooked up the LangOptions name to the LangStandard macros. My concern is: every time there's a new standard version, we need to update a lot of places; reducing that isn't a bad idea. However, that's also probably a more involved refactoring, so I don't insist (or could be done in a follow-up).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah gotcha. Yea that would be neat

That'll probably take me a bit because I'm not sure off the top what's involved. To unblock the debug-info changes I'll go ahead and merge this. Then will give the refactoring a shot. Thanks for the reviews!

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<clang::LangOptionsBase::CLangStd>
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;
}
37 changes: 4 additions & 33 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_distinct_clang_unittest(BasicTests
DiagnosticTest.cpp
FileEntryTest.cpp
FileManagerTest.cpp
LangOptionsTest.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, yes!

LineOffsetMappingTest.cpp
OffloadArchTest.cpp
SanitizersTest.cpp
Expand Down
62 changes: 62 additions & 0 deletions clang/unittests/Basic/LangOptionsTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===- 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());
}
} // namespace
Loading