Skip to content

Commit fe11864

Browse files
committed
IRGen: Generate runtime type manglings using ObjC runtime names.
In order for the runtime demangler to be able to find ObjC classes and protocols, it needs to have the runtime name of the declaration be in the mangled name. Only do this for runtime manglings, to minimize the potential ABI impact for symbol names that already have the source-level names of ObjC entities baked in. Fixes SR-12169 | rdar://59306590.
1 parent b58ea4b commit fe11864

File tree

5 files changed

+53
-10
lines changed

5 files changed

+53
-10
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ class ASTMangler : public Mangler {
3939
bool OptimizeProtocolNames = true;
4040

4141
/// If enabled, use Objective-C runtime names when mangling @objc Swift
42-
/// protocols.
43-
bool UseObjCProtocolNames = false;
42+
/// protocols and classes.
43+
bool UseObjCRuntimeNames = false;
4444

4545
/// If enabled, non-canonical types are allowed and type alias types get a
4646
/// special mangling.

lib/AST/ASTMangler.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ void ASTMangler::appendDeclName(const ValueDecl *decl) {
699699
break;
700700
}
701701
} else if (auto objCName =
702-
getOverriddenSwiftProtocolObjCName(decl, UseObjCProtocolNames)) {
702+
getOverriddenSwiftProtocolObjCName(decl, UseObjCRuntimeNames)) {
703703
// @objc Swift protocols should be mangled as Objective-C protocols,
704704
// so append the Objective-C runtime name.
705705
appendIdentifier(*objCName);
@@ -1298,7 +1298,7 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
12981298
genericArgs = boundType->getGenericArgs();
12991299
if (Type parent = boundType->getParent()) {
13001300
GenericTypeDecl *decl = boundType->getAnyGeneric();
1301-
if (!getSpecialManglingContext(decl, UseObjCProtocolNames))
1301+
if (!getSpecialManglingContext(decl, UseObjCRuntimeNames))
13021302
appendBoundGenericArgs(parent->getDesugaredType(), isFirstArgList);
13031303
}
13041304
}
@@ -1610,7 +1610,7 @@ ASTMangler::getSpecialManglingContext(const ValueDecl *decl,
16101610
/// This is the top-level entrypoint for mangling <context>.
16111611
void ASTMangler::appendContextOf(const ValueDecl *decl) {
16121612
// Check for a special mangling context.
1613-
if (auto context = getSpecialManglingContext(decl, UseObjCProtocolNames)) {
1613+
if (auto context = getSpecialManglingContext(decl, UseObjCRuntimeNames)) {
16141614
switch (*context) {
16151615
case ClangImporterContext:
16161616
return appendOperator("SC");
@@ -1857,7 +1857,10 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
18571857

18581858
appendContextOf(protocol);
18591859
auto *clangDecl = protocol->getClangDecl();
1860-
if (auto *clangProto = cast_or_null<clang::ObjCProtocolDecl>(clangDecl))
1860+
auto clangProto = cast_or_null<clang::ObjCProtocolDecl>(clangDecl);
1861+
if (clangProto && UseObjCRuntimeNames)
1862+
appendIdentifier(clangProto->getObjCRuntimeNameAsString());
1863+
else if (clangProto)
18611864
appendIdentifier(clangProto->getName());
18621865
else
18631866
appendDeclName(protocol);
@@ -1928,15 +1931,25 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
19281931
if (!namedDecl)
19291932
return false;
19301933

1931-
appendIdentifier(namedDecl->getName());
1934+
// Mangle ObjC classes using their runtime names.
1935+
auto interface = dyn_cast<clang::ObjCInterfaceDecl>(namedDecl);
1936+
auto protocol = dyn_cast<clang::ObjCProtocolDecl>(namedDecl);
1937+
1938+
if (UseObjCRuntimeNames && interface) {
1939+
appendIdentifier(interface->getObjCRuntimeNameAsString());
1940+
} else if (UseObjCRuntimeNames && protocol) {
1941+
appendIdentifier(protocol->getObjCRuntimeNameAsString());
1942+
} else {
1943+
appendIdentifier(namedDecl->getName());
1944+
}
19321945

19331946
// The important distinctions to maintain here are Objective-C's various
19341947
// namespaces: protocols, tags (struct/enum/union), and unqualified names.
19351948
// We continue to mangle "class" the standard Swift way because it feels
19361949
// weird to call that an alias, but they're really in the same namespace.
1937-
if (isa<clang::ObjCInterfaceDecl>(namedDecl)) {
1950+
if (interface) {
19381951
appendOperator("C");
1939-
} else if (isa<clang::ObjCProtocolDecl>(namedDecl)) {
1952+
} else if (protocol) {
19401953
appendOperator("P");
19411954
} else if (isa<clang::TagDecl>(namedDecl)) {
19421955
// Note: This includes enums, but that's okay. A Clang enum is not always

lib/IRGen/IRGenMangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ IRGenMangler::withSymbolicReferences(IRGenModule &IGM,
8383
llvm::function_ref<void ()> body) {
8484
Mod = IGM.getSwiftModule();
8585
OptimizeProtocolNames = false;
86-
UseObjCProtocolNames = true;
86+
UseObjCRuntimeNames = true;
8787

8888
llvm::SaveAndRestore<bool>
8989
AllowSymbolicReferencesLocally(AllowSymbolicReferences);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@import Foundation;
2+
3+
__attribute__((objc_runtime_name("ObjCRuntimeNameIsDifferent")))
4+
@interface ObjCRuntimeNamed: NSObject
5+
6+
@end
7+
8+
__attribute__((objc_runtime_name("ObjCProtoRuntimeNameIsDifferent")))
9+
@protocol ObjCProtoRuntimeNamed
10+
11+
@end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -import-objc-header %S/Inputs/objc_runtime_name_clang_attr.h %s | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
4+
// Use the runtime name for runtime instantiation
5+
// CHECK-LABEL: @"$sSo16ObjCRuntimeNamedCSgMD" = {{.*}}@"symbolic So26ObjCRuntimeNameIsDifferentCSg"
6+
public func getMetadata() -> Any.Type {
7+
return ObjCRuntimeNamed?.self
8+
}
9+
// CHECK-LABEL: @"$sSo21ObjCProtoRuntimeNamed_pSgMD" = {{.*}}@"symbolic So31ObjCProtoRuntimeNameIsDifferent_pSg"
10+
public func getMetadata2() -> Any.Type {
11+
return ObjCProtoRuntimeNamed?.self
12+
}
13+
14+
// Use the source name for symbols to avoid breaking ABI.
15+
// CHECK-LABEL: define{{.*}}3fooyySo16ObjCRuntimeNamedCF
16+
public func foo(_: ObjCRuntimeNamed) {}
17+
18+
// CHECK-LABEL: define{{.*}}3fooyySo21ObjCProtoRuntimeNamed_pF
19+
public func foo(_: ObjCProtoRuntimeNamed) {}

0 commit comments

Comments
 (0)