From 4aa516aebbb35b6dd9d8031e268ed1cdd1c38daf Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Sun, 25 May 2025 08:16:22 -0700 Subject: [PATCH] SILGen: Fix `if #available` for unavailable custom domains in zippered modules. When generating SIL for an `if #available(SomeDomain)` query in code being compiled for a zippered target, the generated code was mis-compiled if `SomeDomain` were disabled at compile time. Empty version ranges need to be handled explicitly by `SILGenFunction::emitZipperedOSVersionRangeCheck()`. SILGen still miscompiles `if #unavailable` queries generally in code compiled for a zippered target (rdar://147929876). Resolves rdar://150888941. --- lib/SILGen/SILGenDecl.cpp | 7 +++ ..._custom_domains_maccatalyst_zippered.swift | 59 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 test/IRGen/availability_custom_domains_maccatalyst_zippered.swift diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index cde0970462de2..06c7ba5429117 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -1851,6 +1851,13 @@ SILValue SILGenFunction::emitZipperedOSVersionRangeCheck( return B.createIntegerLiteral(loc, i1, true); } + // If either version is "never" then the check is trivially false because it + // can never succeed. + if (OSVersion.isEmpty() || VariantOSVersion.isEmpty()) { + SILType i1 = SILType::getBuiltinIntegerType(1, getASTContext()); + return B.createIntegerLiteral(loc, i1, false); + } + // The variant-only availability-checking entrypoint is not part // of the Swift 5.0 ABI. It is only available in macOS 10.15 and above. bool isVariantEntrypointAvailable = !TargetTriple.isMacOSXVersionLT(10, 15); diff --git a/test/IRGen/availability_custom_domains_maccatalyst_zippered.swift b/test/IRGen/availability_custom_domains_maccatalyst_zippered.swift new file mode 100644 index 0000000000000..430af01654955 --- /dev/null +++ b/test/IRGen/availability_custom_domains_maccatalyst_zippered.swift @@ -0,0 +1,59 @@ +// RUN: %target-swift-emit-irgen -module-name Test %s -verify \ +// RUN: -enable-experimental-feature CustomAvailability \ +// RUN: -define-enabled-availability-domain EnabledDomain \ +// RUN: -define-disabled-availability-domain DisabledDomain \ +// RUN: -target %target-cpu-apple-macosx13 \ +// RUN: -target-variant %target-cpu-apple-ios16-macabi \ +// RUN: -Onone | %FileCheck %s --check-prefixes=CHECK + +// RUN: %target-swift-emit-irgen -module-name Test %s -verify \ +// RUN: -enable-experimental-feature CustomAvailability \ +// RUN: -define-enabled-availability-domain EnabledDomain \ +// RUN: -define-disabled-availability-domain DisabledDomain \ +// RUN: -target %target-cpu-apple-macosx13 \ +// RUN: -target-variant %target-cpu-apple-ios16-macabi \ +// RUN: -O | %FileCheck %s --check-prefixes=CHECK + +// REQUIRES: OS=macosx || OS=maccatalyst +// REQUIRES: swift_feature_CustomAvailability + +@_silgen_name("always") +public func always() + +@_silgen_name("never") +public func never() + +// CHECK-NOT: call swiftcc void @never() + +// CHECK: call swiftcc void @always() +// CHECK-NOT: call swiftcc void @never() +if #available(EnabledDomain) { + always() +} else { + never() +} + +// CHECK: call swiftcc void @always() +// CHECK-NOT: call swiftcc void @never() +if #available(DisabledDomain) { + never() +} else { + always() +} + +// FIXME: [availability] These CHECK lines for if #unavailable are inverted (rdar://147929876) +// CHECK-NOT: call swiftcc void @always() +// CHECK: call swiftcc void @never() +if #unavailable(EnabledDomain) { + never() +} else { + always() +} + +// CHECK-NOT: call swiftcc void @always() +// CHECK: call swiftcc void @never() +if #unavailable(DisabledDomain) { + always() +} else { + never() +}