From b300f36e6f44d19177934f178b545dde3104ec2b Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 14 Nov 2025 05:50:56 -0800 Subject: [PATCH] Use `inline constexpr` where appropriate. (#6374) This fixes various violations of C++'s One Definition Rule, where we accidentally gave the same static data member multiple definitions in different translation units. Clang happens to emit such definitions with weak linkage, which allows us to get away with this without link errors, but it's still formally incorrect. Also switch keyword order around for a handful of instances of `constexpr inline`, per agreement in open discussion. This happens to reduce the size of a `-c dbg` toolchain binary by 7.2 MiB, presumably by making more of our symbols and especially debug info discardable. --- common/enum_base.h | 2 +- common/raw_hashtable.h | 2 +- common/raw_hashtable_metadata_group.h | 2 +- toolchain/base/int.h | 7 +-- toolchain/base/llvm_tools.h | 4 +- toolchain/base/runtime_sources.bzl | 22 ++++---- toolchain/base/value_ids.h | 15 +++--- toolchain/check/convert.h | 2 +- toolchain/check/eval_inst.h | 6 +-- toolchain/check/keyword_modifier_set.h | 22 ++++---- toolchain/check/node_stack.h | 2 +- toolchain/check/scope_index.h | 2 +- toolchain/lex/token_index.h | 4 +- toolchain/lex/token_kind.h | 4 +- toolchain/lex/tokenized_buffer.h | 4 +- toolchain/parse/node_kind.h | 2 +- toolchain/sem_ir/ids.h | 75 ++++++++++++++------------ toolchain/sem_ir/impl.h | 2 +- 18 files changed, 96 insertions(+), 83 deletions(-) diff --git a/common/enum_base.h b/common/enum_base.h index f4c805cc576a..03fdb9e79b5f 100644 --- a/common/enum_base.h +++ b/common/enum_base.h @@ -210,7 +210,7 @@ class EnumBase : public Printable { // Use this immediately after the Carbon enum class body to define each named // constant. #define CARBON_ENUM_CONSTANT_DEFINITION(EnumClassName, Name) \ - constexpr EnumClassName EnumClassName::Name = \ + inline constexpr EnumClassName EnumClassName::Name = \ EnumClassName::Make(RawEnumType::Name); // Use this in the `.cpp` file for an enum class to start the definition of the diff --git a/common/raw_hashtable.h b/common/raw_hashtable.h index ae642a615f63..613990af72ae 100644 --- a/common/raw_hashtable.h +++ b/common/raw_hashtable.h @@ -147,7 +147,7 @@ namespace Carbon::RawHashtable { // If allocating storage, allocate a minimum of one cacheline of group metadata // or a minimum of one group, whichever is larger. -constexpr ssize_t MinAllocatedSize = std::max(64, MaxGroupSize); +inline constexpr ssize_t MinAllocatedSize = std::max(64, MaxGroupSize); // An entry in the hashtable storage of a `KeyT` and `ValueT` object. // diff --git a/common/raw_hashtable_metadata_group.h b/common/raw_hashtable_metadata_group.h index 1d87d879b4f6..48bd11fb9a16 100644 --- a/common/raw_hashtable_metadata_group.h +++ b/common/raw_hashtable_metadata_group.h @@ -43,7 +43,7 @@ namespace Carbon::RawHashtable { // We define a constant max group size. The particular group size used in // practice may vary, but we want to have some upper bound used to ensure // memory allocation is done consistently across different architectures. -constexpr ssize_t MaxGroupSize = 16; +inline constexpr ssize_t MaxGroupSize = 16; // This takes a collection of bits representing the results of looking for a // particular tag in this metadata group and determines the first position with diff --git a/toolchain/base/int.h b/toolchain/base/int.h index c1b2f9affe81..c75d7bdd798a 100644 --- a/toolchain/base/int.h +++ b/toolchain/base/int.h @@ -206,12 +206,12 @@ class IntId : public Printable { int32_t id_; }; -constexpr IntId IntId::None(IntId::NoneId); +inline constexpr IntId IntId::None(IntId::NoneId); // Note that we initialize the `None` index in a constexpr context which // ensures there is no UB in forming it. This helps ensure all the ID -> index // conversions are correct because the `None` ID is at the limit of that range. -constexpr int32_t IntId::NoneIndex = None.AsIndex(); +inline constexpr int32_t IntId::NoneIndex = None.AsIndex(); // A canonicalizing value store with deep optimizations for integers. // @@ -428,7 +428,8 @@ class IntStore { CanonicalValueStore values_; }; -constexpr IntStore::APIntId IntStore::APIntId::None(IntId::None.AsIndex()); +inline constexpr IntStore::APIntId IntStore::APIntId::None( + IntId::None.AsIndex()); } // namespace Carbon diff --git a/toolchain/base/llvm_tools.h b/toolchain/base/llvm_tools.h index fe05158e9eb0..e82178ce5187 100644 --- a/toolchain/base/llvm_tools.h +++ b/toolchain/base/llvm_tools.h @@ -63,12 +63,12 @@ class LLVMTool : public CARBON_ENUM_BASE(LLVMTool) { CARBON_ENUM_CONSTANT_DEFINITION(LLVMTool, Identifier) #include "toolchain/base/llvm_tools.def" -constexpr LLVMTool LLVMTool::ToolsStorage[] = { +inline constexpr LLVMTool LLVMTool::ToolsStorage[] = { #define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) \ LLVMTool::Identifier, #include "toolchain/base/llvm_tools.def" }; -constexpr llvm::ArrayRef LLVMTool::Tools = ToolsStorage; +inline constexpr llvm::ArrayRef LLVMTool::Tools = ToolsStorage; } // namespace Carbon diff --git a/toolchain/base/runtime_sources.bzl b/toolchain/base/runtime_sources.bzl index 34d6a7201755..4212cfc5044a 100644 --- a/toolchain/base/runtime_sources.bzl +++ b/toolchain/base/runtime_sources.bzl @@ -54,34 +54,34 @@ _TEMPLATE = """ namespace Carbon::RuntimeSources {{ -constexpr inline llvm::StringLiteral CrtBegin = {crtbegin_src}; -constexpr inline llvm::StringLiteral CrtEnd = {crtend_src}; +inline constexpr llvm::StringLiteral CrtBegin = {crtbegin_src}; +inline constexpr llvm::StringLiteral CrtEnd = {crtend_src}; -constexpr inline llvm::StringLiteral BuiltinsGenericSrcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsGenericSrcs[] = {{ {generic_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsMacosSrcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsMacosSrcs[] = {{ {macos_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsBf16Srcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsBf16Srcs[] = {{ {bf16_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsTfSrcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsTfSrcs[] = {{ {tf_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsX86ArchSrcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsX86ArchSrcs[] = {{ {x86_arch_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsX86Fp80Srcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsX86Fp80Srcs[] = {{ {x86_fp80_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsAarch64Srcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsAarch64Srcs[] = {{ {aarch64_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsX86_64Srcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsX86_64Srcs[] = {{ {x86_64_srcs} }}; -constexpr inline llvm::StringLiteral BuiltinsI386Srcs[] = {{ +inline constexpr llvm::StringLiteral BuiltinsI386Srcs[] = {{ {i386_srcs} }}; diff --git a/toolchain/base/value_ids.h b/toolchain/base/value_ids.h index e3c90a60df58..37369218cf16 100644 --- a/toolchain/base/value_ids.h +++ b/toolchain/base/value_ids.h @@ -49,7 +49,7 @@ struct FloatId : public IdBase { static const FloatId None; using IdBase::IdBase; }; -constexpr FloatId FloatId::None(FloatId::NoneIndex); +inline constexpr FloatId FloatId::None(FloatId::NoneIndex); // Corresponds to a Real value. struct RealId : public IdBase { @@ -62,7 +62,7 @@ struct RealId : public IdBase { static const RealId None; using IdBase::IdBase; }; -constexpr RealId RealId::None(RealId::NoneIndex); +inline constexpr RealId RealId::None(RealId::NoneIndex); // Corresponds to StringRefs for identifiers. // @@ -73,7 +73,7 @@ struct IdentifierId : public IdBase { static const IdentifierId None; using IdBase::IdBase; }; -constexpr IdentifierId IdentifierId::None(IdentifierId::NoneIndex); +inline constexpr IdentifierId IdentifierId::None(IdentifierId::NoneIndex); // The name of a package, which is either an identifier or the special `Core` // package name. @@ -122,9 +122,10 @@ struct PackageNameId : public IdBase { } } }; -constexpr PackageNameId PackageNameId::None(PackageNameId::NoneIndex); -constexpr PackageNameId PackageNameId::Core(PackageNameId::NoneIndex - 1); -constexpr PackageNameId PackageNameId::Cpp(PackageNameId::NoneIndex - 2); +inline constexpr PackageNameId PackageNameId::None(PackageNameId::NoneIndex); +inline constexpr PackageNameId PackageNameId::Core(PackageNameId::NoneIndex - + 1); +inline constexpr PackageNameId PackageNameId::Cpp(PackageNameId::NoneIndex - 2); // Corresponds to StringRefs for string literals. struct StringLiteralValueId : public IdBase { @@ -132,7 +133,7 @@ struct StringLiteralValueId : public IdBase { static const StringLiteralValueId None; using IdBase::IdBase; }; -constexpr StringLiteralValueId StringLiteralValueId::None( +inline constexpr StringLiteralValueId StringLiteralValueId::None( StringLiteralValueId::NoneIndex); } // namespace Carbon diff --git a/toolchain/check/convert.h b/toolchain/check/convert.h index 254863a37620..1a7a4ab29b4e 100644 --- a/toolchain/check/convert.h +++ b/toolchain/check/convert.h @@ -149,7 +149,7 @@ struct TypeExpr { SemIR::TypeId type_id; }; -constexpr inline TypeExpr TypeExpr::None = {.inst_id = SemIR::TypeInstId::None, +inline constexpr TypeExpr TypeExpr::None = {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None}; // Converts an expression for use as a type. diff --git a/toolchain/check/eval_inst.h b/toolchain/check/eval_inst.h index 5c54b0ee3174..3d878d1dd773 100644 --- a/toolchain/check/eval_inst.h +++ b/toolchain/check/eval_inst.h @@ -86,13 +86,13 @@ class ConstantEvalResult { bool same_phase_as_inst_; }; -constexpr ConstantEvalResult ConstantEvalResult::Error = +inline constexpr ConstantEvalResult ConstantEvalResult::Error = Existing(SemIR::ErrorInst::ConstantId); -constexpr ConstantEvalResult ConstantEvalResult::NotConstant = +inline constexpr ConstantEvalResult ConstantEvalResult::NotConstant = ConstantEvalResult(SemIR::ConstantId::NotConstant); -constexpr ConstantEvalResult ConstantEvalResult::TODO = NotConstant; +inline constexpr ConstantEvalResult ConstantEvalResult::TODO = NotConstant; // Implementation details to compute the type of the `EvalConstantInst` // functions. diff --git a/toolchain/check/keyword_modifier_set.h b/toolchain/check/keyword_modifier_set.h index a8c4f39196ae..88d13d5da35f 100644 --- a/toolchain/check/keyword_modifier_set.h +++ b/toolchain/check/keyword_modifier_set.h @@ -112,15 +112,19 @@ class KeywordModifierSet : public CARBON_ENUM_MASK_BASE(KeywordModifierSet) { CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE) #undef CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE -constexpr KeywordModifierSet KeywordModifierSet::Access(Private | Protected); -constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base); -constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract | Override | - Virtual); -constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend | Final); -constexpr KeywordModifierSet KeywordModifierSet::Interface(Default | Final); -constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method | Impl | - Interface | Export | - Returned); +inline constexpr KeywordModifierSet KeywordModifierSet::Access(Private | + Protected); +inline constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base); +inline constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract | + Override | + Virtual); +inline constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend | + Final); +inline constexpr KeywordModifierSet KeywordModifierSet::Interface(Default | + Final); +inline constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method | + Impl | Interface | + Export | Returned); static_assert( !KeywordModifierSet::Access.HasAnyOf(KeywordModifierSet::Extern) && diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index b783c3cce076..e1659c14311a 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -637,7 +637,7 @@ class NodeStack { llvm::SmallVector stack_; }; -constexpr NodeStack::IdKindTableType NodeStack::IdKindTable = +inline constexpr NodeStack::IdKindTableType NodeStack::IdKindTable = ComputeIdKindTable(); inline auto NodeStack::PopExprWithNodeId() diff --git a/toolchain/check/scope_index.h b/toolchain/check/scope_index.h index d8d71b5cd370..09154eb9fbe0 100644 --- a/toolchain/check/scope_index.h +++ b/toolchain/check/scope_index.h @@ -24,7 +24,7 @@ struct ScopeIndex : public IndexBase { using IndexBase::IndexBase; }; -constexpr ScopeIndex ScopeIndex::Package = ScopeIndex(0); +inline constexpr ScopeIndex ScopeIndex::Package = ScopeIndex(0); } // namespace Carbon::Check diff --git a/toolchain/lex/token_index.h b/toolchain/lex/token_index.h index 8536df5375b9..2a4a7a30b768 100644 --- a/toolchain/lex/token_index.h +++ b/toolchain/lex/token_index.h @@ -40,8 +40,8 @@ struct TokenIndex : public IndexBase { using IndexBase::IndexBase; }; -constexpr TokenIndex TokenIndex::None(TokenIndex::NoneIndex); -constexpr TokenIndex TokenIndex::FirstNonCommentToken(1); +inline constexpr TokenIndex TokenIndex::None(TokenIndex::NoneIndex); +inline constexpr TokenIndex TokenIndex::FirstNonCommentToken(1); // A lightweight handle to a lexed token in a `TokenizedBuffer` whose kind is // known to be `Kind`. diff --git a/toolchain/lex/token_kind.h b/toolchain/lex/token_kind.h index bfe1a49fcebf..352a5ae3bf0e 100644 --- a/toolchain/lex/token_kind.h +++ b/toolchain/lex/token_kind.h @@ -130,11 +130,11 @@ class TokenKind : public CARBON_ENUM_BASE(TokenKind) { CARBON_ENUM_CONSTANT_DEFINITION(TokenKind, TokenName) #include "toolchain/lex/token_kind.def" -constexpr TokenKind TokenKind::KeywordTokensStorage[] = { +inline constexpr TokenKind TokenKind::KeywordTokensStorage[] = { #define CARBON_KEYWORD_TOKEN(TokenName, Spelling) TokenKind::TokenName, #include "toolchain/lex/token_kind.def" }; -constexpr llvm::ArrayRef TokenKind::KeywordTokens = +inline constexpr llvm::ArrayRef TokenKind::KeywordTokens = KeywordTokensStorage; } // namespace Carbon::Lex diff --git a/toolchain/lex/tokenized_buffer.h b/toolchain/lex/tokenized_buffer.h index 75a8d5188d71..5484c9a1b2f2 100644 --- a/toolchain/lex/tokenized_buffer.h +++ b/toolchain/lex/tokenized_buffer.h @@ -56,7 +56,7 @@ struct LineIndex : public IndexBase { using IndexBase::IndexBase; }; -constexpr LineIndex LineIndex::None(NoneIndex); +inline constexpr LineIndex LineIndex::None(NoneIndex); // A comment, which can be a block of lines. These are tracked separately from // tokens because they don't affect parse; if they were part of tokens, we'd @@ -79,7 +79,7 @@ struct CommentIndex : public IndexBase { using IndexBase::IndexBase; }; -constexpr CommentIndex CommentIndex::None(NoneIndex); +inline constexpr CommentIndex CommentIndex::None(NoneIndex); // Random-access iterator over comments within the buffer. using CommentIterator = IndexIterator; diff --git a/toolchain/parse/node_kind.h b/toolchain/parse/node_kind.h index cee4259f9891..682ed9ce68a4 100644 --- a/toolchain/parse/node_kind.h +++ b/toolchain/parse/node_kind.h @@ -80,7 +80,7 @@ class NodeKind : public CARBON_ENUM_BASE(NodeKind) { CARBON_ENUM_CONSTANT_DEFINITION(NodeKind, Name) #include "toolchain/parse/node_kind.def" -constexpr int NodeKind::ValidCount = 0 +inline constexpr int NodeKind::ValidCount = 0 #define CARBON_PARSE_NODE_KIND(Name) +1 #include "toolchain/parse/node_kind.def" ; diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 2758b1064238..3ee4796f08df 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -42,8 +42,9 @@ struct InstId : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr InstId InstId::InitTombstone = InstId(NoneIndex - 1); -constexpr InstId InstId::ImplWitnessTablePlaceholder = InstId(NoneIndex - 2); +inline constexpr InstId InstId::InitTombstone = InstId(NoneIndex - 1); +inline constexpr InstId InstId::ImplWitnessTablePlaceholder = + InstId(NoneIndex - 2); // An InstId whose value is a type. The fact it's a type must be validated // before construction, and this allows that validation to be represented in the @@ -63,7 +64,8 @@ struct TypeInstId : public InstId { : InstId(id) {} }; -constexpr TypeInstId TypeInstId::None = TypeInstId::UnsafeMake(InstId::None); +inline constexpr TypeInstId TypeInstId::None = + TypeInstId::UnsafeMake(InstId::None); // An InstId whose type is known to be T. The fact it's a type must be validated // before construction, and this allows that validation to be represented in the @@ -89,7 +91,7 @@ struct KnownInstId : public InstId { }; template -constexpr KnownInstId KnownInstId::None = +inline constexpr KnownInstId KnownInstId::None = KnownInstId::UnsafeMake(InstId::None); // An ID of an instruction that is referenced absolutely by another instruction. @@ -249,7 +251,8 @@ struct ConstantId : public IdBase { static constexpr int32_t FirstSymbolicId = NoneIndex - 2; }; -constexpr ConstantId ConstantId::NotConstant = ConstantId(NotConstantIndex); +inline constexpr ConstantId ConstantId::NotConstant = + ConstantId(NotConstantIndex); // The ID of a `EntityName`. struct EntityNameId : public IdBase { @@ -311,7 +314,7 @@ struct CheckIRId : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr CheckIRId CheckIRId::Cpp = CheckIRId(NoneIndex - 1); +inline constexpr CheckIRId CheckIRId::Cpp = CheckIRId(NoneIndex - 1); // The ID of a `Class`. struct ClassId : public IdBase { @@ -444,7 +447,7 @@ struct GenericInstIndex : public IndexBase { static constexpr int32_t FirstDefinitionIndex = NoneIndex - 1; }; -constexpr GenericInstIndex GenericInstIndex::None = +inline constexpr GenericInstIndex GenericInstIndex::None = GenericInstIndex::MakeNone(); // The ID of an `ImportIR` within the set of imported IRs, both direct and @@ -465,8 +468,8 @@ struct ImportIRId : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr ImportIRId ImportIRId::ApiForImpl = ImportIRId(0); -constexpr ImportIRId ImportIRId::Cpp = ImportIRId(ApiForImpl.index + 1); +inline constexpr ImportIRId ImportIRId::ApiForImpl = ImportIRId(0); +inline constexpr ImportIRId ImportIRId::Cpp = ImportIRId(ApiForImpl.index + 1); // A boolean value. struct BoolValue : public IdBase { @@ -490,8 +493,8 @@ struct BoolValue : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr BoolValue BoolValue::False = BoolValue(0); -constexpr BoolValue BoolValue::True = BoolValue(1); +inline constexpr BoolValue BoolValue::False = BoolValue(0); +inline constexpr BoolValue BoolValue::True = BoolValue(1); // A character literal value as a unicode codepoint. struct CharId : public IdBase { @@ -521,8 +524,8 @@ struct IntKind : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr IntKind IntKind::Unsigned = IntKind(0); -constexpr IntKind IntKind::Signed = IntKind(1); +inline constexpr IntKind IntKind::Unsigned = IntKind(0); +inline constexpr IntKind IntKind::Signed = IntKind(1); // A float kind value. This describes the semantics of the floating-point type. // This represents very similar information to the bit-width, but is more @@ -560,15 +563,15 @@ struct FloatKind : public IdBase { auto Semantics() const -> const llvm::fltSemantics&; }; -constexpr FloatKind FloatKind::None = FloatKind(NoneIndex); +inline constexpr FloatKind FloatKind::None = FloatKind(NoneIndex); -constexpr FloatKind FloatKind::Binary16 = FloatKind(0); -constexpr FloatKind FloatKind::Binary32 = FloatKind(1); -constexpr FloatKind FloatKind::Binary64 = FloatKind(2); -constexpr FloatKind FloatKind::Binary128 = FloatKind(3); -constexpr FloatKind FloatKind::BFloat16 = FloatKind(4); -constexpr FloatKind FloatKind::X87Float80 = FloatKind(5); -constexpr FloatKind FloatKind::PPCFloat128 = FloatKind(6); +inline constexpr FloatKind FloatKind::Binary16 = FloatKind(0); +inline constexpr FloatKind FloatKind::Binary32 = FloatKind(1); +inline constexpr FloatKind FloatKind::Binary64 = FloatKind(2); +inline constexpr FloatKind FloatKind::Binary128 = FloatKind(3); +inline constexpr FloatKind FloatKind::BFloat16 = FloatKind(4); +inline constexpr FloatKind FloatKind::X87Float80 = FloatKind(5); +inline constexpr FloatKind FloatKind::PPCFloat128 = FloatKind(6); // An X-macro for special names. Uses should look like: // @@ -654,14 +657,14 @@ struct NameId : public IdBase { // Define the special `static const NameId` values. #define CARBON_SPECIAL_NAME_ID_FOR_DEF(Name) \ - constexpr NameId NameId::Name = \ + inline constexpr NameId NameId::Name = \ NameId(NoneIndex - 1 - static_cast(NameId::SpecialNameId::Name)); CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_DEF) #undef CARBON_SPECIAL_NAME_ID_FOR_DEF // Count non-index values, including `None` and special names. #define CARBON_SPECIAL_NAME_ID_FOR_COUNT(...) +1 -constexpr int NameId::NonIndexValueCount = +inline constexpr int NameId::NonIndexValueCount = 1 CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_COUNT); #undef CARBON_SPECIAL_NAME_ID_FOR_COUNT @@ -675,7 +678,7 @@ struct NameScopeId : public IdBase { using IdBase::IdBase; }; -constexpr NameScopeId NameScopeId::Package = NameScopeId(0); +inline constexpr NameScopeId NameScopeId::Package = NameScopeId(0); // The ID of an `InstId` block. struct InstBlockId : public IdBase { @@ -705,11 +708,12 @@ struct InstBlockId : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr InstBlockId InstBlockId::Empty = InstBlockId(0); -constexpr InstBlockId InstBlockId::Exports = InstBlockId(1); -constexpr InstBlockId InstBlockId::Imports = InstBlockId(2); -constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(3); -constexpr InstBlockId InstBlockId::Unreachable = InstBlockId(NoneIndex - 1); +inline constexpr InstBlockId InstBlockId::Empty = InstBlockId(0); +inline constexpr InstBlockId InstBlockId::Exports = InstBlockId(1); +inline constexpr InstBlockId InstBlockId::Imports = InstBlockId(2); +inline constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(3); +inline constexpr InstBlockId InstBlockId::Unreachable = + InstBlockId(NoneIndex - 1); // Contains either an `InstBlockId` value, an error value, or // `InstBlockId::None`. @@ -817,7 +821,8 @@ struct StructTypeFieldsId : public IdBase { using IdBase::IdBase; }; -constexpr StructTypeFieldsId StructTypeFieldsId::Empty = StructTypeFieldsId(0); +inline constexpr StructTypeFieldsId StructTypeFieldsId::Empty = + StructTypeFieldsId(0); // The ID of a `CustomLayout` block. struct CustomLayoutId : public IdBase { @@ -837,7 +842,7 @@ struct CustomLayoutId : public IdBase { using IdBase::IdBase; }; -constexpr CustomLayoutId CustomLayoutId::Empty = CustomLayoutId(0); +inline constexpr CustomLayoutId CustomLayoutId::Empty = CustomLayoutId(0); // The ID of a type. struct TypeId : public IdBase { @@ -906,8 +911,10 @@ struct LibraryNameId : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; -constexpr LibraryNameId LibraryNameId::Default = LibraryNameId(NoneIndex - 1); -constexpr LibraryNameId LibraryNameId::Error = LibraryNameId(NoneIndex - 2); +inline constexpr LibraryNameId LibraryNameId::Default = + LibraryNameId(NoneIndex - 1); +inline constexpr LibraryNameId LibraryNameId::Error = + LibraryNameId(NoneIndex - 2); // The ID of an `ImportIRInst`. struct ImportIRInstId : public IdBase { @@ -940,7 +947,7 @@ struct RequireImplsBlockId : public IdBase { using IdBase::IdBase; }; -constexpr RequireImplsBlockId RequireImplsBlockId::Empty = +inline constexpr RequireImplsBlockId RequireImplsBlockId::Empty = RequireImplsBlockId(0); // A SemIR location used as the location of instructions. This contains either a diff --git a/toolchain/sem_ir/impl.h b/toolchain/sem_ir/impl.h index 49e38f142963..e4b2039b96b1 100644 --- a/toolchain/sem_ir/impl.h +++ b/toolchain/sem_ir/impl.h @@ -214,7 +214,7 @@ class ImplStore { llvm::SmallVector> lookup_buckets_; }; -constexpr inline ImplStore::ImplOrLookupBucketId +inline constexpr ImplStore::ImplOrLookupBucketId ImplStore::ImplOrLookupBucketId::None(NoneIndex); } // namespace Carbon::SemIR