Skip to content

Commit cfe5da7

Browse files
committed
[4.2] IRGen: We need to make note of any parent decl in nested type decls
Such that we emit the parent's type metadata rdar://39648725 Cherry-pick from #16135
1 parent f77dab5 commit cfe5da7

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,8 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
24242424
IGM.addObjCClass(var,
24252425
classDecl->getAttrs().hasAttribute<ObjCNonLazyRealizationAttr>());
24262426
}
2427+
2428+
IGM.IRGen.noteUseOfAnyParentTypeMetadata(classDecl);
24272429
}
24282430

24292431
llvm::Value *IRGenFunction::emitInvariantLoad(Address address,
@@ -2820,6 +2822,19 @@ void irgen::emitStructMetadata(IRGenModule &IGM, StructDecl *structDecl) {
28202822

28212823
IGM.defineTypeMetadata(declaredType, isIndirect, isPattern,
28222824
canBeConstant, init.finishAndCreateFuture());
2825+
2826+
IGM.IRGen.noteUseOfAnyParentTypeMetadata(structDecl);
2827+
}
2828+
2829+
void IRGenerator::noteUseOfAnyParentTypeMetadata(NominalTypeDecl *type) {
2830+
// If this is a nested type we also potentially might need the outer types.
2831+
auto *declCtxt = type->getDeclContext();
2832+
assert(declCtxt);
2833+
auto *parentNominalDecl = dyn_cast_or_null<NominalTypeDecl>(declCtxt);
2834+
if (!parentNominalDecl)
2835+
return;
2836+
2837+
noteUseOfTypeMetadata(parentNominalDecl);
28232838
}
28242839

28252840
// Enums
@@ -3024,6 +3039,8 @@ void irgen::emitEnumMetadata(IRGenModule &IGM, EnumDecl *theEnum) {
30243039

30253040
IGM.defineTypeMetadata(declaredType, isIndirect, isPattern,
30263041
canBeConstant, init.finishAndCreateFuture());
3042+
3043+
IGM.IRGen.noteUseOfAnyParentTypeMetadata(theEnum);
30273044
}
30283045

30293046
llvm::Value *IRGenFunction::emitObjCSelectorRefLoad(StringRef selector) {

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ class IRGenerator {
357357
noteUseOfTypeGlobals(type, false, requireMetadata);
358358
}
359359

360+
void noteUseOfAnyParentTypeMetadata(NominalTypeDecl *type);
361+
360362
private:
361363
void noteUseOfTypeGlobals(NominalTypeDecl *type,
362364
bool isUseOfMetadata,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
struct Outer {
2+
struct Inner {
3+
}
4+
}
5+
6+
struct Outer2 {
7+
enum InnerE {
8+
}
9+
}
10+
11+
struct Outer3 {
12+
class InnerC {
13+
}
14+
}
15+

test/multifile/nested_types.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-build-swift -module-name test -wmo -O -emit-ir -Xfrontend -num-threads -Xfrontend 0 %s %S/Inputs/nested_types_defs.swift -o - | %FileCheck %s
2+
3+
// Make sure we generate the outer metadata.
4+
5+
// CHECK-DAG: @"$S4test6Outer3VMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test6Outer3VMn"
6+
// CHECK-DAG: @"$S4test6Outer2VMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test6Outer2VMn"
7+
// CHECK-DAG: @"$S4test6Outer3VMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test6Outer3VMn"
8+
9+
class C<T> { }
10+
11+
struct Y {
12+
let x:C<Outer.Inner>
13+
let y:C<Outer2.InnerE>
14+
let z:C<Outer3.InnerC>
15+
}
16+
17+
public func test() {
18+
var c = Y(x: C<Outer.Inner>(), y: C<Outer2.InnerE>(), z: C<Outer3.InnerC>())
19+
20+
print("a \(c)")
21+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -wmo -O %s %S/../Inputs/nested_types_defs.swift -o %t/a.out
3+
// RUN: %target-run %t/a.out | %FileCheck %s
4+
5+
class C<T> { }
6+
7+
struct Y {
8+
let x:C<Outer.Inner>
9+
let y:C<Outer2.InnerE>
10+
let z:C<Outer3.InnerC>
11+
}
12+
13+
func test() {
14+
var c = Y(x: C<Outer.Inner>(), y: C<Outer2.InnerE>(), z: C<Outer3.InnerC>())
15+
16+
print("a \(c)")
17+
}
18+
19+
// CHECK: a Y(x: a.C<a.Outer.Inner>, y: a.C<a.Outer2.InnerE>, z: a.C<a.Outer3.InnerC>)
20+
test()

0 commit comments

Comments
 (0)