keyword_modifier_set.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_
  5. #define CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_
  6. #include <optional>
  7. #include "common/enum_mask_base.h"
  8. #include "toolchain/sem_ir/name_scope.h"
  9. namespace Carbon::Check {
  10. // The order of modifiers. Each of these corresponds to a group on
  11. // KeywordModifierSet, and can be used as an array index.
  12. enum class ModifierOrder : int8_t { Access, Extern, Extend, Decl, Last = Decl };
  13. // A single X-macro to cover modifier groups. These are split out to make groups
  14. // clearer.
  15. #define CARBON_KEYWORD_MODIFIER_SET(X) \
  16. /* At most one of these access modifiers allowed for a given declaration, \
  17. * and if present it must be first. */ \
  18. X(Private) \
  19. X(Protected) \
  20. \
  21. /* Extern is standalone. */ \
  22. X(Extern) \
  23. \
  24. /* Extend can be combined with Final, but no others in the group below. */ \
  25. X(Extend) \
  26. \
  27. /* At most one of these declaration modifiers allowed for a given \
  28. * declaration. */ \
  29. X(Abstract) \
  30. X(Base) \
  31. X(Default) \
  32. X(Export) \
  33. X(Final) \
  34. X(Impl) \
  35. X(Override) \
  36. X(Returned) \
  37. X(Virtual)
  38. // We expect this to grow, so are using a bigger size than needed.
  39. CARBON_DEFINE_RAW_ENUM_MASK(KeywordModifierSet, uint32_t) {
  40. CARBON_KEYWORD_MODIFIER_SET(CARBON_RAW_ENUM_MASK_ENUMERATOR)
  41. };
  42. // Represents a set of keyword modifiers, using a separate bit per modifier.
  43. class KeywordModifierSet : public CARBON_ENUM_MASK_BASE(KeywordModifierSet) {
  44. public:
  45. CARBON_KEYWORD_MODIFIER_SET(CARBON_ENUM_MASK_CONSTANT_DECL)
  46. // Sets of modifiers.
  47. static const KeywordModifierSet Access;
  48. static const KeywordModifierSet Class;
  49. static const KeywordModifierSet Method;
  50. static const KeywordModifierSet ImplDecl;
  51. static const KeywordModifierSet Interface;
  52. static const KeywordModifierSet Decl;
  53. // Return a builder that returns the new enumeration type once a series of
  54. // mapping `Case`s and a final `Default` are provided. For example:
  55. // ```
  56. // auto e = set.ToEnum<SomeEnum>()
  57. // .Case(KeywordModifierSet::A, SomeEnum::A)
  58. // .Case(KeywordModifierSet::B, SomeEnum::B)
  59. // .Default(SomeEnum::DefaultValue);
  60. // ```
  61. template <typename T>
  62. auto ToEnum() const -> auto {
  63. class Converter {
  64. public:
  65. explicit Converter(const KeywordModifierSet& set) : set_(set) {}
  66. auto Case(KeywordModifierSet other, T result) -> Converter& {
  67. if (set_.HasAnyOf(other)) {
  68. result_ = result;
  69. }
  70. return *this;
  71. }
  72. auto Default(T default_value) -> T {
  73. if (result_) {
  74. return *result_;
  75. }
  76. return default_value;
  77. }
  78. private:
  79. const KeywordModifierSet& set_;
  80. std::optional<T> result_;
  81. };
  82. return Converter(*this);
  83. }
  84. // Returns the access kind from modifiers.
  85. auto GetAccessKind() const -> SemIR::AccessKind {
  86. if (HasAnyOf(KeywordModifierSet::Protected)) {
  87. return SemIR::AccessKind::Protected;
  88. }
  89. if (HasAnyOf(KeywordModifierSet::Private)) {
  90. return SemIR::AccessKind::Private;
  91. }
  92. return SemIR::AccessKind::Public;
  93. }
  94. };
  95. #define CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE(X) \
  96. CARBON_ENUM_MASK_CONSTANT_DEFINITION(KeywordModifierSet, X)
  97. CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE)
  98. #undef CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE
  99. inline constexpr KeywordModifierSet KeywordModifierSet::Access(Private |
  100. Protected);
  101. inline constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base);
  102. inline constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract |
  103. Override |
  104. Virtual);
  105. inline constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend |
  106. Final);
  107. inline constexpr KeywordModifierSet KeywordModifierSet::Interface(Default |
  108. Final);
  109. inline constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method |
  110. Impl | Interface |
  111. Export | Returned);
  112. static_assert(
  113. !KeywordModifierSet::Access.HasAnyOf(KeywordModifierSet::Extern) &&
  114. !(KeywordModifierSet::Access | KeywordModifierSet::Extern |
  115. KeywordModifierSet::Extend)
  116. .HasAnyOf(KeywordModifierSet::Decl),
  117. "Order-related sets must not overlap");
  118. #define CARBON_KEYWORD_MODIFIER_SET_IN_GROUP(Modifier) \
  119. static_assert((KeywordModifierSet::Access | KeywordModifierSet::Extern | \
  120. KeywordModifierSet::Extend | KeywordModifierSet::Decl) \
  121. .HasAnyOf(KeywordModifierSet::Modifier), \
  122. "Modifier missing from all modifier sets: " #Modifier);
  123. CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_IN_GROUP)
  124. #undef CARBON_KEYWORD_MODIFIER_SET_IN_GROUP
  125. } // namespace Carbon::Check
  126. #endif // CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_