handle_modifier.cpp 4.2 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. #include "toolchain/check/context.h"
  5. #include "toolchain/lex/token_kind.h"
  6. namespace Carbon::Check {
  7. CARBON_DIAGNOSTIC(ModifierPrevious, Note, "`{0}` previously appeared here.",
  8. Lex::TokenKind);
  9. static auto EmitRepeatedDiagnostic(Context& context, Parse::NodeId first_node,
  10. Parse::NodeId second_node) -> void {
  11. CARBON_DIAGNOSTIC(ModifierRepeated, Error, "`{0}` repeated on declaration.",
  12. Lex::TokenKind);
  13. context.emitter()
  14. .Build(second_node, ModifierRepeated, context.token_kind(second_node))
  15. .Note(first_node, ModifierPrevious, context.token_kind(first_node))
  16. .Emit();
  17. }
  18. static auto EmitNotAllowedWithDiagnostic(Context& context,
  19. Parse::NodeId first_node,
  20. Parse::NodeId second_node) -> void {
  21. CARBON_DIAGNOSTIC(ModifierNotAllowedWith, Error,
  22. "`{0}` not allowed on declaration with `{1}`.",
  23. Lex::TokenKind, Lex::TokenKind);
  24. context.emitter()
  25. .Build(second_node, ModifierNotAllowedWith,
  26. context.token_kind(second_node), context.token_kind(first_node))
  27. .Note(first_node, ModifierPrevious, context.token_kind(first_node))
  28. .Emit();
  29. }
  30. static auto GetAccessModifierEnum(Lex::TokenKind token_kind)
  31. -> KeywordModifierSet {
  32. switch (token_kind) {
  33. case Lex::TokenKind::Private:
  34. return KeywordModifierSet::Private;
  35. case Lex::TokenKind::Protected:
  36. return KeywordModifierSet::Protected;
  37. default:
  38. CARBON_FATAL() << "Unhandled access modifier keyword";
  39. }
  40. }
  41. auto HandleAccessModifierKeyword(Context& context, Parse::NodeId parse_node)
  42. -> bool {
  43. auto keyword = GetAccessModifierEnum(
  44. context.tokens().GetKind(context.parse_tree().node_token(parse_node)));
  45. auto& s = context.decl_state_stack().innermost();
  46. if (!!(s.modifier_set & keyword)) {
  47. EmitRepeatedDiagnostic(context, s.saw_access_modifier, parse_node);
  48. } else if (s.saw_access_modifier.is_valid()) {
  49. EmitNotAllowedWithDiagnostic(context, s.saw_access_modifier, parse_node);
  50. } else if (s.saw_decl_modifier.is_valid()) {
  51. CARBON_DIAGNOSTIC(ModifierMustAppearBefore, Error,
  52. "`{0}` must appear before `{1}`.", Lex::TokenKind,
  53. Lex::TokenKind);
  54. context.emitter()
  55. .Build(parse_node, ModifierMustAppearBefore,
  56. context.token_kind(parse_node),
  57. context.token_kind(s.saw_decl_modifier))
  58. .Note(s.saw_decl_modifier, ModifierPrevious,
  59. context.token_kind(s.saw_decl_modifier))
  60. .Emit();
  61. } else {
  62. s.modifier_set |= keyword;
  63. s.saw_access_modifier = parse_node;
  64. s.first_node = parse_node;
  65. }
  66. return true;
  67. }
  68. static auto GetDeclModifierEnum(Lex::TokenKind token_kind)
  69. -> KeywordModifierSet {
  70. switch (token_kind) {
  71. case Lex::TokenKind::Abstract:
  72. return KeywordModifierSet::Abstract;
  73. case Lex::TokenKind::Base:
  74. return KeywordModifierSet::Base;
  75. case Lex::TokenKind::Default:
  76. return KeywordModifierSet::Default;
  77. case Lex::TokenKind::Final:
  78. return KeywordModifierSet::Final;
  79. case Lex::TokenKind::Impl:
  80. return KeywordModifierSet::Impl;
  81. case Lex::TokenKind::Virtual:
  82. return KeywordModifierSet::Virtual;
  83. default:
  84. CARBON_FATAL() << "Unhandled declaration modifier keyword";
  85. }
  86. }
  87. auto HandleDeclModifierKeyword(Context& context, Parse::NodeId parse_node)
  88. -> bool {
  89. auto keyword = GetDeclModifierEnum(
  90. context.tokens().GetKind(context.parse_tree().node_token(parse_node)));
  91. auto& s = context.decl_state_stack().innermost();
  92. if (!!(s.modifier_set & keyword)) {
  93. EmitRepeatedDiagnostic(context, s.saw_decl_modifier, parse_node);
  94. } else if (s.saw_decl_modifier.is_valid()) {
  95. EmitNotAllowedWithDiagnostic(context, s.saw_decl_modifier, parse_node);
  96. } else {
  97. s.modifier_set |= keyword;
  98. s.saw_decl_modifier = parse_node;
  99. if (s.saw_access_modifier == Parse::NodeId::Invalid) {
  100. s.first_node = parse_node;
  101. }
  102. }
  103. return true;
  104. }
  105. } // namespace Carbon::Check