Skip to content

Commit fe965a7

Browse files
authored
Merge pull request #15860 from slavapestov/fix-foreign-class-bug
Fix miscompile when emitting protocol conformance of a runtime-only class
2 parents 4f26ef7 + 94409b8 commit fe965a7

File tree

4 files changed

+38
-7
lines changed

4 files changed

+38
-7
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3348,7 +3348,7 @@ IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) {
33483348
if (auto classType = dyn_cast<ClassType>(type)) {
33493349
assert(!classType.getParent());
33503350
auto classDecl = classType->getDecl();
3351-
assert(classDecl->isForeign());
3351+
assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType);
33523352

33533353
ForeignClassMetadataBuilder builder(*this, classDecl, init);
33543354
builder.layout();
@@ -3389,7 +3389,8 @@ IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) {
33893389
if (auto enclosing = type->getNominalParent()) {
33903390
auto canonicalEnclosing = enclosing->getCanonicalType();
33913391
if (requiresForeignTypeMetadata(canonicalEnclosing)) {
3392-
getAddrOfForeignTypeMetadataCandidate(canonicalEnclosing);
3392+
(void)getTypeMetadataAccessFunction(*this, canonicalEnclosing,
3393+
ForDefinition);
33933394
}
33943395
}
33953396

lib/IRGen/GenProto.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,8 +2187,19 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
21872187

21882188
// Trigger the lazy emission of the foreign type metadata.
21892189
CanType conformingType = conf->getType()->getCanonicalType();
2190-
if (requiresForeignTypeMetadata(conformingType))
2191-
(void)getAddrOfForeignTypeMetadataCandidate(conformingType);
2190+
if (requiresForeignTypeMetadata(conformingType)) {
2191+
// Make sure we emit the metadata access function.
2192+
(void)getTypeMetadataAccessFunction(*this, conformingType,
2193+
ForDefinition);
2194+
2195+
// Make sure we emit the nominal type descriptor.
2196+
auto *nominal = conformingType->getAnyNominal();
2197+
auto entity = LinkEntity::forNominalTypeDescriptor(nominal);
2198+
if (auto entry = GlobalVars[entity])
2199+
return;
2200+
2201+
emitLazyTypeContextDescriptor(*this, nominal, RequireMetadata);
2202+
}
21922203
}
21932204

21942205
/// True if a function's signature in LLVM carries polymorphic parameters.

lib/IRGen/MetadataLayout.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ MetadataLayout &IRGenModule::getMetadataLayout(NominalTypeDecl *decl) {
111111
auto &entry = MetadataLayouts[decl];
112112
if (!entry) {
113113
if (auto theClass = dyn_cast<ClassDecl>(decl)) {
114-
if (theClass->isForeign())
114+
if (theClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType)
115115
entry = new ForeignClassMetadataLayout(*this, theClass);
116116
else
117117
entry = new ClassMetadataLayout(*this, theClass);
@@ -456,7 +456,7 @@ ClassMetadataLayout::getFieldOffsetVectorOffset(IRGenFunction &IGF) const {
456456

457457
Size irgen::getClassFieldOffsetOffset(IRGenModule &IGM, ClassDecl *theClass,
458458
VarDecl *field) {
459-
if (theClass->isForeign())
459+
if (theClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType)
460460
return Size();
461461

462462
return IGM.getClassMetadataLayout(theClass).getStaticFieldOffset(field);
@@ -602,7 +602,8 @@ StructMetadataLayout::getFieldOffsetVectorOffset() const {
602602
ForeignClassMetadataLayout::ForeignClassMetadataLayout(IRGenModule &IGM,
603603
ClassDecl *theClass)
604604
: MetadataLayout(Kind::ForeignClass), Class(theClass) {
605-
assert(theClass->isForeign() && "Not a foreign class");
605+
assert(theClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
606+
"Not a foreign class");
606607

607608
struct Scanner : LayoutScanner<Scanner, ForeignClassMetadataScanner> {
608609
using super = LayoutScanner;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// REQUIRES: objc_interop
2+
3+
// RUN: %target-swift-frontend -I %S/../Inputs/custom-modules %s -emit-ir | %FileCheck %s
4+
5+
import ObjCRuntimeVisible
6+
7+
protocol MyProtocol {}
8+
protocol YourProtocol {}
9+
10+
extension A : MyProtocol {}
11+
extension A : YourProtocol {}
12+
13+
// CHECK-LABEL: @"$SSo1ACMn" = linkonce_odr hidden constant <{ {{.*}} }>, section "__TEXT,__const"
14+
15+
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo1ACMa"({{i32|i64}}) {{.*}} {
16+
// CHECK: call %objc_class* @objc_lookUpClass
17+
// CHECK: call %swift.type* @swift_getObjCClassMetadata
18+
// CHECK: ret

0 commit comments

Comments
 (0)