Skip to content

Commit 7ddface

Browse files
Merge pull request swiftlang#28187 from aschwaighofer/fix_metadata_emission_foreign_types
IRGen: We need to emit metadata for types that are emitted with shared linkage
2 parents ea9d043 + 7acabfe commit 7ddface

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)