decl_state.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. Extend = 1 << 6,
  27. Final = 1 << 7,
  28. Impl = 1 << 8,
  29. Virtual = 1 << 9,
  30. // Sets of modifiers:
  31. Access = Private | Protected,
  32. Class = Abstract | Base,
  33. Method = Abstract | Impl | Virtual,
  34. ImplDecl = Extend | Final,
  35. Interface = Default | Final,
  36. Decl = Class | Method | ImplDecl | Interface,
  37. None = 0,
  38. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Virtual)
  39. };
  40. inline constexpr auto operator!(KeywordModifierSet k) -> bool {
  41. return !static_cast<uint32_t>(k);
  42. }
  43. // The order of modifiers. Each of these corresponds to a group on
  44. // KeywordModifierSet, and can be used as an array index.
  45. enum class ModifierOrder : int8_t { Access, Extern, Decl, Last = Decl };
  46. static_assert(!(KeywordModifierSet::Access & KeywordModifierSet::Extern) &&
  47. !((KeywordModifierSet::Access | KeywordModifierSet::Extern) &
  48. KeywordModifierSet::Decl),
  49. "Order-related sets must not overlap");
  50. // State stored for each declaration we are currently in: the kind of
  51. // declaration and the keyword modifiers that apply to that declaration.
  52. struct DeclState {
  53. // The kind of declaration.
  54. enum DeclKind : int8_t {
  55. FileScope,
  56. Alias,
  57. Base,
  58. Class,
  59. Constraint,
  60. Fn,
  61. Impl,
  62. Interface,
  63. Let,
  64. Namespace,
  65. Var
  66. };
  67. explicit DeclState(DeclKind decl_kind) : kind(decl_kind) {}
  68. auto modifier_node_id(ModifierOrder order) -> Parse::NodeId {
  69. return ordered_modifier_node_ids[static_cast<int8_t>(order)];
  70. }
  71. auto set_modifier_node_id(ModifierOrder order, Parse::NodeId node_id)
  72. -> void {
  73. ordered_modifier_node_ids[static_cast<int8_t>(order)] = node_id;
  74. }
  75. DeclKind kind;
  76. // Nodes of modifiers on this declaration, in expected order. `Invalid` if no
  77. // modifier of that kind is present.
  78. Parse::NodeId
  79. ordered_modifier_node_ids[static_cast<int8_t>(ModifierOrder::Decl) + 1] =
  80. {Parse::NodeId::Invalid, Parse::NodeId::Invalid,
  81. Parse::NodeId::Invalid};
  82. // Invariant: contains just the modifiers represented by `saw_*_modifier`.
  83. KeywordModifierSet modifier_set = KeywordModifierSet::None;
  84. };
  85. // Stack of `DeclState` values, representing all the declarations we are
  86. // currently nested within.
  87. // Invariant: Bottom of the stack always has a "DeclState::FileScope" entry.
  88. class DeclStateStack {
  89. public:
  90. DeclStateStack() { stack_.emplace_back(DeclState::FileScope); }
  91. // Enters a declaration of kind `k`.
  92. auto Push(DeclState::DeclKind k) -> void { stack_.emplace_back(k); }
  93. // Gets the state of declaration at the top of the stack -- the innermost
  94. // declaration currently being processed.
  95. auto innermost() -> DeclState& { return stack_.back(); }
  96. // Exits a declaration of kind `k`.
  97. auto Pop(DeclState::DeclKind k) -> void {
  98. CARBON_CHECK(stack_.back().kind == k)
  99. << "Found: " << stack_.back().kind << " expected: " << k;
  100. stack_.pop_back();
  101. CARBON_CHECK(!stack_.empty());
  102. }
  103. private:
  104. llvm::SmallVector<DeclState> stack_;
  105. };
  106. } // namespace Carbon::Check
  107. #endif // CARBON_TOOLCHAIN_CHECK_DECL_STATE_H_