mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
Add framework for the extern keyword. (#3755)
This doesn't add full support. I'm separating it out to make the effects of the modifier changes clearer for review. I'm restructuring a little with the expectation that we'll have some more categories of modifier keywords in the future (similar to `extern`, these may not be in a "set" such as access), and thus easily scaling up to a few more would be useful.
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "toolchain/check/modifiers.h"
|
||||
|
||||
#include "toolchain/check/decl_state.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
static auto ReportNotAllowed(Context& context, Parse::NodeId modifier_node,
|
||||
@@ -24,22 +26,16 @@ static auto ReportNotAllowed(Context& context, Parse::NodeId modifier_node,
|
||||
diag.Emit();
|
||||
}
|
||||
|
||||
auto LimitModifiersOnDecl(Context& context, KeywordModifierSet allowed,
|
||||
Lex::TokenKind decl_kind) -> void {
|
||||
auto& s = context.decl_state_stack().innermost();
|
||||
auto not_allowed = s.modifier_set & ~allowed;
|
||||
if (!!(not_allowed & KeywordModifierSet::Access)) {
|
||||
ReportNotAllowed(context, s.saw_access_modifier, decl_kind, "",
|
||||
Parse::NodeId::Invalid);
|
||||
not_allowed = not_allowed & ~KeywordModifierSet::Access;
|
||||
s.saw_access_modifier = Parse::NodeId::Invalid;
|
||||
// Returns the KeywordModifierSet corresponding to the ModifierOrder entry.
|
||||
static auto ModifierOrderAsSet(ModifierOrder order) -> KeywordModifierSet {
|
||||
switch (order) {
|
||||
case ModifierOrder::Access:
|
||||
return KeywordModifierSet::Access;
|
||||
case ModifierOrder::Extern:
|
||||
return KeywordModifierSet::Extern;
|
||||
case ModifierOrder::Decl:
|
||||
return KeywordModifierSet::Decl;
|
||||
}
|
||||
if (!!not_allowed) {
|
||||
ReportNotAllowed(context, s.saw_decl_modifier, decl_kind, "",
|
||||
Parse::NodeId::Invalid);
|
||||
s.saw_decl_modifier = Parse::NodeId::Invalid;
|
||||
}
|
||||
s.modifier_set &= allowed;
|
||||
}
|
||||
|
||||
auto ForbidModifiersOnDecl(Context& context, KeywordModifierSet forbidden,
|
||||
@@ -48,23 +44,26 @@ auto ForbidModifiersOnDecl(Context& context, KeywordModifierSet forbidden,
|
||||
Parse::NodeId context_node) -> void {
|
||||
auto& s = context.decl_state_stack().innermost();
|
||||
auto not_allowed = s.modifier_set & forbidden;
|
||||
if (!!(not_allowed & KeywordModifierSet::Access)) {
|
||||
ReportNotAllowed(context, s.saw_access_modifier, decl_kind, context_string,
|
||||
context_node);
|
||||
not_allowed = not_allowed & ~KeywordModifierSet::Access;
|
||||
s.saw_access_modifier = Parse::NodeId::Invalid;
|
||||
if (!not_allowed) {
|
||||
return;
|
||||
}
|
||||
if (!!not_allowed) {
|
||||
ReportNotAllowed(context, s.saw_decl_modifier, decl_kind, context_string,
|
||||
context_node);
|
||||
s.saw_decl_modifier = Parse::NodeId::Invalid;
|
||||
|
||||
for (auto order_index = 0;
|
||||
order_index <= static_cast<int8_t>(ModifierOrder::Last); ++order_index) {
|
||||
auto order = static_cast<ModifierOrder>(order_index);
|
||||
if (!!(not_allowed & ModifierOrderAsSet(order))) {
|
||||
ReportNotAllowed(context, s.modifier_node_id(order), decl_kind,
|
||||
context_string, context_node);
|
||||
s.set_modifier_node_id(order, Parse::NodeId::Invalid);
|
||||
}
|
||||
}
|
||||
s.modifier_set = s.modifier_set & ~forbidden;
|
||||
|
||||
s.modifier_set &= ~forbidden;
|
||||
}
|
||||
|
||||
// Returns the instruction that owns the given scope, or Invalid if the scope is
|
||||
// not associated with an instruction.
|
||||
auto GetScopeInstId(Context& context, SemIR::NameScopeId scope_id)
|
||||
static auto GetScopeInstId(Context& context, SemIR::NameScopeId scope_id)
|
||||
-> SemIR::InstId {
|
||||
if (!scope_id.is_valid()) {
|
||||
return SemIR::InstId::Invalid;
|
||||
@@ -74,7 +73,7 @@ auto GetScopeInstId(Context& context, SemIR::NameScopeId scope_id)
|
||||
|
||||
// Returns the instruction that owns the given scope, or Invalid if the scope is
|
||||
// not associated with an instruction.
|
||||
auto GetScopeInst(Context& context, SemIR::NameScopeId scope_id)
|
||||
static auto GetScopeInst(Context& context, SemIR::NameScopeId scope_id)
|
||||
-> std::optional<SemIR::Inst> {
|
||||
auto inst_id = GetScopeInstId(context, scope_id);
|
||||
if (!inst_id.is_valid()) {
|
||||
@@ -109,7 +108,6 @@ auto CheckAccessModifiersOnDecl(Context& context, Lex::TokenKind decl_kind,
|
||||
", `private` is only allowed on class members and at file scope");
|
||||
}
|
||||
|
||||
// Rules for abstract, virtual, and impl, which are only allowed in classes.
|
||||
auto CheckMethodModifiersOnFunction(Context& context,
|
||||
SemIR::NameScopeId target_scope_id)
|
||||
-> void {
|
||||
|
||||
Reference in New Issue
Block a user