Skip to content

Commit 64ca7c3

Browse files
Merge pull request #16135 from aschwaighofer/irgen_parent_metadata_fix
IRGen: We need to make not of any parent decl in nested type decls
2 parents d46ebe5 + 75bf101 commit 64ca7c3

File tree

5 files changed

+84
-0
lines changed

5 files changed

+84
-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+
auto *parentNominalDecl =
2833+
declCtxt->getAsNominalTypeOrNominalTypeExtensionContext();
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
16+
struct Outer4 {}
17+
18+
extension Outer4 {
19+
struct InnerExtension {}
20+
}

test/multifile/nested_types.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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: @"$S4test5OuterVMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test5OuterVMn"
6+
// CHECK-DAG: @"$S4test6Outer2VMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test6Outer2VMn"
7+
// CHECK-DAG: @"$S4test6Outer3VMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test6Outer3VMn"
8+
// CHECK-DAG: @"$S4test6Outer4VMf" = internal constant {{.*}} @"$SytWV"{{.*}}@"$S4test6Outer4VMn"
9+
10+
class C<T> { }
11+
12+
struct Y {
13+
let x:C<Outer.Inner>
14+
let y:C<Outer2.InnerE>
15+
let z:C<Outer3.InnerC>
16+
let w:C<Outer4.InnerExtension>
17+
}
18+
19+
public func test() {
20+
var c = Y(x: C<Outer.Inner>(), y: C<Outer2.InnerE>(), z: C<Outer3.InnerC>(),
21+
w: C<Outer4.InnerExtension>())
22+
23+
print("a \(c)")
24+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
let w:C<Outer4.InnerExtension>
12+
}
13+
14+
func test() {
15+
var c = Y(x: C<Outer.Inner>(), y: C<Outer2.InnerE>(), z: C<Outer3.InnerC>(), w: C<Outer4.InnerExtension>())
16+
17+
print("a \(c)")
18+
}
19+
20+
// CHECK: a Y(x: a.C<a.Outer.Inner>, y: a.C<a.Outer2.InnerE>, z: a.C<a.Outer3.InnerC>, w: a.C<a.Outer4.InnerExtension>)
21+
test()

0 commit comments

Comments
 (0)