Skip to content

[clang] Refactor LangOptions to specify AST effect as X macro arg #146766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
787 changes: 368 additions & 419 deletions clang/include/clang/Basic/LangOptions.def

Large diffs are not rendered by default.

31 changes: 24 additions & 7 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ class LangOptionsBase {
using RoundingMode = llvm::RoundingMode;
using CFBranchLabelSchemeKind = clang::CFBranchLabelSchemeKind;

/// For ASTs produced with different option value, signifies their level of
/// compatibility.
enum class CompatibilityKind {
/// Does affect the construction of the AST in a way that does prevent
/// module interoperability.
NotCompatible,
/// Does affect the construction of the AST in a way that doesn't prevent
/// interoperability (that is, the value can be different between an
/// explicit module and the user of that module).
Compatible,
/// Does not affect the construction of the AST in any way (that is, the
/// value can be different between an implicit module and the user of that
/// module).
Benign,
};

enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };

Expand Down Expand Up @@ -486,16 +502,17 @@ class LangOptionsBase {
};

// Define simple language options (with no accessors).
#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
unsigned Name : Bits;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description)
#include "clang/Basic/LangOptions.def"

protected:
// Define language options of enumeration type. These are private, and will
// have accessors (below).
#define LANGOPT(Name, Bits, Default, Description)
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
LLVM_PREFERRED_TYPE(Type) \
#define LANGOPT(Name, Bits, Default, Compatibility, Description)
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
LLVM_PREFERRED_TYPE(Type) \
unsigned Name : Bits;
#include "clang/Basic/LangOptions.def"
};
Expand Down Expand Up @@ -655,8 +672,8 @@ class LangOptions : public LangOptionsBase {
LangStandard::Kind LangStd = LangStandard::lang_unspecified);

// Define accessors/mutators for language options of enumeration type.
#define LANGOPT(Name, Bits, Default, Description)
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
#define LANGOPT(Name, Bits, Default, Compatibility, Description)
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
Type get##Name() const { return static_cast<Type>(Name); } \
void set##Name(Type Value) { \
assert(static_cast<unsigned>(Value) < (1u << Bits)); \
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@
using namespace clang;

LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified) {
#define LANGOPT(Name, Bits, Default, Description) Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
#define LANGOPT(Name, Bits, Default, Compatibility, Description) Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
set##Name(Default);
#include "clang/Basic/LangOptions.def"
}

