mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:30:12 +01:00
This adds the `static` token to the lexer and parses it as a modifier. In check, `FullPatternStack::Kind::FieldDecl` is now used for both static and non-static vars. Static vars get treated basically the same as `NameBindingDecl`s. Global initialization is used for static var initializers. To make the necessary stack information available to `pattern_match.cpp`, the `full_pattern_stack` and `decl_introducer_state_stack` are now popped later in `handle_let_and_var.cpp`. In lowering, each class's body is checked for `VarStorage` insts and lowered the same as global vars.
177 lines
7.9 KiB
C++
177 lines
7.9 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_
|
|
|
|
#include <optional>
|
|
|
|
#include "common/enum_mask_base.h"
|
|
#include "toolchain/sem_ir/name_scope.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
// The order of modifiers. Each of these corresponds to a group on
|
|
// KeywordModifierSet, and can be used as an array index.
|
|
enum class ModifierOrder : int8_t {
|
|
Access,
|
|
Extern,
|
|
Extend,
|
|
Decl,
|
|
Static,
|
|
Evaluation,
|
|
Last = Evaluation
|
|
};
|
|
|
|
// A single X-macro to cover modifier groups. These are split out to make groups
|
|
// clearer.
|
|
#define CARBON_KEYWORD_MODIFIER_SET(X) \
|
|
/* At most one of these access modifiers allowed for a given declaration, \
|
|
* and if present it must be first. */ \
|
|
X(Private) \
|
|
X(Protected) \
|
|
\
|
|
/* Extern is standalone. */ \
|
|
X(Extern) \
|
|
\
|
|
/* Extend can be combined with Final, but no others in the group below. */ \
|
|
X(Extend) \
|
|
\
|
|
/* At most one of these declaration modifiers allowed for a given \
|
|
* declaration. */ \
|
|
X(Abstract) \
|
|
X(Base) \
|
|
X(Default) \
|
|
X(Export) \
|
|
X(Final) \
|
|
X(Impl) \
|
|
X(Override) \
|
|
X(Returned) \
|
|
X(Virtual) \
|
|
\
|
|
/* Static is standalone. */ \
|
|
X(Static) \
|
|
\
|
|
/* Eval and MustEval are mutually exclusive. */ \
|
|
X(Eval) \
|
|
X(MustEval)
|
|
|
|
// We expect this to grow, so are using a bigger size than needed.
|
|
CARBON_DEFINE_RAW_ENUM_MASK(KeywordModifierSet, uint32_t) {
|
|
CARBON_KEYWORD_MODIFIER_SET(CARBON_RAW_ENUM_MASK_ENUMERATOR)
|
|
};
|
|
|
|
// Represents a set of keyword modifiers, using a separate bit per modifier.
|
|
class KeywordModifierSet : public CARBON_ENUM_MASK_BASE(KeywordModifierSet) {
|
|
public:
|
|
CARBON_KEYWORD_MODIFIER_SET(CARBON_ENUM_MASK_CONSTANT_DECL)
|
|
|
|
// Sets of modifiers.
|
|
static const KeywordModifierSet Access;
|
|
static const KeywordModifierSet Class;
|
|
static const KeywordModifierSet Method;
|
|
static const KeywordModifierSet ImplDecl;
|
|
static const KeywordModifierSet Interface;
|
|
static const KeywordModifierSet Evaluation;
|
|
static const KeywordModifierSet Decl;
|
|
|
|
// Return a builder that returns the new enumeration type once a series of
|
|
// mapping `Case`s and a final `Default` are provided. For example:
|
|
// ```
|
|
// auto e = set.ToEnum<SomeEnum>()
|
|
// .Case(KeywordModifierSet::A, SomeEnum::A)
|
|
// .Case(KeywordModifierSet::B, SomeEnum::B)
|
|
// .Default(SomeEnum::DefaultValue);
|
|
// ```
|
|
template <typename T>
|
|
auto ToEnum() const -> auto {
|
|
class Converter {
|
|
public:
|
|
explicit Converter(const KeywordModifierSet& set) : set_(set) {}
|
|
|
|
auto Case(KeywordModifierSet other, T result) -> Converter& {
|
|
if (set_.HasAnyOf(other)) {
|
|
result_ = result;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
auto Default(T default_value) -> T {
|
|
if (result_) {
|
|
return *result_;
|
|
}
|
|
return default_value;
|
|
}
|
|
|
|
private:
|
|
const KeywordModifierSet& set_;
|
|
std::optional<T> result_;
|
|
};
|
|
return Converter(*this);
|
|
}
|
|
|
|
// Returns the access kind from modifiers.
|
|
auto GetAccessKind() const -> SemIR::AccessKind {
|
|
if (HasAnyOf(KeywordModifierSet::Override)) {
|
|
// TODO: Instead of hiding `override fn`s, we should expose them but make
|
|
// calls that we cannot statically devirtualize call the base class
|
|
// version (the one whose signature is in the vtable).
|
|
return SemIR::AccessKind::Hidden;
|
|
}
|
|
if (HasAnyOf(KeywordModifierSet::Protected)) {
|
|
return SemIR::AccessKind::Protected;
|
|
}
|
|
if (HasAnyOf(KeywordModifierSet::Private)) {
|
|
return SemIR::AccessKind::Private;
|
|
}
|
|
return SemIR::AccessKind::Public;
|
|
}
|
|
};
|
|
|
|
#define CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE(X) \
|
|
CARBON_ENUM_MASK_CONSTANT_DEFINITION(KeywordModifierSet, X)
|
|
CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE)
|
|
#undef CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE
|
|
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::Access(Private |
|
|
Protected);
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base);
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract |
|
|
Override |
|
|
Virtual);
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend |
|
|
Final);
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::Interface(Default |
|
|
Final);
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method |
|
|
Impl | Interface |
|
|
Export | Returned);
|
|
inline constexpr KeywordModifierSet KeywordModifierSet::Evaluation(Eval |
|
|
MustEval);
|
|
|
|
// TODO: This and the ordering checking logic in handle_modifiers.cpp are
|
|
// becoming unwieldy. Find a better representation.
|
|
static_assert(
|
|
!KeywordModifierSet::Access.HasAnyOf(KeywordModifierSet::Extern) &&
|
|
!(KeywordModifierSet::Access | KeywordModifierSet::Extern |
|
|
KeywordModifierSet::Extend)
|
|
.HasAnyOf(KeywordModifierSet::Decl) &&
|
|
!(KeywordModifierSet::Access | KeywordModifierSet::Extern |
|
|
KeywordModifierSet::Decl)
|
|
.HasAnyOf(KeywordModifierSet::Evaluation),
|
|
"Order-related sets must not overlap");
|
|
|
|
#define CARBON_KEYWORD_MODIFIER_SET_IN_GROUP(Modifier) \
|
|
static_assert((KeywordModifierSet::Access | KeywordModifierSet::Extern | \
|
|
KeywordModifierSet::Extend | KeywordModifierSet::Decl | \
|
|
KeywordModifierSet::Evaluation | KeywordModifierSet::Static) \
|
|
.HasAnyOf(KeywordModifierSet::Modifier), \
|
|
"Modifier missing from all modifier sets: " #Modifier);
|
|
CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_IN_GROUP)
|
|
#undef CARBON_KEYWORD_MODIFIER_SET_IN_GROUP
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_
|