mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 11:31:05 +01:00
Improve interop for classes with multiple inheritance. (#6130)
If there's a unique "preferred" base class, then treat that as "the" base class for Carbon's purposes. In particular: * If there's exactly one polymorphic base class, that's our preferred base class. * If there's exactly one non-empty base class, that's our perferred base class. * (Degenerate case) If there's exactly one base class, that's our preferred base class. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
parent
f194acbf96
commit
949ec17da2
@@ -828,6 +828,16 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id,
|
||||
|
||||
// TODO: Import vptr(s).
|
||||
|
||||
// The kind of base class we've picked so far. These are ordered in increasing
|
||||
// preference order.
|
||||
enum class BaseKind {
|
||||
None,
|
||||
Empty,
|
||||
NonEmpty,
|
||||
Polymorphic,
|
||||
};
|
||||
BaseKind base_kind = BaseKind::None;
|
||||
|
||||
// Import bases.
|
||||
for (const auto& base : clang_def->bases()) {
|
||||
CARBON_CHECK(!base.isVirtual(),
|
||||
@@ -849,19 +859,27 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id,
|
||||
.base_type_inst_id = base_type_inst_id,
|
||||
.index = SemIR::ElementIndex(fields.size())}));
|
||||
|
||||
// If there's exactly one base class, treat it as a Carbon base class too.
|
||||
// TODO: Improve handling for the case where the class has multiple base
|
||||
// classes.
|
||||
if (clang_def->getNumBases() == 1) {
|
||||
auto& class_info = context.classes().Get(class_id);
|
||||
CARBON_CHECK(!class_info.base_id.has_value());
|
||||
class_info.base_id = base_decl_id;
|
||||
}
|
||||
|
||||
auto* base_class = base.getType()->getAsCXXRecordDecl();
|
||||
CARBON_CHECK(base_class, "Base class {0} is not a class",
|
||||
base.getType().getAsString());
|
||||
|
||||
// If there's a unique "best" base class, treat it as a Carbon base class
|
||||
// too.
|
||||
// TODO: Improve handling for the case where the class has multiple base
|
||||
// classes.
|
||||
BaseKind kind = base_class->isPolymorphic() ? BaseKind::Polymorphic
|
||||
: base_class->isEmpty() ? BaseKind::Empty
|
||||
: BaseKind::NonEmpty;
|
||||
auto& class_info = context.classes().Get(class_id);
|
||||
if (kind > base_kind) {
|
||||
// This base is better than the previous best.
|
||||
class_info.base_id = base_decl_id;
|
||||
base_kind = kind;
|
||||
} else if (kind == base_kind) {
|
||||
// Multiple base classes of this kind: no unique best.
|
||||
class_info.base_id = SemIR::InstId::None;
|
||||
}
|
||||
|
||||
auto base_offset = base.isVirtual()
|
||||
? clang_layout.getVBaseClassOffset(base_class)
|
||||
: clang_layout.getBaseClassOffset(base_class);
|
||||
|
||||
Reference in New Issue
Block a user