Skip to content

Commit 7acabfe

Browse files
committed
IRGen: We need to emit metadata for types that are emitted with shared linkage
Otherwise one TU could only require the type descriptor without metadata and another TU could require metadata and type descriptor. Whether the metadata access function is available would then depend on the linking order of the two TUs. rdar://56929811
1 parent 0a262fc commit 7acabfe

File tree

5 files changed

+63
-0
lines changed

5 files changed

+63
-0
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,17 @@ void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
12621262
if (!hasLazyMetadata(type))
12631263
return;
12641264

1265+
// If the type can be generated in several TU with weak linkage we don't know
1266+
// which one will be picked up so we have to require the metadata. Otherwise,
1267+
// the situation can arise where one TU contains a type descriptor with a null
1268+
// metadata access function and the other TU which requires metadata has a
1269+
// type descriptor with a valid metadata access function but the linker picks
1270+
// the first one.
1271+
if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(
1272+
type->getDeclaredType()->getCanonicalType()))) {
1273+
requireMetadata = RequireMetadata;
1274+
}
1275+
12651276
// Try to create a new record of the fact that we used this type.
12661277
auto insertResult = LazyTypeGlobals.try_emplace(type);
12671278
auto &entry = insertResult.first->second;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s
2+
3+
// REQUIRES: objc_interop
4+
5+
import Foundation
6+
7+
// Make sure we emit a metadata accessor for foreign types even if the type
8+
// metadata is not required by this TU. Another TU could require it and the
9+
// linker could choose the less defined one of the two.
10+
11+
// CHECK: @"$sSo8_NSRangeVMn" = linkonce_odr hidden constant <{ {{.*}}sSo8_NSRangeVMa{{.*}} }>, section "__TEXT,__const"
12+
13+
func use(_ closure: @escaping (Int) -> ()) {}
14+
15+
public func captureRange(_ r: NSRange?) {
16+
var l = r
17+
use {
18+
if $0 == 0 {
19+
l = NSRange()
20+
}
21+
}
22+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: cp %s %t/main.swift
3+
// RUN: %target-build-swift -o %t/main %S/Inputs/ForeignTypeMetadata1.swift %S/Inputs/ForeignTypeMetadata2.swift %t/main.swift -swift-version 5
4+
// RUN: %target-codesign %t/main
5+
// RUN: %target-run %t/main
6+
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: objc_interop
10+
11+
useType()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Foundation
2+
3+
func use(_ closure: @escaping (Int) -> ()) {}
4+
5+
public func captureRange(_ r: NSRange?) {
6+
var l = r
7+
use {
8+
if $0 == 0 {
9+
l = NSRange()
10+
}
11+
}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Foundation
2+
3+
public func useType() {
4+
var x = [NSRange]()
5+
x.append(NSRange())
6+
print(x)
7+
}

0 commit comments

Comments
 (0)