keyword_modifier_set.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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 {
  13. Access,
  14. Extern,
  15. Extend,
  16. Decl,
  17. Evaluation,
  18. Last = Evaluation
  19. };
  20. // A single X-macro to cover modifier groups. These are split out to make groups
  21. // clearer.
  22. #define CARBON_KEYWORD_MODIFIER_SET(X) \
  23. /* At most one of these access modifiers allowed for a given declaration, \
  24. * and if present it must be first. */ \
  25. X(Private) \
  26. X(Protected) \
  27. \
  28. /* Extern is standalone. */ \
  29. X(Extern) \
  30. \
  31. /* Extend can be combined with Final, but no others in the group below. */ \
  32. X(Extend) \
  33. \
  34. /* At most one of these declaration modifiers allowed for a given \
  35. * declaration. */ \
  36. X(Abstract) \
  37. X(Base) \
  38. X(Default) \
  39. X(Export) \
  40. X(Final) \
  41. X(Impl) \
  42. X(Override) \
  43. X(Returned) \
  44. X(Virtual) \
  45. \
  46. /* Eval and MustEval are mutually exclusive. */ \
  47. X(Eval) \
  48. X(MustEval)
  49. // We expect this to grow, so are using a bigger size than needed.
  50. CARBON_DEFINE_RAW_ENUM_MASK(KeywordModifierSet, uint32_t) {
  51. CARBON_KEYWORD_MODIFIER_SET(CARBON_RAW_ENUM_MASK_ENUMERATOR)
  52. };
  53. // Represents a set of keyword modifiers, using a separate bit per modifier.
  54. class KeywordModifierSet : public CARBON_ENUM_MASK_BASE(KeywordModifierSet) {
  55. public:
  56. CARBON_KEYWORD_MODIFIER_SET(CARBON_ENUM_MASK_CONSTANT_DECL)
  57. // Sets of modifiers.
  58. static const KeywordModifierSet Access;
  59. static const KeywordModifierSet Class;
  60. static const KeywordModifierSet Method;
  61. static const KeywordModifierSet ImplDecl;
  62. static const KeywordModifierSet Interface;
  63. static const KeywordModifierSet Evaluation;
  64. static const KeywordModifierSet Decl;
  65. // Return a builder that returns the new enumeration type once a series of
  66. // mapping `Case`s and a final `Default` are provided. For example:
  67. // ```
  68. // auto e = set.ToEnum<SomeEnum>()
  69. // .Case(KeywordModifierSet::A, SomeEnum::A)
  70. // .Case(KeywordModifierSet::B, SomeEnum::B)
  71. // .Default(SomeEnum::DefaultValue);
  72. // ```
  73. template <typename T>
  74. auto ToEnum() const -> auto {
  75. class Converter {
  76. public:
  77. explicit Converter(const KeywordModifierSet& set) : set_(set) {}
  78. auto Case(KeywordModifierSet other, T result) -> Converter& {
  79. if (set_.HasAnyOf(other)) {
  80. result_ = result;
  81. }
  82. return *this;
  83. }
  84. auto Default(T default_value) -> T {
  85. if (result_) {
  86. return *result_;
  87. }
  88. return default_value;
  89. }
  90. private:
  91. const KeywordModifierSet& set_;
  92. std::optional<T> result_;
  93. };
  94. return Converter(*this);
  95. }
  96. // Returns the access kind from modifiers.
  97. auto GetAccessKind() const -> SemIR::AccessKind {
  98. if (HasAnyOf(KeywordModifierSet::Protected)) {
  99. return SemIR::AccessKind::Protected;
  100. }
  101. if (HasAnyOf(KeywordModifierSet::Private)) {
  102. return SemIR::AccessKind::Private;
  103. }
  104. return SemIR::AccessKind::Public;
  105. }
  106. };
  107. #define CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE(X) \
  108. CARBON_ENUM_MASK_CONSTANT_DEFINITION(KeywordModifierSet, X)
  109. CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE)
  110. #undef CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE
  111. inline constexpr KeywordModifierSet KeywordModifierSet::Access(Private |
  112. Protected);
  113. inline constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base);
  114. inline constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract |
  115. Override |
  116. Virtual);
  117. inline constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend |
  118. Final);
  119. inline constexpr KeywordModifierSet KeywordModifierSet::Interface(Default |
  120. Final);
  121. inline constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method |
  122. Impl | Interface |
  123. Export | Returned);
  124. inline constexpr KeywordModifierSet KeywordModifierSet::Evaluation(Eval |
  125. MustEval);
  126. // TODO: This and the ordering checking logic in handle_modifiers.cpp are
  127. // becoming unwieldy. Find a better representation.
  128. static_assert(
  129. !KeywordModifierSet::Access.HasAnyOf(KeywordModifierSet::Extern) &&
  130. !(KeywordModifierSet::Access | KeywordModifierSet::Extern |
  131. KeywordModifierSet::Extend)
  132. .HasAnyOf(KeywordModifierSet::Decl) &&
  133. !(KeywordModifierSet::Access | KeywordModifierSet::Extern |
  134. KeywordModifierSet::Decl)
  135. .HasAnyOf(KeywordModifierSet::Evaluation),
  136. "Order-related sets must not overlap");
  137. #define CARBON_KEYWORD_MODIFIER_SET_IN_GROUP(Modifier) \
  138. static_assert((KeywordModifierSet::Access | KeywordModifierSet::Extern | \
  139. KeywordModifierSet::Extend | KeywordModifierSet::Decl | \
  140. KeywordModifierSet::Evaluation) \
  141. .HasAnyOf(KeywordModifierSet::Modifier), \
  142. "Modifier missing from all modifier sets: " #Modifier);
  143. CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_IN_GROUP)
  144. #undef CARBON_KEYWORD_MODIFIER_SET_IN_GROUP
  145. } // namespace Carbon::Check
  146. #endif // CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_