decl_state.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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/tree.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. // At most one of these declaration modifiers allowed for a given
  20. // declaration:
  21. Abstract = 1 << 2,
  22. Base = 1 << 3,
  23. Default = 1 << 4,
  24. Extend = 1 << 5,
  25. Final = 1 << 6,
  26. Impl = 1 << 7,
  27. Virtual = 1 << 8,
  28. // Sets of modifiers:
  29. Access = Private | Protected,
  30. Class = Abstract | Base,
  31. Method = Abstract | Impl | Virtual,
  32. Interface = Default | Final,
  33. None = 0,
  34. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Virtual)
  35. };
  36. inline auto operator!(KeywordModifierSet k) -> bool {
  37. return !static_cast<unsigned>(k);
  38. }
  39. // State stored for each declaration we are currently in: the kind of
  40. // declaration and the keyword modifiers that apply to that declaration.
  41. struct DeclState {
  42. // The kind of declaration.
  43. enum DeclKind : int8_t {
  44. FileScope,
  45. Base,
  46. Class,
  47. Constraint,
  48. Fn,
  49. Interface,
  50. Let,
  51. Namespace,
  52. Var
  53. };
  54. explicit DeclState(DeclKind decl_kind, Parse::NodeId parse_node)
  55. : kind(decl_kind), first_node(parse_node) {}
  56. DeclKind kind;
  57. // Nodes of modifiers on this declaration. `Invalid` if no modifier of that
  58. // kind is present.
  59. Parse::NodeId saw_access_modifier = Parse::NodeId::Invalid;
  60. Parse::NodeId saw_decl_modifier = Parse::NodeId::Invalid;
  61. // Invariant: contains just the modifiers represented by `saw_access_modifier`
  62. // and `saw_other_modifier`.
  63. KeywordModifierSet modifier_set = KeywordModifierSet::None;
  64. // Node corresponding to the first token of the declaration.
  65. Parse::NodeId first_node;
  66. };
  67. // Stack of `DeclState` values, representing all the declarations we are
  68. // currently nested within.
  69. // Invariant: Bottom of the stack always has a "DeclState::FileScope" entry.
  70. class DeclStateStack {
  71. public:
  72. DeclStateStack() {
  73. stack_.emplace_back(DeclState::FileScope, Parse::NodeId::Invalid);
  74. }
  75. // Enters a declaration of kind `k`, with `parse_node` for the introducer
  76. // token.
  77. auto Push(DeclState::DeclKind k, Parse::NodeId parse_node) -> void {
  78. stack_.push_back(DeclState(k, parse_node));
  79. }
  80. // Gets the state of declaration at the top of the stack -- the innermost
  81. // declaration currently being processed.
  82. auto innermost() -> DeclState& { return stack_.back(); }
  83. // Exits a declaration of kind `k`.
  84. auto Pop(DeclState::DeclKind k) -> void {
  85. CARBON_CHECK(stack_.back().kind == k)
  86. << "Found: " << stack_.back().kind << " expected: " << k;
  87. stack_.pop_back();
  88. CARBON_CHECK(!stack_.empty());
  89. }
  90. private:
  91. llvm::SmallVector<DeclState> stack_;
  92. };
  93. } // namespace Carbon::Check
  94. #endif // CARBON_TOOLCHAIN_CHECK_DECL_STATE_H_