void LangOptions::resetNonModularOptions() {
#define LANGOPT(Name, Bits, Default, Description)
#define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default;
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Name = static_cast<unsigned>(Default);
#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
if constexpr (CompatibilityKind::Compatibility == CompatibilityKind::Benign) \
Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
if constexpr (CompatibilityKind::Compatibility == CompatibilityKind::Benign) \
Name = static_cast<unsigned>(Default);
#include "clang/Basic/LangOptions.def"

// Reset "benign" options with implied values (Options.td ImpliedBy relations)
Expand Down
13 changes: 8 additions & 5 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5178,11 +5178,14 @@ std::string CompilerInvocation::getModuleHash() const {
HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);

// Extend the signature with the language options
#define LANGOPT(Name, Bits, Default, Description) HBuilder.add(LangOpts->Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
// FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.
using CK = LangOptions::CompatibilityKind;
#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) \
HBuilder.add(LangOpts->Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) \
HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
#include "clang/Basic/LangOptions.def"

HBuilder.addRange(getLangOpts().ModuleFeatures);
Expand Down
16 changes: 10 additions & 6 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,16 +643,20 @@ namespace {
bool ReadLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override {
// FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.
using CK = LangOptions::CompatibilityKind;

Out.indent(2) << "Language options:\n";
#define LANGOPT(Name, Bits, Default, Description) \
#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) \
DUMP_BOOLEAN(LangOpts.Name, Description);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Out.indent(4) << Description << ": " \
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) \
Out.indent(4) << Description << ": " \
<< static_cast<unsigned>(LangOpts.get##Name()) << "\n";
#define VALUE_LANGOPT(Name, Bits, Default, Description) \
#define VALUE_LANGOPT(Name, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) \
Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"

if (!LangOpts.ModuleFeatures.empty()) {
Expand Down
86 changes: 46 additions & 40 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,51 +278,57 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename,
DiagnosticsEngine *Diags,
bool AllowCompatibleDifferences = true) {
#define LANGOPT(Name, Bits, Default, Description) \
if (ExistingLangOpts.Name != LangOpts.Name) { \
if (Diags) { \
if (Bits == 1) \
Diags->Report(diag::err_ast_file_langopt_mismatch) \
<< Description << LangOpts.Name << ExistingLangOpts.Name \
<< ModuleFilename; \
else \
Diags->Report(diag::err_ast_file_langopt_value_mismatch) \
<< Description << ModuleFilename; \
// FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.
using CK = LangOptions::CompatibilityKind;

#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) { \
if ((CK::Compatibility == CK::NotCompatible) || \
(CK::Compatibility == CK::Compatible && \
!AllowCompatibleDifferences)) { \
if (ExistingLangOpts.Name != LangOpts.Name) { \
if (Diags) { \
if (Bits == 1) \
Diags->Report(diag::err_ast_file_langopt_mismatch) \
<< Description << LangOpts.Name << ExistingLangOpts.Name \
<< ModuleFilename; \
else \
Diags->Report(diag::err_ast_file_langopt_value_mismatch) \
<< Description << ModuleFilename; \
} \
return true; \
} \
} \
return true; \
}

#define VALUE_LANGOPT(Name, Bits, Default, Description) \
if (ExistingLangOpts.Name != LangOpts.Name) { \
if (Diags) \
Diags->Report(diag::err_ast_file_langopt_value_mismatch) \
<< Description << ModuleFilename; \
return true; \
#define VALUE_LANGOPT(Name, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) { \
if ((CK::Compatibility == CK::NotCompatible) || \
(CK::Compatibility == CK::Compatible && \
!AllowCompatibleDifferences)) { \
if (ExistingLangOpts.Name != LangOpts.Name) { \
if (Diags) \
Diags->Report(diag::err_ast_file_langopt_value_mismatch) \
<< Description << ModuleFilename; \
return true; \
} \
} \
}

#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) { \
if (Diags) \
Diags->Report(diag::err_ast_file_langopt_value_mismatch) \
<< Description << ModuleFilename; \
return true; \
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
if constexpr (CK::Compatibility != CK::Benign) { \
if ((CK::Compatibility == CK::NotCompatible) || \
(CK::Compatibility == CK::Compatible && \
!AllowCompatibleDifferences)) { \
if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) { \
if (Diags) \
Diags->Report(diag::err_ast_file_langopt_value_mismatch) \
<< Description << ModuleFilename; \
return true; \
} \
} \
}

#define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \
if (!AllowCompatibleDifferences) \
LANGOPT(Name, Bits, Default, Description)

#define COMPATIBLE_ENUM_LANGOPT(Name, Bits, Default, Description) \
if (!AllowCompatibleDifferences) \
ENUM_LANGOPT(Name, Bits, Default, Description)

#define COMPATIBLE_VALUE_LANGOPT(Name, Bits, Default, Description) \
if (!AllowCompatibleDifferences) \
VALUE_LANGOPT(Name, Bits, Default, Description)

#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#define BENIGN_VALUE_LANGOPT(Name, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"

if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) {
Expand Down Expand Up @@ -6353,9 +6359,9 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
bool AllowCompatibleDifferences) {
LangOptions LangOpts;
unsigned Idx = 0;
#define LANGOPT(Name, Bits, Default, Description) \
#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
LangOpts.Name = Record[Idx++];
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
#include "clang/Basic/LangOptions.def"
#define SANITIZER(NAME, ID) \
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1612,9 +1612,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
// Language options.
Record.clear();
const LangOptions &LangOpts = PP.getLangOpts();
#define LANGOPT(Name, Bits, Default, Description) \
#define LANGOPT(Name, Bits, Default, Compatibility, Description) \
Record.push_back(LangOpts.Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));
#include "clang/Basic/LangOptions.def"
#define SANITIZER(NAME, ID) \
Expand Down
Loading