decl_state.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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_DECL_STATE_H_
  5. #define CARBON_TOOLCHAIN_CHECK_DECL_STATE_H_
  6. #include "llvm/ADT/BitmaskEnum.h"
  7. #include "toolchain/parse/node_ids.h"
  8. namespace Carbon::Check {
  9. LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
  10. // Represents a set of keyword modifiers, using a separate bit per modifier.
  11. //
  12. // We expect this to grow, so are using a bigger size than needed.
  13. // NOLINTNEXTLINE(performance-enum-size)
  14. enum class KeywordModifierSet : uint32_t {
  15. // At most one of these access modifiers allowed for a given declaration,
  16. // and if present it must be first:
  17. Private = 1 << 0,
  18. Protected = 1 << 1,
  19. // Extern is standalone.
  20. Extern = 1 << 2,
  21. // At most one of these declaration modifiers allowed for a given
  22. // declaration:
  23. Abstract = 1 << 3,
  24. Base = 1 << 4,
  25. Default = 1 << 5,
  26. Export = 1 << 6,
  27. Extend = 1 << 7,
  28. Final = 1 << 8,
  29. Impl = 1 << 9,
  30. Virtual = 1 << 10,
  31. // Sets of modifiers:
  32. Access = Private | Protected,
  33. Class = Abstract | Base,
  34. Method = Abstract | Impl | Virtual,
  35. ImplDecl = Extend | Final,
  36. Interface = Default | Final,
  37. Decl = Class | Method | ImplDecl | Interface | Export,
  38. None = 0,
  39. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Virtual)
  40. };
  41. inline constexpr auto operator!(KeywordModifierSet k) -> bool {
  42. return !static_cast<uint32_t>(k);
  43. }
  44. // The order of modifiers. Each of these corresponds to a group on
  45. // KeywordModifierSet, and can be used as an array index.
  46. enum class ModifierOrder : int8_t { Access, Extern, Decl, Last = Decl };
  47. static_assert(!(KeywordModifierSet::Access & KeywordModifierSet::Extern) &&
  48. !((KeywordModifierSet::Access | KeywordModifierSet::Extern) &
  49. KeywordModifierSet::Decl),
  50. "Order-related sets must not overlap");
  51. static_assert(~KeywordModifierSet::None ==
  52. (KeywordModifierSet::Access | KeywordModifierSet::Extern |
  53. KeywordModifierSet::Decl),
  54. "Modifier missing from all modifier sets");
  55. // State stored for each declaration we are currently in: the kind of
  56. // declaration and the keyword modifiers that apply to that declaration.
  57. struct DeclState {
  58. // The kind of declaration.
  59. enum DeclKind : int8_t {
  60. FileScope,
  61. Adapt,
  62. Alias,
  63. Base,
  64. Class,
  65. Constraint,
  66. Export,
  67. Fn,
  68. Impl,
  69. Import,
  70. Interface,
  71. Let,
  72. Namespace,
  73. PackageOrLibrary,
  74. Var
  75. };
  76. explicit DeclState(DeclKind decl_kind) : kind(decl_kind) {}
  77. auto modifier_node_id(ModifierOrder order) -> Parse::NodeId {
  78. return ordered_modifier_node_ids[static_cast<int8_t>(order)];
  79. }
  80. auto set_modifier_node_id(ModifierOrder order, Parse::NodeId node_id)
  81. -> void {
  82. ordered_modifier_node_ids[static_cast<int8_t>(order)] = node_id;
  83. }
  84. DeclKind kind;
  85. // Nodes of modifiers on this declaration, in expected order. `Invalid` if no
  86. // modifier of that kind is present.
  87. Parse::NodeId
  88. ordered_modifier_node_ids[static_cast<int8_t>(ModifierOrder::Decl) + 1] =
  89. {Parse::NodeId::Invalid, Parse::NodeId::Invalid,
  90. Parse::NodeId::Invalid};
  91. // Invariant: contains just the modifiers represented by `saw_*_modifier`.
  92. KeywordModifierSet modifier_set = KeywordModifierSet::None;
  93. };
  94. // Stack of `DeclState` values, representing all the declarations we are
  95. // currently nested within.
  96. // Invariant: Bottom of the stack always has a "DeclState::FileScope" entry.
  97. class DeclStateStack {
  98. public:
  99. DeclStateStack() { stack_.emplace_back(DeclState::FileScope); }
  100. // Enters a declaration of kind `k`.
  101. auto Push(DeclState::DeclKind k) -> void { stack_.emplace_back(k); }
  102. // Gets the state of declaration at the top of the stack -- the innermost
  103. // declaration currently being processed.
  104. auto innermost() -> DeclState& { return stack_.back(); }
  105. // Exits a declaration of kind `k`.
  106. auto Pop(DeclState::DeclKind k) -> void {
  107. CARBON_CHECK(stack_.back().kind == k)
  108. << "Found: " << stack_.back().kind << " expected: " << k;
  109. stack_.pop_back();
  110. CARBON_CHECK(!stack_.empty());
  111. }
  112. private:
  113. llvm::SmallVector<DeclState> stack_;
  114. };
  115. } // namespace Carbon::Check
  116. #endif // CARBON_TOOLCHAIN_CHECK_DECL_STATE_H_