Skip to content

Commit 1b459c1

Browse files
DougGregoreeckstein
authored andcommitted
Improve/clarify the inference of @_staticInitializeObjCMetadata.
Infer @_staticInitializeObjCMetadata in those cases where we need a static initializer to make an NSCoding-conforming class visible to the Objective-C runtime. This does *not* include classes with one of the @NSKeyedArchive attributes: * @NSKeyedArchiveLegacy implies that we'll register the class directly, with the necessary side effect of initialize Objective-C metadata. * @NSKeyedArchiveSubclassesOnly promises not to archive the class directly anyway.
1 parent 50510ea commit 1b459c1

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5850,6 +5850,35 @@ static bool hasGenericAncestry(ClassDecl *classDecl) {
58505850
return false;
58515851
}
58525852

5853+
/// Infer the attribute tostatic-initialize the Objective-C metadata for the
5854+
/// given class, if needed.
5855+
static void inferStaticInitializeObjCMetadata(ClassDecl *classDecl,
5856+
bool requiresNSCodingAttr) {
5857+
// If we already have the attribute, there's nothing to do.
5858+
if (classDecl->getAttrs().hasAttribute<StaticInitializeObjCMetadataAttr>())
5859+
return;
5860+
5861+
// A class with the @NSKeyedArchiveLegacyAttr will end up getting registered
5862+
// with the Objective-C runtime anyway.
5863+
if (classDecl->getAttrs().hasAttribute<NSKeyedArchiveLegacyAttr>())
5864+
return;
5865+
5866+
// A class with @NSKeyedArchiveSubclassesOnly promises not to be archived,
5867+
// so don't static-initialize its Objective-C metadata.
5868+
if (classDecl->getAttrs().hasAttribute<NSKeyedArchiveSubclassesOnlyAttr>())
5869+
return;
5870+
5871+
// If we know that the Objective-C metadata will be statically registered,
5872+
// there's nothing to do.
5873+
if (!requiresNSCodingAttr && !hasGenericAncestry(classDecl))
5874+
return;
5875+
5876+
// Infer @_staticInitializeObjCMetadata.
5877+
ASTContext &ctx = classDecl->getASTContext();
5878+
classDecl->getAttrs().add(
5879+
new (ctx) StaticInitializeObjCMetadataAttr(/*implicit=*/true));
5880+
}
5881+
58535882
void TypeChecker::checkConformancesInContext(DeclContext *dc,
58545883
IterableDeclContext *idc) {
58555884
// For anything imported from Clang, lazily check conformances.
@@ -5962,18 +5991,8 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
59625991
}
59635992
}
59645993

5965-
// If the class declaration doesn't have the
5966-
// @_staticInitializeObjCMetadata attribute but requires one because
5967-
// either we complained above, have @NSKeyedArchiveLegacy, or
5968-
// have generic ancestry, add @_staticInitializeObjCMetadata to indicate
5969-
// that we need to statically initialize Objective-C metadata.
5970-
if (!classDecl->getAttrs()
5971-
.hasAttribute<StaticInitializeObjCMetadataAttr>() &&
5972-
(kind || hasGenericAncestry(classDecl) ||
5973-
classDecl->getAttrs().hasAttribute<NSKeyedArchiveLegacyAttr>())) {
5974-
classDecl->getAttrs().add(
5975-
new (Context) StaticInitializeObjCMetadataAttr(/*implicit=*/true));
5976-
}
5994+
// Infer @_staticInitializeObjCMetadata if needed.
5995+
inferStaticInitializeObjCMetadata(classDecl, kind.hasValue());
59775996
}
59785997
}
59795998
}

test/decl/protocol/conforms/nscoding.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,9 @@ extension CodingB {
139139
// Inference of @_staticInitializeObjCMetadata.
140140
class SubclassOfCodingE : CodingE<Int> { }
141141

142+
// CHECK-NOT: class_decl "CodingA"{{.*}}@_staticInitializeObjCMetadata
142143
// CHECK: class_decl "NestedA"{{.*}}@_staticInitializeObjCMetadata
144+
// CHECK: class_decl "NestedC"{{.*}}@_staticInitializeObjCMetadata
145+
// CHECK-NOT: class_decl "NestedE"{{.*}}@_staticInitializeObjCMetadata
146+
// CHECK-NOT: class_decl "CodingGeneric"{{.*}}@_staticInitializeObjCMetadata
143147
// CHECK: class_decl "SubclassOfCodingE"{{.*}}@_staticInitializeObjCMetadata

0 commit comments

Comments
 (0)