mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:00:11 +01:00
Move logic to merge class and function definitions onto Class and Function, matching how we handle merging for EntityWithParamsBase. Assisted-by: Gemini via Antigravity
139 lines
4.8 KiB
C++
139 lines
4.8 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_SEM_IR_CLASS_H_
|
|
#define CARBON_TOOLCHAIN_SEM_IR_CLASS_H_
|
|
|
|
#include "common/map.h"
|
|
#include "toolchain/base/value_store.h"
|
|
#include "toolchain/sem_ir/entity_with_params_base.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::SemIR {
|
|
|
|
// Class-specific fields.
|
|
struct ClassFields {
|
|
enum InheritanceKind : int8_t {
|
|
// `abstract class`
|
|
Abstract,
|
|
// `base class`
|
|
Base,
|
|
// `class`
|
|
Final,
|
|
};
|
|
|
|
// The following members always have values, and do not change throughout the
|
|
// lifetime of the class.
|
|
|
|
// The class type, which is the type of `Self` in the class definition.
|
|
TypeId self_type_id;
|
|
// The kind of inheritance that this class supports.
|
|
// TODO: The rules here are not yet decided. See #3384.
|
|
InheritanceKind inheritance_kind;
|
|
|
|
// Whether this class or any base class has at least one virtual function.
|
|
bool is_dynamic = false;
|
|
|
|
// Whether the class's fields have been exported to C++.
|
|
bool fields_exported = false;
|
|
|
|
// The following members are set at the `{` of the class definition.
|
|
|
|
// The class scope.
|
|
NameScopeId scope_id = NameScopeId::None;
|
|
// The first block of the class body.
|
|
// TODO: Handle control flow in the class body, such as if-expressions.
|
|
InstBlockId body_block_id = InstBlockId::None;
|
|
|
|
// The following members are accumulated throughout the class definition.
|
|
|
|
// The adapted type declaration, if any. `None` if the class is not an
|
|
// adapter. This is an AdaptDecl instruction.
|
|
// TODO: Consider sharing the storage for `adapt_id` and `base_id`. A class
|
|
// can't have both.
|
|
InstId adapt_id = InstId::None;
|
|
// The base class declaration. `None` if the class has no base class. This is
|
|
// a BaseDecl instruction.
|
|
InstId base_id = InstId::None;
|
|
|
|
// The following members are set at the `}` of the class definition.
|
|
|
|
// A `CompleteTypeWitness` instruction witnessing that this class type is
|
|
// complete, and tracking its object representation. This has a value once the
|
|
// class is defined. For an adapter, the object representation is the
|
|
// non-adapter type that this class directly or transitively adapts.
|
|
InstId complete_type_witness_id = InstId::None;
|
|
|
|
// The virtual function table. `None` if the class has no (direct or
|
|
// inherited) virtual functions.
|
|
InstId vtable_decl_id = InstId::None;
|
|
|
|
auto PrintClassFields(llvm::raw_ostream& out) const -> void {
|
|
out << "self_type_id: " << self_type_id << ", inheritance_kind: ";
|
|
switch (inheritance_kind) {
|
|
case Abstract:
|
|
out << "Abstract";
|
|
break;
|
|
case Base:
|
|
out << "Base";
|
|
break;
|
|
case Final:
|
|
out << "Final";
|
|
break;
|
|
}
|
|
out << ", is_dynamic: " << is_dynamic << ", scope_id: " << scope_id
|
|
<< ", body_block_id: " << body_block_id << ", adapt_id: " << adapt_id
|
|
<< ", base_id: " << base_id
|
|
<< ", complete_type_witness_id: " << complete_type_witness_id
|
|
<< ", vtable_decl_id: " << vtable_decl_id << "}";
|
|
}
|
|
};
|
|
|
|
// A class. See EntityWithParamsBase regarding the inheritance here.
|
|
struct Class : public EntityWithParamsBase,
|
|
public ClassFields,
|
|
public Printable<Class> {
|
|
auto Print(llvm::raw_ostream& out) const -> void {
|
|
out << "{";
|
|
PrintBaseFields(out);
|
|
out << ", ";
|
|
PrintClassFields(out);
|
|
out << "}";
|
|
}
|
|
|
|
// This is false until we reach the `}` of the class definition.
|
|
auto is_complete() const -> bool {
|
|
return complete_type_witness_id.has_value();
|
|
}
|
|
|
|
// When merging a declaration and definition, prefer things which would point
|
|
// at the definition for diagnostics.
|
|
auto MergeDefinition(const Class& definition) -> void {
|
|
EntityWithParamsBase::MergeBaseDefinition(definition);
|
|
scope_id = definition.scope_id;
|
|
body_block_id = definition.body_block_id;
|
|
adapt_id = definition.adapt_id;
|
|
base_id = definition.base_id;
|
|
complete_type_witness_id = definition.complete_type_witness_id;
|
|
}
|
|
|
|
// Gets the type that this class type adapts. Returns `None` if there is no
|
|
// such type, or if the class is not yet defined.
|
|
auto GetAdaptedType(const File& file, SpecificId specific_id) const -> TypeId;
|
|
|
|
// Gets the base class for this class type. Returns `None` if there is no
|
|
// such type, or if the class is not yet defined.
|
|
auto GetBaseType(const File& file, SpecificId specific_id) const -> TypeId;
|
|
|
|
// Gets the object representation for this class. Returns `None` if the class
|
|
// is not yet defined.
|
|
auto GetObjectRepr(const File& file, SpecificId specific_id) const -> TypeId;
|
|
};
|
|
|
|
using ClassStore = ValueStore<ClassId, Class, Tag<CheckIRId>>;
|
|
|
|
} // namespace Carbon::SemIR
|
|
|
|
#endif // CARBON_TOOLCHAIN_SEM_IR_CLASS_H_
|