Skip to content

Commit 52353f8

Browse files
committed
[Static Mirror] Extract names of external-type conformances
Covering two cases: external ObjC class extensions that add a conformances, and extensions of external Swift types that add a conformance. For both cases, we were not previously reading out the type name correctly, or at all. Resolves rdar://91832735
1 parent 4ebf04a commit 52353f8

File tree

6 files changed

+87
-10
lines changed

6 files changed

+87
-10
lines changed

include/swift/Reflection/TypeRefBuilder.h

+38-10
Original file line numberDiff line numberDiff line change
@@ -1148,11 +1148,21 @@ class TypeRefBuilder {
11481148
}
11491149

11501150
/// Extract conforming type's name from a Conformance Descriptor
1151-
llvm::Optional<std::string> getConformingTypeName(
1151+
/// Returns a pair of (mangledTypeName, fullyQualifiedTypeName)
1152+
llvm::Optional<std::pair<std::string, std::string>> getConformingTypeName(
11521153
const uintptr_t conformanceDescriptorAddress,
11531154
const ExternalProtocolConformanceDescriptor<
11541155
ObjCInteropKind, PointerSize> &conformanceDescriptor) {
11551156
std::string typeName;
1157+
std::string mangledTypeName = "";
1158+
1159+
// If this is a conformance added to an ObjC class, detect that here and return class name
1160+
if (conformanceDescriptor.getTypeKind() == TypeReferenceKind::DirectObjCClassName) {
1161+
auto className = conformanceDescriptor.getDirectObjCClassName();
1162+
typeName = MANGLING_MODULE_OBJC.str() + std::string(".") + className;
1163+
return std::make_pair(mangledTypeName, typeName);
1164+
}
1165+
11561166
// Compute the address of the type descriptor as follows:
11571167
// - Compute the address of the TypeRef field in the protocol
11581168
// descriptor
@@ -1179,6 +1189,21 @@ class TypeRefBuilder {
11791189
(const char *)contextDescriptorFieldAddress,
11801190
(int32_t)*contextDescriptorOffset);
11811191

1192+
// Instead of a type descriptor this may just be a symbol reference, check that first
1193+
if (auto symbol = OpaquePointerReader(remote::RemoteAddress(contextTypeDescriptorAddress),
1194+
PointerSize)) {
1195+
if (!symbol->getSymbol().empty()) {
1196+
mangledTypeName = symbol->getSymbol().str();
1197+
Demangle::Context Ctx;
1198+
auto demangledRoot =
1199+
Ctx.demangleSymbolAsNode(mangledTypeName);
1200+
assert(demangledRoot->getKind() == Node::Kind::Global);
1201+
typeName =
1202+
nodeToString(demangledRoot->getChild(0)->getChild(0));
1203+
return std::make_pair(mangledTypeName, typeName);
1204+
}
1205+
}
1206+
11821207
auto contextTypeDescriptorBytes = OpaqueByteReader(
11831208
remote::RemoteAddress(contextTypeDescriptorAddress),
11841209
sizeof(ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
@@ -1213,7 +1238,7 @@ class TypeRefBuilder {
12131238
typeName = optionalParentName.getValue() + "." + typeName;
12141239
}
12151240

1216-
return typeName;
1241+
return std::make_pair(mangledTypeName, typeName);
12171242
}
12181243

12191244
/// Extract protocol name from a Conformance Descriptor
@@ -1317,9 +1342,9 @@ class TypeRefBuilder {
13171342
(const ExternalProtocolConformanceDescriptor<
13181343
ObjCInteropKind, PointerSize> *)descriptorBytes.get();
13191344

1320-
auto optionalConformingTypeName = getConformingTypeName(
1345+
auto optionalConformingTypeNamePair = getConformingTypeName(
13211346
conformanceDescriptorAddress, *conformanceDescriptorPtr);
1322-
if (!optionalConformingTypeName.hasValue())
1347+
if (!optionalConformingTypeNamePair.hasValue())
13231348
return llvm::None;
13241349

13251350
auto optionalConformanceProtocol = getConformanceProtocolName(
@@ -1328,15 +1353,18 @@ class TypeRefBuilder {
13281353
return llvm::None;
13291354

13301355
std::string mangledTypeName;
1331-
auto it =
1332-
typeNameToManglingMap.find(optionalConformingTypeName.getValue());
1333-
if (it != typeNameToManglingMap.end()) {
1334-
mangledTypeName = it->second;
1356+
if (optionalConformingTypeNamePair.getValue().first.empty()) {
1357+
auto it = typeNameToManglingMap.find(optionalConformingTypeNamePair.getValue().second);
1358+
if (it != typeNameToManglingMap.end()) {
1359+
mangledTypeName = it->second;
1360+
} else {
1361+
mangledTypeName = "";
1362+
}
13351363
} else {
1336-
mangledTypeName = "";
1364+
mangledTypeName = optionalConformingTypeNamePair.getValue().first;
13371365
}
13381366

1339-
return ProtocolConformanceInfo{optionalConformingTypeName.getValue(),
1367+
return ProtocolConformanceInfo{optionalConformingTypeNamePair.getValue().second,
13401368
optionalConformanceProtocol.getValue(),
13411369
mangledTypeName};
13421370
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module testModA {
2+
header "testModA.h"
3+
export *
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#import <Foundation/Foundation.h>
2+
@interface testModAClass : NSObject
3+
@property int x;
4+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#import "testModA.h"
2+
3+
@implementation testModAClass
4+
- (instancetype) init {
5+
if ((self = [super init]) == nil) return nil;
6+
self.x = 42;
7+
return self;
8+
}
9+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Foundation
2+
3+
public struct testModBStruct {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// REQUIRES: objc_interop, OS=macosx
2+
// Temporarily disable on arm64e (rdar://88579818)
3+
// UNSUPPORTED: CPU=arm64e
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: %empty-directory(%t/includes)
7+
8+
// Build external Swift library/module
9+
// RUN: %target-build-swift %S/Inputs/swiftmodules/testModB.swift -parse-as-library -emit-module -emit-library -module-name testModB -o %t/includes/testModB.o
10+
11+
// Build external Clang library
12+
// RUN: %target-clang %S/Inputs/cmodules/testModA.m -c -o %t/testModA.o
13+
14+
// Build the test into a binary
15+
// RUN: %target-build-swift %s -parse-as-library -emit-module -emit-library -module-name ExternalConformanceCheck -I %t/includes -I %S/Inputs/cmodules -o %t/ExternalConformances %t/testModA.o %t/includes/testModB.o
16+
17+
// RUN: %target-swift-reflection-dump -binary-filename %t/ExternalConformances -binary-filename %platform-module-dir/%target-library-name(swiftCore) | %FileCheck %s
18+
19+
import testModA
20+
import testModB
21+
22+
protocol myTestProto {}
23+
extension testModBStruct : myTestProto {}
24+
extension testModAClass : myTestProto {}
25+
26+
// CHECK: CONFORMANCES:
27+
// CHECK: =============
28+
// CHECK-DAG: (__C.testModAClass) : ExternalConformanceCheck.myTestProto
29+
// CHECK-DAG: _$s8testModB0aB7BStructVMn (testModB.testModBStruct) : ExternalConformanceCheck.myTestProto

0 commit comments

Comments
 (0)