Skip to content

Upstream support for the Xcode 26 SDKs #82153

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 7 commits into from
Jun 11, 2025
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
4 changes: 4 additions & 0 deletions include/swift/AST/AvailabilityDomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ class AvailabilityDomain final {
/// version ranges.
bool isVersioned() const;

/// Returns true if the given version is a valid version number for this
/// domain. It is an error to call this on an un-versioned domain.
bool isVersionValid(const llvm::VersionTuple &version) const;

/// Returns true if availability of the domain can be refined using
/// `@available` attributes and `if #available` queries. If not, then the
/// domain's availability is fixed by compilation settings. For example,
Expand Down
11 changes: 11 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,14 @@ ERROR(serialization_failed,none,
WARNING(can_import_invalid_swiftmodule,none,
"canImport() evaluated to false due to invalid swiftmodule: %0", (StringRef))

ERROR(map_os_version_from_textual_interface_failed,none,
"failed to map OS version from %0 to %1 in %2",
(StringRef, StringRef, StringRef))

ERROR(target_os_version_from_textual_interface_invalid,none,
"invalid target triple %0 in %1",
(StringRef, StringRef))

ERROR(serialization_load_failed,Fatal,
"failed to load module '%0'", (StringRef))
ERROR(module_interface_build_failed,Fatal,
Expand Down Expand Up @@ -6929,6 +6937,9 @@ GROUPED_ERROR(availability_suggest_platform_name,
(Identifier, StringRef))
WARNING(availability_unsupported_version_number, none,
"'%0' is not a supported version number", (llvm::VersionTuple))
WARNING(availability_invalid_version_number_for_domain, none,
"'%0' is not a valid version number for %1",
(llvm::VersionTuple, AvailabilityDomain))

WARNING(attr_availability_expected_deprecated_version, none,
"expected version number with 'deprecated' in '%0' attribute for %1",
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/PlatformKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "swift/Config.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>

namespace swift {
Expand Down Expand Up @@ -91,6 +92,10 @@ PlatformKind targetVariantPlatform(const LangOptions &LangOpts);
/// an explicit attribute for the child.
bool inheritsAvailabilityFromPlatform(PlatformKind Child, PlatformKind Parent);

/// Returns the LLVM triple OS type for the given platform, if there is one.
std::optional<llvm::Triple::OSType>
tripleOSTypeForPlatform(PlatformKind platform);

llvm::VersionTuple canonicalizePlatformVersion(
PlatformKind platform, const llvm::VersionTuple &version);

Expand Down
3 changes: 2 additions & 1 deletion include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ class SerializedASTFile final : public LoadedFile {
bool extractCompilerFlagsFromInterface(
StringRef interfacePath, StringRef buffer, llvm::StringSaver &ArgSaver,
SmallVectorImpl<const char *> &SubArgs,
std::optional<llvm::Triple> PreferredTarget = std::nullopt);
std::optional<llvm::Triple> PreferredTarget = std::nullopt,
DiagnosticEngine *diagEngine = nullptr);

/// Extract the user module version number from an interface file.
llvm::VersionTuple extractUserModuleVersionFromInterface(StringRef moduleInterfacePath);
Expand Down
17 changes: 7 additions & 10 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2375,16 +2375,13 @@ static StringRef getLinkerModuleName(StringRef OriginalModuleName) {
}

OriginallyDefinedInAttr::OriginallyDefinedInAttr(
SourceLoc AtLoc, SourceRange Range,
StringRef OriginalModuleName,
PlatformKind Platform,
const llvm::VersionTuple MovedVersion, bool Implicit)
: DeclAttribute(DeclAttrKind::OriginallyDefinedIn, AtLoc, Range,
Implicit),
ManglingModuleName(getManglingModuleName(OriginalModuleName)),
LinkerModuleName(getLinkerModuleName(OriginalModuleName)),
Platform(Platform),
MovedVersion(MovedVersion) {}
SourceLoc AtLoc, SourceRange Range, StringRef OriginalModuleName,
PlatformKind Platform, const llvm::VersionTuple MovedVersion, bool Implicit)
: DeclAttribute(DeclAttrKind::OriginallyDefinedIn, AtLoc, Range, Implicit),
ManglingModuleName(getManglingModuleName(OriginalModuleName)),
LinkerModuleName(getLinkerModuleName(OriginalModuleName)),
Platform(Platform),
MovedVersion(canonicalizePlatformVersion(Platform, MovedVersion)) {}

std::optional<OriginallyDefinedInAttr::ActiveVersion>
OriginallyDefinedInAttr::isActivePlatform(const ASTContext &ctx) const {
Expand Down
15 changes: 14 additions & 1 deletion lib/AST/Availability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,14 +832,27 @@ SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,

auto checkVersion = [&](std::optional<llvm::VersionTuple> version,
SourceRange sourceRange) {
if (version && !VersionRange::isValidVersion(*version)) {
if (!version)
return false;

if (!VersionRange::isValidVersion(*version)) {
diags
.diagnose(attrLoc, diag::availability_unsupported_version_number,
*version)
.highlight(sourceRange);
return true;
}

// Warn if the version is not a valid one for the domain. For example, macOS
// 17 will never exist.
if (domain->isVersioned() && !domain->isVersionValid(*version)) {
diags
.diagnose(attrLoc,
diag::availability_invalid_version_number_for_domain,
*version, *domain)
.highlight(sourceRange);
}

return false;
};

Expand Down
20 changes: 20 additions & 0 deletions lib/AST/AvailabilityDomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ bool AvailabilityDomain::isVersioned() const {
}
}

bool AvailabilityDomain::isVersionValid(
const llvm::VersionTuple &version) const {
ASSERT(isVersioned());

switch (getKind()) {
case Kind::Universal:
case Kind::Embedded:
llvm_unreachable("unexpected domain kind");
case Kind::SwiftLanguage:
case Kind::PackageDescription:
return true;
case Kind::Platform:
if (auto osType = tripleOSTypeForPlatform(getPlatformKind()))
return llvm::Triple::isValidVersionForOS(*osType, version);
return true;
case Kind::Custom:
return true;
}
}

bool AvailabilityDomain::supportsContextRefinement() const {
switch (getKind()) {
case Kind::Universal:
Expand Down
46 changes: 37 additions & 9 deletions lib/AST/PlatformKind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,43 @@ bool swift::inheritsAvailabilityFromPlatform(PlatformKind Child,
return false;
}

llvm::VersionTuple swift::canonicalizePlatformVersion(
PlatformKind platform, const llvm::VersionTuple &version) {

// Canonicalize macOS version for macOS Big Sur to treat
// 10.16 as 11.0.
if (platform == PlatformKind::macOS ||
platform == PlatformKind::macOSApplicationExtension) {
return llvm::Triple::getCanonicalVersionForOS(llvm::Triple::MacOSX,
version);
std::optional<llvm::Triple::OSType>
swift::tripleOSTypeForPlatform(PlatformKind platform) {
switch (platform) {
case PlatformKind::macOS:
case PlatformKind::macOSApplicationExtension:
return llvm::Triple::MacOSX;
case PlatformKind::iOS:
case PlatformKind::iOSApplicationExtension:
case PlatformKind::macCatalyst:
case PlatformKind::macCatalystApplicationExtension:
return llvm::Triple::IOS;
case PlatformKind::tvOS:
case PlatformKind::tvOSApplicationExtension:
return llvm::Triple::TvOS;
case PlatformKind::watchOS:
case PlatformKind::watchOSApplicationExtension:
return llvm::Triple::WatchOS;
case PlatformKind::visionOS:
case PlatformKind::visionOSApplicationExtension:
return llvm::Triple::XROS;
case PlatformKind::OpenBSD:
return llvm::Triple::OpenBSD;
case PlatformKind::Windows:
return llvm::Triple::Win32;
case PlatformKind::none:
return std::nullopt;
}
llvm_unreachable("bad PlatformKind");
}

llvm::VersionTuple
swift::canonicalizePlatformVersion(PlatformKind platform,
const llvm::VersionTuple &version) {
if (auto osType = tripleOSTypeForPlatform(platform)) {
bool isInValidRange = llvm::Triple::isValidVersionForOS(*osType, version);
return llvm::Triple::getCanonicalVersionForOS(*osType, version,
isInValidRange);
}

return version;
Expand Down
2 changes: 1 addition & 1 deletion lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1547,7 +1547,7 @@ static bool readSwiftInterfaceVersionAndArgs(

if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver,
interfaceInfo.Arguments,
preferredTarget)) {
preferredTarget, &Diags)) {
InterfaceSubContextDelegateImpl::diagnose(
interfacePath, diagnosticLoc, SM, &Diags,
diag::error_extracting_version_from_module_interface);
Expand Down
72 changes: 56 additions & 16 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1470,30 +1470,70 @@ static std::optional<StringRef> getFlagsFromInterfaceFile(StringRef &file,
bool swift::extractCompilerFlagsFromInterface(
StringRef interfacePath, StringRef buffer, llvm::StringSaver &ArgSaver,
SmallVectorImpl<const char *> &SubArgs,
std::optional<llvm::Triple> PreferredTarget) {
std::optional<llvm::Triple> PreferredTarget, DiagnosticEngine *Diag) {
auto FlagMatch = getFlagsFromInterfaceFile(buffer, SWIFT_MODULE_FLAGS_KEY);
if (!FlagMatch)
return true;
llvm::cl::TokenizeGNUCommandLine(*FlagMatch, ArgSaver, SubArgs);

// If the target triple parsed from the Swift interface file differs
// only in subarchitecture from the compatible target triple, then
// we have loaded a Swift interface from a different-but-compatible
// architecture slice. Use the compatible subarchitecture.
if (PreferredTarget) {
for (unsigned I = 1; I < SubArgs.size(); ++I) {
if (strcmp(SubArgs[I - 1], "-target") != 0 &&
strcmp(SubArgs[I - 1], "-target-variant") != 0)
continue;
for (unsigned I = 1; I < SubArgs.size(); ++I) {
if (strcmp(SubArgs[I - 1], "-target") != 0 &&
strcmp(SubArgs[I - 1], "-target-variant") != 0)
continue;

llvm::Triple triple(SubArgs[I]);
if (triple.getArch() != PreferredTarget->getArch())
continue;
if (triple.getSubArch() == PreferredTarget->getSubArch())
continue;
llvm::Triple triple(SubArgs[I]);
bool shouldModify = false;
// If the target triple parsed from the swiftinterface file differs
// only in subarchitecture from the compatible target triple, then
// we have loaded a Swift interface from a different-but-compatible
// architecture slice. Use the compatible subarchitecture.
if (PreferredTarget && triple.getArch() == PreferredTarget->getArch() &&
triple.getSubArch() != PreferredTarget->getSubArch()) {
triple.setArch(PreferredTarget->getArch(), PreferredTarget->getSubArch());
SubArgs[I] = ArgSaver.save(triple.str()).data();
shouldModify = true;
}

// Diagnose if the version in the target triple parsed from the
// swiftinterface is invalid for the OS.
const llvm::VersionTuple originalVer = triple.getOSVersion();
bool isValidVersion =
llvm::Triple::isValidVersionForOS(triple.getOS(), originalVer);
if (!isValidVersion) {
if (Diag) {
Diag->diagnose(SourceLoc(),
diag::target_os_version_from_textual_interface_invalid,
triple.str(), interfacePath);
}
break;
}

// Canonicalize the version in the target triple parsed from the
// swiftinterface.
llvm::VersionTuple newVer = llvm::Triple::getCanonicalVersionForOS(
triple.getOS(), originalVer, isValidVersion);
if (originalVer != newVer) {
std::string originalOSName = triple.getOSName().str();
std::string originalVerStr = originalVer.getAsString();
std::string newVerStr = newVer.getAsString();
const int OSNameWithoutVersionLength =
originalOSName.size() - originalVerStr.size();
if (!StringRef(originalOSName).ends_with(originalVerStr) ||
(OSNameWithoutVersionLength <= 0)) {
if (Diag) {
Diag->diagnose(SourceLoc(),
diag::map_os_version_from_textual_interface_failed,
originalVerStr, newVerStr, interfacePath);
}
break;
}
llvm::SmallString<64> buffer(
originalOSName.substr(0, OSNameWithoutVersionLength));
buffer.append(newVerStr);
triple.setOSName(buffer.str());
shouldModify = true;
}
if (shouldModify)
SubArgs[I] = ArgSaver.save(triple.str()).data();
}

auto IgnFlagMatch =
Expand Down
18 changes: 3 additions & 15 deletions stdlib/public/Concurrency/DispatchGlobalExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,22 +314,10 @@ clock_and_value_to_time(int clock, long long sec, long long nsec) {
case swift_clock_id_continuous:
return value | DISPATCH_UP_OR_MONOTONIC_TIME_MASK;
case swift_clock_id_wall: {
#if defined(_WIN32)
struct timespec ts = {
.tv_sec = sec,
.tv_nsec = static_cast<long>(nsec)
};
#elif defined(__APPLE__)
struct timespec ts = {
.tv_sec = static_cast<__darwin_time_t>(sec),
.tv_nsec = nsec
struct timespec ts = {
.tv_sec = static_cast<decltype(ts.tv_sec)>(sec),
.tv_nsec = static_cast<decltype(ts.tv_nsec)>(nsec)
};
#else
struct timespec ts = {
.tv_sec = static_cast<long>(sec),
.tv_nsec = static_cast<long>(nsec)
};
#endif
return dispatch_walltime(&ts, 0);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,20 @@ void FunctionIntroducedIn10_16();
__attribute__((availability(macosx,introduced=11.0)))
void FunctionIntroducedIn11_0();

__attribute__((availability(macosx,introduced=16.0)))
void FunctionIntroducedIn16_0();

__attribute__((availability(macosx,introduced=26.0)))
void FunctionIntroducedIn26_0();

__attribute__((availability(macosx_app_extension,introduced=10.16)))
void FunctionIntroducedIn10_16AppExt();

__attribute__((availability(macosx_app_extension,introduced=11.0)))
void FunctionIntroducedIn11_0AppExt();

__attribute__((availability(macosx_app_extension,introduced=16.0)))
void FunctionIntroducedIn16_0AppExt();

__attribute__((availability(macosx_app_extension,introduced=26.0)))
void FunctionIntroducedIn26_0AppExt();
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ FunctionIntroducedIn10_16()
FunctionIntroducedIn11_0()
// expected-error@-1 {{'FunctionIntroducedIn11_0()' is only available in macOS 11.0 or newer}}
// expected-note@-2 {{add 'if #available' version check}}

FunctionIntroducedIn16_0()
// expected-error@-1 {{'FunctionIntroducedIn16_0()' is only available in macOS 26.0 or newer}}
// expected-note@-2 {{add 'if #available' version check}}

FunctionIntroducedIn26_0()
// expected-error@-1 {{'FunctionIntroducedIn26_0()' is only available in macOS 26.0 or newer}}
// expected-note@-2 {{add 'if #available' version check}}
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ FunctionIntroducedIn10_16AppExt()
FunctionIntroducedIn11_0AppExt()
// expected-error@-1 {{'FunctionIntroducedIn11_0AppExt()' is only available in application extensions for macOS 11.0 or newer}}
// expected-note@-2 {{add 'if #available' version check}}

FunctionIntroducedIn16_0AppExt()
// expected-error@-1 {{'FunctionIntroducedIn16_0AppExt()' is only available in application extensions for macOS 26.0 or newer}}
// expected-note@-2 {{add 'if #available' version check}}

FunctionIntroducedIn26_0AppExt()
// expected-error@-1 {{'FunctionIntroducedIn26_0AppExt()' is only available in application extensions for macOS 26.0 or newer}}
// expected-note@-2 {{add 'if #available' version check}}
4 changes: 2 additions & 2 deletions test/Constraints/operator_availability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ public func ~><T> (lhs: T, rhs: (T) -> Void) -> T {
}

struct S {
@available(macOS 20, *)
@available(macOS 50, *)
func f() {}
}

let s = S() ~> {
if #available(macOS 20.0, *) {
if #available(macOS 50.0, *) {
$0.f()
}
}
Loading