Skip to content

IRGen: Opaque type descriptor and nested type fixes for -unavailable-decl-optimization #64808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/AST/Availability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ AvailabilityInference::parentDeclForInferredAvailability(const Decl *D) {
if (auto *PBD = dyn_cast<PatternBindingDecl>(D))
return PBD->getAnchoringVarDecl(0);

if (auto *OTD = dyn_cast<OpaqueTypeDecl>(D))
return OTD->getNamingDecl();

// Clang decls may be inaccurately parented rdar://53956555
if (D->hasClangNode())
return nullptr;
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,8 @@ AvailabilityContext Decl::getAvailabilityForLinkage() const {
return *containingContext;
}

// FIXME: Adopt AvailabilityInference::parentDeclForInferredAvailability()
// here instead of duplicating the logic.
if (auto *accessor = dyn_cast<AccessorDecl>(this))
return accessor->getStorage()->getAvailabilityForLinkage();

Expand Down
3 changes: 3 additions & 0 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5489,6 +5489,9 @@ Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case,

void IRGenModule::emitNestedTypeDecls(DeclRange members) {
for (Decl *member : members) {
if (Lowering::shouldSkipLowering(member))
continue;

member->visitAuxiliaryDecls([&](Decl *decl) {
emitNestedTypeDecls({decl, nullptr});
});
Expand Down
3 changes: 3 additions & 0 deletions lib/IRGen/GenStruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,9 @@ void IRGenModule::emitStructDecl(StructDecl *st) {
}

void IRGenModule::maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque) {
if (Lowering::shouldSkipLowering(opaque))
return;

if (IRGen.Opts.EnableAnonymousContextMangledNames) {
// If we're emitting anonymous context mangled names for debuggability,
// then emit all opaque type descriptors and make them runtime-discoverable
Expand Down
179 changes: 0 additions & 179 deletions test/IRGen/unavailable_decl_optimization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,182 +13,3 @@ public let globalConstant = true
// CHECK-STRIP-NOT: s4Test15unavailableFuncyyF
@available(*, unavailable)
public func unavailableFunc() {}

@available(*, unavailable)
public struct UnavailableStruct<T> {
// CHECK-NO-STRIP: s4Test17UnavailableStructV8propertyxvg
// CHECK-NO-STRIP: s4Test17UnavailableStructV8propertyxvs
// CHECK-NO-STRIP: s4Test17UnavailableStructV8propertyxvM
// CHECK-STRIP-NOT: s4Test17UnavailableStructV8propertyxvg
// CHECK-STRIP-NOT: s4Test17UnavailableStructV8propertyxvs
// CHECK-STRIP-NOT: s4Test17UnavailableStructV8propertyxvM
public var property: T

// CHECK-NO-STRIP: s4Test17UnavailableStructVyACyxGxcfC
// CHECK-NO-STRIP: s4Test17UnavailableStructVMa
// CHECK-STRIP-NOT: s4Test17UnavailableStructVyACyxGxcfC
// CHECK-STRIP-NOT: s4Test17UnavailableStructVMa
public init(_ t: T) {
self.property = t
}

// CHECK-NO-STRIP: s4Test17UnavailableStructV6methodyyF
// CHECK-STRIP-NOT: s4Test17UnavailableStructV6methodyyF
public func method() {}
}

@available(*, unavailable)
extension UnavailableStruct {
// CHECK-NO-STRIP: s4Test17UnavailableStructV15extensionMethodyyF
// CHECK-STRIP-NOT: s4Test17UnavailableStructV15extensionMethodyyF
public func extensionMethod() {}
}

@available(*, unavailable)
public enum UnavailableEnum {
case a, b

// CHECK-NO-STRIP: s4Test15UnavailableEnumO6methodyyF
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO6methodyyF
public func method() {}

// CHECK-NO-STRIP: s4Test15UnavailableEnumO21__derived_enum_equalsySbAC_ACtFZ
// CHECK-NO-STRIP: s4Test15UnavailableEnumO4hash4intoys6HasherVz_tF
// CHECK-NO-STRIP: s4Test15UnavailableEnumO9hashValueSivg
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO21__derived_enum_equalsySbAC_ACtFZ
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO4hash4intoys6HasherVz_tF
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO9hashValueSivg
}

@available(*, unavailable)
public class UnavailableClass<T> {
// CHECK-NO-STRIP: s4Test16UnavailableClassC8propertyxvg
// CHECK-NO-STRIP: s4Test16UnavailableClassC8propertyxvs
// CHECK-NO-STRIP: s4Test16UnavailableClassC8propertyxvM
// CHECK-STRIP-NOT: s4Test16UnavailableClassC8propertyxvg
// CHECK-STRIP-NOT: s4Test16UnavailableClassC8propertyxvs
// CHECK-STRIP-NOT: s4Test16UnavailableClassC8propertyxvM
public var property: T

// CHECK-NO-STRIP: s4Test16UnavailableClassCyACyxGxcfC
// CHECK-NO-STRIP: s4Test16UnavailableClassCyACyxGxcfc
// CHECK-STRIP-NOT: s4Test16UnavailableClassCyACyxGxcfC
// CHECK-STRIP-NOT: s4Test16UnavailableClassCyACyxGxcfc
public init(_ t: T) {
self.property = t
}

// CHECK-NO-STRIP: s4Test16UnavailableClassCfd
// CHECK-NO-STRIP: s4Test16UnavailableClassCfD
// CHECK-STRIP-NOT: s4Test16UnavailableClassCfd
// CHECK-STRIP-NOT: s4Test16UnavailableClassCfD
deinit {}
}

public struct S<T> {
// CHECK-NO-STRIP: s4Test1SV19unavailablePropertyxvg
// CHECK-NO-STRIP: s4Test1SV19unavailablePropertyxvs
// CHECK-NO-STRIP: s4Test1SV19unavailablePropertyxvM
// CHECK-STRIP-NOT: s4Test1SV19unavailablePropertyxvg
// CHECK-STRIP-NOT: s4Test1SV19unavailablePropertyxvs
// CHECK-STRIP-NOT: s4Test1SV19unavailablePropertyxvM
@available(*, unavailable)
public var unavailableProperty: T

// CHECK-NO-STRIP: s4Test1SVyACyxGxcfC
// CHECK-STRIP-NOT: s4Test1SVyACyxGxcfC
@available(*, unavailable)
public init(_ t: T) { fatalError() }

// CHECK-NO-STRIP: s4Test1SV17unavailableMethodyyF
// CHECK-STRIP-NOT: s4Test1SV17unavailableMethodyyF
@available(*, unavailable)
public func unavailableMethod() {}
}

@available(*, unavailable)
extension S {
// CHECK-NO-STRIP: s4Test1SV28methodInUnavailableExtensionyyF
// CHECK-STRIP-NOT: s4Test1SV28methodInUnavailableExtensionyyF
public func methodInUnavailableExtension() {}
}

public enum E {
case a

@available(*, unavailable)
case b

// CHECK-NO-STRIP: s4Test1EO17unavailableMethodyyF
// CHECK-STRIP-NOT: s4Test1EO17unavailableMethodyyF
@available(*, unavailable)
public func unavailableMethod() {}
}

public class C<T> {
// CHECK-NO-STRIP: s4Test1CC19unavailablePropertyxvg
// CHECK-NO-STRIP: s4Test1CC19unavailablePropertyxvs
// CHECK-NO-STRIP: s4Test1CC19unavailablePropertyxvM
// CHECK-STRIP-NOT: s4Test1CC19unavailablePropertyxvg
// CHECK-STRIP-NOT: s4Test1CC19unavailablePropertyxvs
// CHECK-STRIP-NOT: s4Test1CC19unavailablePropertyxvM
@available(*, unavailable)
public var unavailableProperty: T

// CHECK-NO-STRIP: s4Test1CCyACyxGxcfC
// CHECK-NO-STRIP: s4Test1CCyACyxGxcfc
// CHECK-STRIP-NOT: s4Test1CCyACyxGxcfC
// CHECK-STRIP-NOT: s4Test1CCyACyxGxcfc
@available(*, unavailable)
public init(_ t: T) { fatalError() }

// CHECK: s4Test1CCfd
// CHECK: s4Test1CCfD
deinit {}
}

public protocol P {
func requirement()
}

@available(*, unavailable)
extension S: P {
// CHECK-NO-STRIP: s4Test1SV11requirementyyF
// CHECK-STRIP-NOT: s4Test1SV11requirementyyF
public func requirement() {}
}

// CHECK-NO-STRIP: s4Test29unavailableFuncWithNestedTypeyyF
// CHECK-STRIP-NOT: s4Test29unavailableFuncWithNestedTypeyyF
@available(*, unavailable)
public func unavailableFuncWithNestedType() {
struct Nested {
// s4Test29unavailableFuncWithNestedTypeyyF0E0L_V6methodyyF
public func method() {}
}
}

// MARK: -

// MARK: UnavailableEnum

// CHECK-NO-STRIP: s4Test15UnavailableEnumOwug
// CHECK-STRIP-NOT: s4Test15UnavailableEnumOwug

// CHECK-NO-STRIP: s4Test15UnavailableEnumOMa
// CHECK-STRIP-NOT: s4Test15UnavailableEnumOMa

// MARK: UnavailableClass

// CHECK-NO-STRIP: s4Test16UnavailableClassCMa
// CHECK-STRIP-NOT: s4Test16UnavailableClassCMa

// MARK: E

// CHECK: s4Test1EOwug
// CHECK: s4Test1EOMa

// MARK: unavailableFuncWithNestedType().Nested

// CHECK-NO-STRIP: s4Test29unavailableFuncWithNestedTypeyyF0E0L_VMa
// CHECK-STRIP-NOT: s4Test29unavailableFuncWithNestedTypeyyF0E0L_VMa
55 changes: 55 additions & 0 deletions test/IRGen/unavailable_decl_optimization_class.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP

// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP

public class AvailableClass<T> {
// CHECK-NO-STRIP: s4Test14AvailableClassC19unavailablePropertyxvg
// CHECK-NO-STRIP: s4Test14AvailableClassC19unavailablePropertyxvs
// CHECK-NO-STRIP: s4Test14AvailableClassC19unavailablePropertyxvM
// CHECK-STRIP-NOT: s4Test14AvailableClassC19unavailablePropertyxvg
// CHECK-STRIP-NOT: s4Test14AvailableClassC19unavailablePropertyxvs
// CHECK-STRIP-NOT: s4Test14AvailableClassC19unavailablePropertyxvM
@available(*, unavailable)
public var unavailableProperty: T

// CHECK-NO-STRIP: s4Test14AvailableClassCyACyxGxcfC
// CHECK-NO-STRIP: s4Test14AvailableClassCyACyxGxcfc
// CHECK-STRIP-NOT: s4Test14AvailableClassCyACyxGxcfC
// CHECK-STRIP-NOT: s4Test14AvailableClassCyACyxGxcfc
@available(*, unavailable)
public init(_ t: T) { fatalError() }

// CHECK: s4Test14AvailableClassCfd
// CHECK: s4Test14AvailableClassCfD
deinit {}
}

@available(*, unavailable)
public class UnavailableClass<T> {
// CHECK-NO-STRIP: s4Test16UnavailableClassC8propertyxvg
// CHECK-NO-STRIP: s4Test16UnavailableClassC8propertyxvs
// CHECK-NO-STRIP: s4Test16UnavailableClassC8propertyxvM
// CHECK-STRIP-NOT: s4Test16UnavailableClassC8propertyxvg
// CHECK-STRIP-NOT: s4Test16UnavailableClassC8propertyxvs
// CHECK-STRIP-NOT: s4Test16UnavailableClassC8propertyxvM
public var property: T

// CHECK-NO-STRIP: s4Test16UnavailableClassCyACyxGxcfC
// CHECK-NO-STRIP: s4Test16UnavailableClassCyACyxGxcfc
// CHECK-STRIP-NOT: s4Test16UnavailableClassCyACyxGxcfC
// CHECK-STRIP-NOT: s4Test16UnavailableClassCyACyxGxcfc
public init(_ t: T) {
self.property = t
}

// CHECK-NO-STRIP: s4Test16UnavailableClassCfd
// CHECK-NO-STRIP: s4Test16UnavailableClassCfD
// CHECK-STRIP-NOT: s4Test16UnavailableClassCfd
// CHECK-STRIP-NOT: s4Test16UnavailableClassCfD
deinit {}
}

// CHECK: s4Test14AvailableClassCMa

// CHECK-NO-STRIP: s4Test16UnavailableClassCMa
// CHECK-STRIP-NOT: s4Test16UnavailableClassCMa
26 changes: 26 additions & 0 deletions test/IRGen/unavailable_decl_optimization_conformance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP

// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP

// CHECK-NO-STRIP: s4Test1SVAA1PAAMc
// CHECK-STRIP-NOT: s4Test1SVAA1PAAMc

// CHECK-NO-STRIP: s4Test1SVAA1PAAWP
// CHECK-STRIP-NOT: s4Test1SVAA1PAAWP

// CHECK-NO-STRIP: s4Test1PMp
// CHECK-STRIP-NOT: s4Test1PMp

@available(*, unavailable)
public protocol P {
func requirement()
}

public struct S {}

@available(*, unavailable)
extension S: P {
// CHECK-NO-STRIP: s4Test1SV11requirementyyF
// CHECK-STRIP-NOT: s4Test1SV11requirementyyF
public func requirement() {}
}
56 changes: 56 additions & 0 deletions test/IRGen/unavailable_decl_optimization_enum.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP

// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP

// CHECK: private constant [27 x i8] c"availableEnumAvailableCase\00"

// FIXME: Should this reflection metadata for an unavailable case be stripped?
// CHECK: private constant [29 x i8] c"availableEnumUnavailableCase\00"

// CHECK-NO-STRIP: private constant [25 x i8] c"unavailableEnumFirstCase\00"
// CHECK-STRIP-NOT: private constant [25 x i8] c"unavailableEnumFirstCase\00"


public enum AvailableEnum {
case availableEnumAvailableCase

@available(*, unavailable)
case availableEnumUnavailableCase

// CHECK-NO-STRIP: s4Test13AvailableEnumO17unavailableMethodyyF
// CHECK-STRIP-NOT: s4Test13AvailableEnumO17unavailableMethodyyF
@available(*, unavailable)
public func unavailableMethod() {}

// CHECK: s4Test13AvailableEnumO21__derived_enum_equalsySbAC_ACtFZ
// CHECK: s4Test13AvailableEnumO4hash4intoys6HasherVz_tF
// CHECK: s4Test13AvailableEnumO9hashValueSivg
}

@available(*, unavailable)
public enum UnavailableEnum {
case unavailableEnumFirstCase

// CHECK-NO-STRIP: s4Test15UnavailableEnumO6methodyyF
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO6methodyyF
public func method() {}

// CHECK-NO-STRIP: s4Test15UnavailableEnumO21__derived_enum_equalsySbAC_ACtFZ
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO21__derived_enum_equalsySbAC_ACtFZ

// CHECK-NO-STRIP: s4Test15UnavailableEnumO4hash4intoys6HasherVz_tF
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO4hash4intoys6HasherVz_tF

// CHECK-NO-STRIP: s4Test15UnavailableEnumO9hashValueSivg
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO9hashValueSivg
}

// CHECK: s4Test13AvailableEnumOwug

// CHECK: s4Test13AvailableEnumOMa

// CHECK-NO-STRIP: s4Test15UnavailableEnumOwug
// CHECK-STRIP-NOT: s4Test15UnavailableEnumOwug

// CHECK-NO-STRIP: s4Test15UnavailableEnumOMa
// CHECK-STRIP-NOT: s4Test15UnavailableEnumOMa
35 changes: 35 additions & 0 deletions test/IRGen/unavailable_decl_optimization_nested_type.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP

// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP

// CHECK-NO-STRIP: s4Test29unavailableFuncWithNestedTypeyyF
// CHECK-STRIP-NOT: s4Test29unavailableFuncWithNestedTypeyyF
@available(*, unavailable)
public func unavailableFuncWithNestedType() {
struct NestedInFunction {
// s4Test29unavailableFuncWithNestedTypeyyF0E10InFunctionL_VADycfC
init() {}
}

_ = NestedInFunction()
}

// CHECK-NO-STRIP: s4Test29unavailableFuncWithNestedTypeyyF0E10InFunctionL_VADycfC
// CHECK-STRIP-NOT: s4Test29unavailableFuncWithNestedTypeyyF0E10InFunctionL_VADycfC

public struct S {}

extension S {
@available(*, unavailable)
public struct NestedInExtension {
// CHECK-NO-STRIP: s4Test1SV17NestedInExtensionV6methodyyF
// CHECK-STRIP-NOT: s4Test1SV17NestedInExtensionV6methodyyF
public func method() {}
}
}

// CHECK-NO-STRIP: s4Test1SV17NestedInExtensionVMa
// CHECK-STRIP-NOT: s4Test1SV17NestedInExtensionVMa

// CHECK-NO-STRIP: s4Test29unavailableFuncWithNestedTypeyyF0E10InFunctionL_VMa
// CHECK-STRIP-NOT: s4Test29unavailableFuncWithNestedTypeyyF0E10InFunctionL_VMa
Loading