Author: Cyndy Ishida Date: 2025-06-10T09:50:46-07:00 New Revision: 88f041f3e05e26617856cc096d2e2864dfaa1c7b
URL: https://github.com/llvm/llvm-project/commit/88f041f3e05e26617856cc096d2e2864dfaa1c7b DIFF: https://github.com/llvm/llvm-project/commit/88f041f3e05e26617856cc096d2e2864dfaa1c7b.diff LOG: [clang][Darwin] Align all OS Versions for 26 (#143548) * Translate the following versions to 26. * watchOS 12 -> 26 * visionOS 3 -> 26 * macos 16 -> 26 * iOS 19 -> 26 * tvOS 19 -> 26 * Emit diagnostics, but allow conversion when clients attempt to use invalid gaps in OS versioning in availability. * For target-triples, only allow "valid" versions for implicit conversions. Added: clang/test/CodeGen/attr-availability-aligned-versions.c clang/test/Driver/darwin-invalid-os-versions.c clang/test/Sema/Inputs/XROS.sdk/SDKSettings.json clang/test/Sema/attr-availability-invalid-os-versions.c clang/test/Sema/attr-availability-ios-aligned-versions.c clang/test/Sema/attr-availability-ios-fallback-aligned-versions.c Modified: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Driver/ToolChains/Darwin.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaExprObjC.cpp clang/test/Driver/darwin-infer-simulator-sdkroot.c clang/test/Driver/darwin-ld-platform-version-macos.c clang/test/Driver/darwin-ld-platform-version-watchos.c clang/test/ExtractAPI/availability.c clang/test/ExtractAPI/inherited_availability.m clang/test/Sema/attr-availability-iosmac-infer-from-macos.c llvm/include/llvm/TargetParser/Triple.h llvm/lib/TargetParser/Triple.cpp llvm/lib/TextAPI/Platform.cpp llvm/unittests/TargetParser/TripleTest.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index f889e41c8699f..bd07bb1361a85 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1111,6 +1111,8 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { return llvm::StringSwitch<llvm::StringRef>(Platform) .Case("iOS", "ios") .Case("macOS", "macos") + .Case("macOSX", "macos") + .Case("macosx", "macos") .Case("tvOS", "tvos") .Case("watchOS", "watchos") .Case("iOSApplicationExtension", "ios_app_extension") @@ -1175,6 +1177,26 @@ static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environm .Case("library", llvm::Triple::Library) .Default(llvm::Triple::UnknownEnvironment); } + +static llvm::Triple::OSType getOSType(llvm::StringRef Platform) { + using OSType = llvm::Triple::OSType; + return llvm::StringSwitch<OSType>(Platform) + .Case("ios", OSType::IOS) + .Case("macos", OSType::MacOSX) + .Case("maccatalyst", OSType::IOS) + .Case("tvos", OSType::TvOS) + .Case("watchos", OSType::WatchOS) + .Case("bridgeos", OSType::BridgeOS) + .Case("ios_app_extension", OSType::IOS) + .Case("maccatalyst_app_extension", OSType::IOS) + .Case("macos_app_extension", OSType::MacOSX) + .Case("tvos_app_extension", OSType::TvOS) + .Case("watchos_app_extension", OSType::WatchOS) + .Case("xros", OSType::XROS) + .Case("xros_app_extension", OSType::XROS) + .Default(OSType::UnknownOS); +} + }]; let HasCustomParsing = 1; let InheritEvenIfAlreadyPresent = 1; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1f283b776a02c..0f77083dac9df 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4063,6 +4063,9 @@ def warn_at_available_unchecked_use : Warning< "%select{@available|__builtin_available}0 does not guard availability here; " "use if (%select{@available|__builtin_available}0) instead">, InGroup<DiagGroup<"unsupported-availability-guard">>; +def warn_availability_invalid_os_version + : Warning<"invalid %1 version '%0' in availability attribute">, InGroup<DiagGroup<"invalid-version-availability">>; +def note_availability_invalid_os_version_adjusted: Note<"implicitly treating version as '%0'">; def warn_missing_sdksettings_for_availability_checking : Warning< "%0 availability is ignored without a valid 'SDKSettings.json' in the SDK">, diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 59f423b633464..e987ef78920e8 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1721,10 +1721,14 @@ struct DarwinPlatform { UnderlyingOSVersion.reset(); return Result; } + bool isValidOSVersion() const { + return llvm::Triple::isValidVersionForOS(getOSFromPlatform(Platform), + getOSVersion()); + } VersionTuple getCanonicalOSVersion() const { - return llvm::Triple::getCanonicalVersionForOS(getOSFromPlatform(Platform), - getOSVersion()); + return llvm::Triple::getCanonicalVersionForOS( + getOSFromPlatform(Platform), getOSVersion(), /*IsInValidRange=*/true); } void setOSVersion(const VersionTuple &Version) { @@ -2451,6 +2455,9 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } assert(PlatformAndVersion && "Unable to infer Darwin variant"); + if (!PlatformAndVersion->isValidOSVersion()) + getDriver().Diag(diag::err_drv_invalid_version_number) + << PlatformAndVersion->getAsString(Args, Opts); // After the deployment OS version has been resolved, set it to the canonical // version before further error detection and converting to a proper target // triple. @@ -2552,6 +2559,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { ZipperedOSVersion = PlatformAndVersion->getZipperedOSVersion(); setTarget(Platform, Environment, Major, Minor, Micro, ZipperedOSVersion); TargetVariantTriple = PlatformAndVersion->getTargetVariantTriple(); + if (TargetVariantTriple && + !llvm::Triple::isValidVersionForOS(TargetVariantTriple->getOS(), + TargetVariantTriple->getOSVersion())) { + getDriver().Diag(diag::err_drv_invalid_version_number) + << TargetVariantTriple->str(); + } if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef SDK = getSDKName(A->getValue()); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index da0e3265767d8..6360827f415b8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2374,7 +2374,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *Platform = AL.getArgAsIdent(0); IdentifierInfo *II = Platform->getIdentifierInfo(); - if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) + StringRef PrettyName = AvailabilityAttr::getPrettyPlatformName(II->getName()); + if (PrettyName.empty()) S.Diag(Platform->getLoc(), diag::warn_availability_unknown_platform) << Platform->getIdentifierInfo(); @@ -2385,6 +2386,32 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AvailabilityChange Introduced = AL.getAvailabilityIntroduced(); AvailabilityChange Deprecated = AL.getAvailabilityDeprecated(); AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted(); + + const llvm::Triple::OSType PlatformOS = AvailabilityAttr::getOSType( + AvailabilityAttr::canonicalizePlatformName(II->getName())); + + auto reportAndUpdateIfInvalidOS = [&](auto &InputVersion) -> void { + const bool IsInValidRange = + llvm::Triple::isValidVersionForOS(PlatformOS, InputVersion); + // Canonicalize availability versions. + auto CanonicalVersion = llvm::Triple::getCanonicalVersionForOS( + PlatformOS, InputVersion, IsInValidRange); + if (!IsInValidRange) { + S.Diag(Platform->getLoc(), diag::warn_availability_invalid_os_version) + << InputVersion.getAsString() << PrettyName; + S.Diag(Platform->getLoc(), + diag::note_availability_invalid_os_version_adjusted) + << CanonicalVersion.getAsString(); + } + InputVersion = CanonicalVersion; + }; + + if (PlatformOS != llvm::Triple::OSType::UnknownOS) { + reportAndUpdateIfInvalidOS(Introduced.Version); + reportAndUpdateIfInvalidOS(Deprecated.Version); + reportAndUpdateIfInvalidOS(Obsoleted.Version); + } + bool IsUnavailable = AL.getUnavailableLoc().isValid(); bool IsStrict = AL.getStrictLoc().isValid(); StringRef Str; @@ -2476,7 +2503,11 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } auto Major = Version.getMajor(); - auto NewMajor = Major >= 9 ? Major - 7 : 0; + auto NewMajor = Major; + if (Major < 9) + NewMajor = 0; + else if (Major < 12) + NewMajor = Major - 7; if (NewMajor >= 2) { if (Version.getMinor()) { if (Version.getSubminor()) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index b248ea380a526..3505d9f38d23c 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -5151,7 +5151,8 @@ ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr( SourceLocation RParen) { ASTContext &Context = getASTContext(); auto FindSpecVersion = - [&](StringRef Platform) -> std::optional<VersionTuple> { + [&](StringRef Platform, + const llvm::Triple::OSType &OS) -> std::optional<VersionTuple> { auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { return Spec.getPlatform() == Platform; }); @@ -5164,12 +5165,16 @@ ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr( } if (Spec == AvailSpecs.end()) return std::nullopt; - return Spec->getVersion(); + + return llvm::Triple::getCanonicalVersionForOS( + OS, Spec->getVersion(), + llvm::Triple::isValidVersionForOS(OS, Spec->getVersion())); }; VersionTuple Version; if (auto MaybeVersion = - FindSpecVersion(Context.getTargetInfo().getPlatformName())) + FindSpecVersion(Context.getTargetInfo().getPlatformName(), + Context.getTargetInfo().getTriple().getOS())) Version = *MaybeVersion; // The use of `@available` in the enclosing context should be analyzed to diff --git a/clang/test/CodeGen/attr-availability-aligned-versions.c b/clang/test/CodeGen/attr-availability-aligned-versions.c new file mode 100644 index 0000000000000..5555fa8e7f690 --- /dev/null +++ b/clang/test/CodeGen/attr-availability-aligned-versions.c @@ -0,0 +1,28 @@ +/// This test verifies IR generated for APIs protected with availability annotations with a common versions. +// RUN: %clang_cc1 -fvisibility=hidden "-triple" "arm64-apple-ios26.0" -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fvisibility=hidden "-triple" "arm64-apple-tvos26" -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fvisibility=hidden "-triple" "arm64-apple-watchos26" -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fvisibility=hidden "-triple" "arm64-apple-ios18" -emit-llvm -o - %s | FileCheck -check-prefix=OLD %s + +__attribute__((availability(ios,introduced=19))) +void f0(void); + +__attribute__((availability(ios,introduced=26))) +void f1(void); + +__attribute__((availability(ios,introduced=27))) +void f2(void); + +// OLD: declare extern_weak void @f0 +// OLD: declare extern_weak void @f1 +// OLD: declare extern_weak void @f2 + +// CHECK: declare void @f0 +// CHECK: declare void @f1 +// CHECK: declare extern_weak void @f2 + +void test() { + f0(); + f1(); + f2(); +} diff --git a/clang/test/Driver/darwin-infer-simulator-sdkroot.c b/clang/test/Driver/darwin-infer-simulator-sdkroot.c index 519e6d27540e3..a946015028aa3 100644 --- a/clang/test/Driver/darwin-infer-simulator-sdkroot.c +++ b/clang/test/Driver/darwin-infer-simulator-sdkroot.c @@ -41,9 +41,9 @@ // // RUN: rm -rf %t/SDKs/WatchOS3.0.sdk // RUN: mkdir -p %t/SDKs/WatchOS3.0.sdk -// RUN: env SDKROOT=%t/SDKs/WatchOS3.0.sdk %clang %s -fuse-ld= -mlinker-version=400 -### 2>&1 \ +// RUN: env SDKROOT=%t/SDKs/WatchOS3.0.sdk %clang %s -fuse-ld= -arch arm64_32 -mlinker-version=400 -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WATCH %s -// RUN: env WATCHOS_DEPLOYMENT_TARGET=3.0 %clang %s -fuse-ld= -isysroot %t/SDKs/WatchOS3.0.sdk -mlinker-version=400 -### 2>&1 \ +// RUN: env WATCHOS_DEPLOYMENT_TARGET=3.0 %clang %s -fuse-ld= -arch arm64_32 -isysroot %t/SDKs/WatchOS3.0.sdk -mlinker-version=400 -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WATCH %s // // CHECK-WATCH: clang diff --git a/clang/test/Driver/darwin-invalid-os-versions.c b/clang/test/Driver/darwin-invalid-os-versions.c new file mode 100644 index 0000000000000..d9424c1e67280 --- /dev/null +++ b/clang/test/Driver/darwin-invalid-os-versions.c @@ -0,0 +1,22 @@ +/// Verify invalid OSVersions are diagnosed. + +// RUN: not %clang -target arm64-apple-ios20 -c %s 2>&1 | FileCheck %s --check-prefix=IOS +// IOS: error: invalid version number in '-target arm64-apple-ios20' + +// RUN: not %clang -target arm64-apple-watchos20 -c %s 2>&1 | FileCheck %s --check-prefix=WATCHOS +// WATCHOS: error: invalid version number in '-target arm64-apple-watchos20' + +// RUN: not %clang -target arm64-apple-macosx19 -c %s 2>&1 | FileCheck %s --check-prefix=MAC +// MAC: error: invalid version number in '-target arm64-apple-macosx19' + +// RUN: not %clang -target arm64-apple-ios22-macabi -c %s 2>&1 | FileCheck %s --check-prefix=IOSMAC +// IOSMAC: error: invalid version number in '-target arm64-apple-ios22-macabi' + +// RUN: not %clang -target arm64-apple-macosx16 -darwin-target-variant arm64-apple-ios22-macabi -c %s 2>&1 | FileCheck %s --check-prefix=ZIPPERED +// ZIPPERED: error: invalid version number in 'arm64-apple-ios22-macabi' + +// RUN: not %clang -target arm64-apple-visionos5 -c %s 2>&1 | FileCheck %s --check-prefix=VISION +// VISION: error: invalid version number in '-target arm64-apple-visionos5' + +// RUN: not %clang -target arm64-apple-tvos21 -c %s 2>&1 | FileCheck %s --check-prefix=TV +// TV: error: invalid version number in '-target arm64-apple-tvos21' diff --git a/clang/test/Driver/darwin-ld-platform-version-macos.c b/clang/test/Driver/darwin-ld-platform-version-macos.c index 355df8dfc1bc2..b16ca8a853745 100644 --- a/clang/test/Driver/darwin-ld-platform-version-macos.c +++ b/clang/test/Driver/darwin-ld-platform-version-macos.c @@ -48,3 +48,8 @@ // RUN: -### %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=NOSDK %s // NOSDK: "-platform_version" "macos" "10.13.0" "10.13.0" + +// RUN: %clang -target arm64-apple-macos26 -mlinker-version=520 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=VERSION_BUMP %s +// VERSION_BUMP: "-platform_version" "macos" "26.0.0" "26.0.0" diff --git a/clang/test/Driver/darwin-ld-platform-version-watchos.c b/clang/test/Driver/darwin-ld-platform-version-watchos.c index fc8e859f30efa..afbc3194963fb 100644 --- a/clang/test/Driver/darwin-ld-platform-version-watchos.c +++ b/clang/test/Driver/darwin-ld-platform-version-watchos.c @@ -17,6 +17,54 @@ // RUN: -### %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=SIMUL %s +// RUN: %clang -target arm64-apple-watchos6.3 -fuse-ld= \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=400 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-OLD %s + +// RUN: %clang -target arm64e-apple-watchos6.3 -fuse-ld= \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=400 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-OLD %s + +// RUN: %clang -target arm64-apple-watchos26.1 -fuse-ld= \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=400 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-OLD-261 %s + +// RUN: %clang -target arm64-apple-watchos6.3 -fuse-ld=lld \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=0 \ +// RUN: -### %t.o -B%S/Inputs/lld 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-NEW %s + +// RUN: %clang -target arm64e-apple-watchos6.3 -fuse-ld=lld \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=0 \ +// RUN: -### %t.o -B%S/Inputs/lld 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-NEW %s + +// RUN: %clang -target arm64-apple-watchos6.3 -fuse-ld= \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=520 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-NEW %s + +// RUN: %clang -target arm64-apple-watchos26.1 -fuse-ld= \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=520 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-LINKER-NEW-261 %s + +// RUN: %clang -target arm64-apple-watchos6-simulator -fuse-ld= \ +// RUN: -isysroot %S/Inputs/WatchOS6.0.sdk -mlinker-version=520 \ +// RUN: -### %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=ARM64-SIMUL %s + // LINKER-OLD: "-watchos_version_min" "5.2.0" // LINKER-NEW: "-platform_version" "watchos" "5.2.0" "6.0" // SIMUL: "-platform_version" "watchos-simulator" "6.0.0" "6.0" + +// ARM64-LINKER-OLD: "-watchos_version_min" "26.0.0" +// ARM64-LINKER-OLD-261: "-watchos_version_min" "26.1.0" + +// ARM64-LINKER-NEW: "-platform_version" "watchos" "26.0.0" "6.0" +// ARM64-LINKER-NEW-261: "-platform_version" "watchos" "26.1.0" "6.0" + +// ARM64-SIMUL: "-platform_version" "watchos-simulator" "7.0.0" "6.0" diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c index 237b2ffa55d7d..4f7e21a5c3765 100644 --- a/clang/test/ExtractAPI/availability.c +++ b/clang/test/ExtractAPI/availability.c @@ -17,7 +17,7 @@ void a(void) __attribute__((availability(macos, introduced=12.0))); // A-NEXT: ] // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix B -void b(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=20.0))); +void b(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=30.0))); // B-LABEL: "!testLabel": "c:@F@b" // B: "availability": [ // B-NEXT: { @@ -33,7 +33,7 @@ void b(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0 // B-NEXT: "patch": 0 // B-NEXT: }, // B-NEXT: "obsoleted": { -// B-NEXT: "major": 20, +// B-NEXT: "major": 30, // B-NEXT: "minor": 0, // B-NEXT: "patch": 0 // B-NEXT: } @@ -41,7 +41,7 @@ void b(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0 // B-NEXT: ] // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix E -void c(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=20.0))) __attribute__((availability(ios, introduced=13.0))); +void c(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0, obsoleted=30.0))) __attribute__((availability(ios, introduced=13.0))); // C-LABEL: "!testLabel": "c:@F@c" // C: "availability": [ // C-NEXT: { @@ -57,7 +57,7 @@ void c(void) __attribute__((availability(macos, introduced=11.0, deprecated=12.0 // C-NEXT: "patch": 0 // C-NEXT: }, // C-NEXT: "obsoleted": { -// C-NEXT: "major": 20, +// C-NEXT: "major": 30, // C-NEXT: "minor": 0, // C-NEXT: "patch": 0 // C-NEXT: } diff --git a/clang/test/ExtractAPI/inherited_availability.m b/clang/test/ExtractAPI/inherited_availability.m index c24e7fa8e208f..3d9f953bbda1f 100644 --- a/clang/test/ExtractAPI/inherited_availability.m +++ b/clang/test/ExtractAPI/inherited_availability.m @@ -4,7 +4,7 @@ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix A -__attribute__((availability(macos, introduced=9.0, deprecated=12.0, obsoleted=20.0))) +__attribute__((availability(macos, introduced=9.0, deprecated=12.0, obsoleted=30.0))) @interface A // A-LABEL: "!testLabel": "c:objc(cs)A" // A: "availability": [ @@ -21,7 +21,7 @@ @interface A // A-NEXT: "patch": 0 // A-NEXT: } // A-NEXT: "obsoleted": { -// A-NEXT: "major": 20, +// A-NEXT: "major": 30, // A-NEXT: "minor": 0, // A-NEXT: "patch": 0 // A-NEXT: } @@ -45,7 +45,7 @@ @interface A // CP-NEXT: "patch": 0 // CP-NEXT: } // CP-NEXT: "obsoleted": { -// CP-NEXT: "major": 20, +// CP-NEXT: "major": 30, // CP-NEXT: "minor": 0, // CP-NEXT: "patch": 0 // CP-NEXT: } @@ -69,7 +69,7 @@ @interface A // IP-NEXT: "patch": 0 // IP-NEXT: } // IP-NEXT: "obsoleted": { -// IP-NEXT: "major": 20, +// IP-NEXT: "major": 30, // IP-NEXT: "minor": 0, // IP-NEXT: "patch": 0 // IP-NEXT: } @@ -77,7 +77,7 @@ @interface A // IP-NEXT: ] // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MR -@property int moreRestrictive __attribute__((availability(macos, introduced=10.0, deprecated=11.0, obsoleted=19.0))); +@property int moreRestrictive __attribute__((availability(macos, introduced=10.0, deprecated=11.0, obsoleted=29.0))); // MR-LABEL: "!testLabel": "c:objc(cs)A(py)moreRestrictive" // MR: "availability": [ // MR-NEXT: { @@ -93,7 +93,7 @@ @interface A // MR-NEXT: "patch": 0 // MR-NEXT: } // MR-NEXT: "obsoleted": { -// MR-NEXT: "major": 19, +// MR-NEXT: "major": 29, // MR-NEXT: "minor": 0, // MR-NEXT: "patch": 0 // MR-NEXT: } @@ -148,7 +148,7 @@ @interface C @interface D // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix DIP -@property int DIP __attribute__((availability(macos, introduced=10.0, deprecated=11.0, obsoleted=19.0))); +@property int DIP __attribute__((availability(macos, introduced=10.0, deprecated=11.0, obsoleted=29.0))); // DIP-LABEL: "!testLabel": "c:objc(cs)D(py)DIP" // DIP: "availability": [ // DIP-NEXT: { @@ -164,7 +164,7 @@ @interface D // DIP-NEXT: "patch": 0 // DIP-NEXT: } // DIP-NEXT: "obsoleted": { -// DIP-NEXT: "major": 19, +// DIP-NEXT: "major": 29, // DIP-NEXT: "minor": 0, // DIP-NEXT: "patch": 0 // DIP-NEXT: } diff --git a/clang/test/Sema/Inputs/XROS.sdk/SDKSettings.json b/clang/test/Sema/Inputs/XROS.sdk/SDKSettings.json new file mode 100644 index 0000000000000..a56a7d61431b9 --- /dev/null +++ b/clang/test/Sema/Inputs/XROS.sdk/SDKSettings.json @@ -0,0 +1,9 @@ +{ + "DefaultVariant": "xrOS", "DisplayName": "xrOS", + "Version": "26.0", + "CanonicalName": "xros26.0", + "MaximumDeploymentTarget": "26.0.99", + "VersionMap": { + "iOS_xrOS":{"15.0":"1.0", "16.0":"2.0", "19.0":"26.0", "26.0":"26.0"} + } +} diff --git a/clang/test/Sema/attr-availability-invalid-os-versions.c b/clang/test/Sema/attr-availability-invalid-os-versions.c new file mode 100644 index 0000000000000..871263fc62cb0 --- /dev/null +++ b/clang/test/Sema/attr-availability-invalid-os-versions.c @@ -0,0 +1,35 @@ +/// This test verifies diagnostic reporting for OS versions within an invalid range. +// RUN: %clang_cc1 -triple x86_64-apple-darwin25 -fsyntax-only -verify %s + + __attribute__((availability(macosx,introduced=16, deprecated=20))) +void invalid_dep(void); // expected-warning@-1 {{invalid macOS version '20' in availability attribute}} + // expected-note@-2 {{implicitly treating version as '30'}} + +__attribute__((availability(macosx,introduced=15, obsoleted=19))) +void invalid_obsolete(void); // expected-warning@-1 {{invalid macOS version '19' in availability attribute}} + // expected-note@-2 {{implicitly treating version as '29'}} + +__attribute__((availability(macosx,introduced=24))) +void invalid_intro(void); // expected-warning@-1 {{invalid macOS version '24' in availability attribute}} + // expected-note@-2 {{implicitly treating version as '34'}} + +__attribute__((availability(watchos,introduced=24))) +void invalid_watch_intro(void); // expected-warning@-1 {{invalid watchOS version '24' in availability attribute}} + // expected-note@-2 {{implicitly treating version as '38'}} + +__attribute__((availability(maccatalyst, introduced=18.1, deprecated=21.1))) +void invalid_catalyst_intro(void); // expected-warning@-1 {{invalid macCatalyst version '21.1' in availability attribute}} + // expected-note@-2 {{implicitly treating version as '28.1'}} + +__attribute__((availability(macos, introduced=15, deprecated=26))) +__attribute__((availability(watchos, introduced=15))) +__attribute__((availability(ios, introduced=15, deprecated=18))) +void invalid_intro_multiple(void); // expected-warning@-2 {{invalid watchOS version '15' in availability attribute}} + // expected-note@-3 {{implicitly treating version as '29'}} + +__attribute__((availability(macCatalyst, introduced=19.2, deprecated=22.2))) +void invalid_dep(void); // expected-warning@-1 {{invalid macCatalyst version '19.2' in availability attribute}} + // expected-note@-2 {{implicitly treating version as '26.2'}} + // expected-warning@-3 {{invalid macCatalyst version '22.2' in availability attribute}} + // expected-note@-4 {{implicitly treating version as '29.2'}} + diff --git a/clang/test/Sema/attr-availability-ios-aligned-versions.c b/clang/test/Sema/attr-availability-ios-aligned-versions.c new file mode 100644 index 0000000000000..703ef42d881d3 --- /dev/null +++ b/clang/test/Sema/attr-availability-ios-aligned-versions.c @@ -0,0 +1,116 @@ +/// This test verifies several diff erent patterns of iOS, and app extension, availability declarations & usages. +// RUN: %clang_cc1 "-triple" "arm64-apple-ios26" -DNEW -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "arm64-apple-ios18" -fsyntax-only -verify -fapplication-extension -DAPP_EXT %s +// RUN: %clang_cc1 "-triple" "arm64-apple-ios18" -fsyntax-only -verify %s + +__attribute__((availability(ios,strict,introduced=19))) +void fNew1(); +#ifndef NEW +// expected-note@-2 {{here}} +#endif + +__attribute__((availability(ios,strict,introduced=19))) +void fNew(); + +__attribute__((availability(ios,strict,introduced=26))) +void fNew() { } +#ifndef NEW +// expected-note@-2 {{here}} +#endif + +__attribute__((availability(ios,strict,deprecated=19))) +void fDep(); + +__attribute__((availability(ios,strict,deprecated=26))) +void fDep() { } +#ifdef NEW +// expected-note@-2 {{here}} +#endif + +__attribute__((availability(ios,strict,obsoleted=19))) +void fObs(); + +__attribute__((availability(ios,strict,obsoleted=26))) +void fObs() { } +#ifdef NEW +// expected-note@-2 {{here}} +#endif + +__attribute__((availability(ios_app_extension,strict,introduced=19))) +void fAppExt(); + +__attribute__((availability(ios_app_extension,strict,introduced=26))) +void fAppExt() { } +#ifdef APP_EXT +// expected-note@-2 {{here}} +#endif + +void testVersionRemapping() { + fNew1(); +#ifndef NEW + // expected-error@-2 {{'fNew1' is unavailable: introduced in iOS 26.0}} +#endif + fNew(); +#ifndef NEW + // expected-error@-2 {{'fNew' is unavailable: introduced in iOS 26}} +#endif + fDep(); +#ifdef NEW + // expected-warning@-2 {{'fDep' is deprecated: first deprecated in iOS 26}} +#endif + fObs(); +#ifdef NEW + // expected-error@-2 {{'fObs' is unavailable: obsoleted in iOS 26}} +#endif + + fAppExt(); +#ifdef APP_EXT + // expected-error@-2 {{'fAppExt' is unavailable: introduced in iOS (App Extension) 26}} +#endif +} + +__attribute__((availability(ios,strict,introduced=18.5))) // expected-note {{here}} +void fMatchErr(); + +__attribute__((availability(ios,strict,introduced=26))) // expected-warning {{availability does not match previous declaration}} +void fMatchErr() { } + +__attribute__((availability(ios_app_extension,strict,introduced=19))) // expected-note {{here}} +void fAppExtErr(); + +__attribute__((availability(ios_app_extension,strict,introduced=26.1))) // expected-warning {{availability does not match previous declaration}} +void fAppExtErr() { } + +__attribute__((availability(ios,introduced=26))) +void fNew2(); +#ifndef NEW + // expected-note@-2 {{'fNew2' has been marked as being introduced in iOS 26 here, but the deployment target is iOS 18}} +#endif +__attribute__((availability(ios,introduced=19))) +void fNew3(); + +__attribute__((availability(ios,introduced=27))) +void evenNewer(); +#ifdef NEW + // expected-note@-2 {{'evenNewer' has been marked as being introduced in iOS 27 here, but the deployment target is iOS 26}} +#endif + +void testAvailabilityCheck() { + if (__builtin_available(iOS 19, *)) { + fNew2(); + fNew3(); + } + if (__builtin_available(iOS 26, *)) { + fNew2(); + fNew3(); + } + fNew2(); +#ifndef NEW + // expected-warning@-2 {{'fNew2' is only available on iOS 26 or newer}} expected-note@-2 {{enclose}} +#endif +#ifdef NEW + evenNewer(); // expected-warning {{'evenNewer' is only available on iOS 27 or newer}} expected-note {{enclose}} +#endif +} + + diff --git a/clang/test/Sema/attr-availability-ios-fallback-aligned-versions.c b/clang/test/Sema/attr-availability-ios-fallback-aligned-versions.c new file mode 100644 index 0000000000000..8947bc7dda469 --- /dev/null +++ b/clang/test/Sema/attr-availability-ios-fallback-aligned-versions.c @@ -0,0 +1,32 @@ +// This validates that all expected OSVersions that allow fallbacks +// from iOS behave as expected against a common version bump. + +// RUN: %clang_cc1 "-triple" "arm64-apple-ios26" -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "arm64-apple-watchos26" -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "arm64-apple-tvos26" -fsyntax-only -verify %s + +// VisionOS requires SDKSettings support to enable remappings. +// RUN: %clang_cc1 "-triple" "arm64-apple-visionos26" -isysroot %S/Inputs/XROS.sdk -fsyntax-only -verify %s + +// expected-no-diagnostics + +__attribute__((availability(ios,strict,introduced=19))) +int iOSExistingAPI(void); + +__attribute__((availability(ios,strict,introduced=26))) +int iOSExistingAPI2(void); + +void testAvailabilityCheck(void) { + + if (__builtin_available(iOS 19, *)) { + iOSExistingAPI(); + iOSExistingAPI2(); + } + + if (__builtin_available(iOS 26, *)) { + iOSExistingAPI(); + iOSExistingAPI2(); + } + + iOSExistingAPI2(); +} diff --git a/clang/test/Sema/attr-availability-iosmac-infer-from-macos.c b/clang/test/Sema/attr-availability-iosmac-infer-from-macos.c index 12c6d59b61ac2..73ff8c33ebe54 100644 --- a/clang/test/Sema/attr-availability-iosmac-infer-from-macos.c +++ b/clang/test/Sema/attr-availability-iosmac-infer-from-macos.c @@ -24,7 +24,7 @@ void fObs(void) __attribute__((availability(macOS, introduced = 10.11, obsoleted void fAPItoDepr(void) __attribute__((availability(macOS, introduced = 10.11, deprecated = 100000))); -void dontRemapFutureVers(void) __attribute__((availability(macOS, introduced = 20))); +void dontRemapFutureVers(void) __attribute__((availability(macOS, introduced = 30))); void usage(void) { f0(); diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 351da0d6598c2..b56e6e18805e0 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -1300,7 +1300,11 @@ class Triple { /// Returns a canonicalized OS version number for the specified OS. static VersionTuple getCanonicalVersionForOS(OSType OSKind, - const VersionTuple &Version); + const VersionTuple &Version, + bool IsInValidRange); + + /// Returns whether an OS version is invalid and would not map to an Apple OS. + static bool isValidVersionForOS(OSType OSKind, const VersionTuple &Version); }; } // End llvm namespace diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 6a559ff023caa..bd291e1918219 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -1446,9 +1446,12 @@ bool Triple::getMacOSXVersion(VersionTuple &Version) const { } if (Version.getMajor() <= 19) { Version = VersionTuple(10, Version.getMajor() - 4); - } else { - // darwin20+ corresponds to macOS 11+. + } else if (Version.getMajor() < 25) { + // darwin20-24 corresponds to macOS 11-15. Version = VersionTuple(11 + Version.getMajor() - 20); + } else { + // darwin25 corresponds with macOS26+. + Version = VersionTuple(Version.getMajor() + 1); } break; case MacOSX: @@ -1492,14 +1495,33 @@ VersionTuple Triple::getiOSVersion() const { // Default to 5.0 (or 7.0 for arm64). if (Version.getMajor() == 0) return (getArch() == aarch64) ? VersionTuple(7) : VersionTuple(5); - return Version; + if (Version.getMajor() == 19) + // tvOS 19 corresponds to ios26. + return VersionTuple(26); + return getCanonicalVersionForOS(OSType::IOS, Version, + isValidVersionForOS(OSType::IOS, Version)); } case XROS: { + VersionTuple Version = getOSVersion(); // xrOS 1 is aligned with iOS 17. + if (Version.getMajor() < 3) + return Version.withMajorReplaced(Version.getMajor() + 16); + // visionOS 3 corresponds to ios 26+. + if (Version.getMajor() == 3) + return VersionTuple(26); + return getCanonicalVersionForOS(OSType::XROS, Version, + isValidVersionForOS(OSType::XROS, Version)); + } + case WatchOS: { VersionTuple Version = getOSVersion(); - return Version.withMajorReplaced(Version.getMajor() + 16); + // watchOS 12 corresponds to ios 26. + if (Version.getMajor() == 12) + return VersionTuple(26); + return getCanonicalVersionForOS( + OSType::WatchOS, Version, + isValidVersionForOS(OSType::WatchOS, Version)); } - case WatchOS: + case BridgeOS: llvm_unreachable("conflicting triple info"); case DriverKit: llvm_unreachable("DriverKit doesn't have an iOS version"); @@ -2116,12 +2138,12 @@ bool Triple::isMacOSXVersionLT(unsigned Major, unsigned Minor, return isOSVersionLT(Major, Minor, Micro); // Otherwise, compare to the "Darwin" number. - if (Major == 10) { + if (Major == 10) return isOSVersionLT(Minor + 4, Micro, 0); - } else { - assert(Major >= 11 && "Unexpected major version"); + assert(Major >= 11 && "Unexpected major version"); + if (Major < 25) return isOSVersionLT(Major - 11 + 20, Minor, Micro); - } + return isOSVersionLT(Major + 1, Minor, Micro); } VersionTuple Triple::getMinimumSupportedOSVersion() const { @@ -2149,7 +2171,10 @@ VersionTuple Triple::getMinimumSupportedOSVersion() const { // ARM64 simulators are supported for watchOS 7+. if (isSimulatorEnvironment()) return VersionTuple(7, 0, 0); - break; + // ARM64/ARM64e slices are supported starting from watchOS 26. + // ARM64_32 is older though. + assert(getArch() != Triple::aarch64_32); + return VersionTuple(26, 0, 0); case Triple::DriverKit: return VersionTuple(20, 0, 0); default: @@ -2159,16 +2184,85 @@ VersionTuple Triple::getMinimumSupportedOSVersion() const { } VersionTuple Triple::getCanonicalVersionForOS(OSType OSKind, - const VersionTuple &Version) { + const VersionTuple &Version, + bool IsInValidRange) { + const unsigned MacOSRangeBump = 10; + const unsigned IOSRangeBump = 7; + const unsigned XROSRangeBump = 23; + const unsigned WatchOSRangeBump = 14; switch (OSKind) { - case MacOSX: + case MacOSX: { // macOS 10.16 is canonicalized to macOS 11. if (Version == VersionTuple(10, 16)) return VersionTuple(11, 0); - [[fallthrough]]; + // macOS 16 is canonicalized to macOS 26. + if (Version == VersionTuple(16, 0)) + return VersionTuple(26, 0); + if (!IsInValidRange) + return Version.withMajorReplaced(Version.getMajor() + MacOSRangeBump); + break; + } + case IOS: + case TvOS: { + // Both iOS & tvOS 19.0 canonicalize to 26. + if (Version == VersionTuple(19, 0)) + return VersionTuple(26, 0); + if (!IsInValidRange) + return Version.withMajorReplaced(Version.getMajor() + IOSRangeBump); + break; + } + case XROS: { + // visionOS3 is canonicalized to 26. + if (Version == VersionTuple(3, 0)) + return VersionTuple(26, 0); + if (!IsInValidRange) + return Version.withMajorReplaced(Version.getMajor() + XROSRangeBump); + break; + } + case WatchOS: { + // watchOS 12 is canonicalized to 26. + if (Version == VersionTuple(12, 0)) + return VersionTuple(26, 0); + if (!IsInValidRange) + return Version.withMajorReplaced(Version.getMajor() + WatchOSRangeBump); + break; + } default: return Version; } + + return Version; +} + +bool Triple::isValidVersionForOS(OSType OSKind, const VersionTuple &Version) { + /// This constant is used to capture gaps in versioning. + const VersionTuple CommonVersion(26); + auto IsValid = [&](const VersionTuple &StartingVersion) { + return !((Version > StartingVersion) && (Version < CommonVersion)); + }; + switch (OSKind) { + case WatchOS: { + const VersionTuple StartingWatchOS(12); + return IsValid(StartingWatchOS); + } + case IOS: + case TvOS: { + const VersionTuple StartingIOS(19); + return IsValid(StartingIOS); + } + case MacOSX: { + const VersionTuple StartingMacOS(16); + return IsValid(StartingMacOS); + } + case XROS: { + const VersionTuple StartingXROS(3); + return IsValid(StartingXROS); + } + default: + return true; + } + + llvm_unreachable("unexpected or invalid os version"); } // HLSL triple environment orders are relied on in the front end diff --git a/llvm/lib/TextAPI/Platform.cpp b/llvm/lib/TextAPI/Platform.cpp index d7d391102ce69..d5c4e0a974d0b 100644 --- a/llvm/lib/TextAPI/Platform.cpp +++ b/llvm/lib/TextAPI/Platform.cpp @@ -124,7 +124,9 @@ VersionTuple mapToSupportedOSVersion(const Triple &Triple) { const VersionTuple MinSupportedOS = Triple.getMinimumSupportedOSVersion(); if (MinSupportedOS > Triple.getOSVersion()) return MinSupportedOS; - return Triple.getOSVersion(); + return Triple::getCanonicalVersionForOS( + Triple.getOS(), Triple.getOSVersion(), + Triple::isValidVersionForOS(Triple.getOS(), Triple.getOSVersion())); } } // end namespace MachO. diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp index bbd12e6d0e412..0f6d07657c931 100644 --- a/llvm/unittests/TargetParser/TripleTest.cpp +++ b/llvm/unittests/TargetParser/TripleTest.cpp @@ -2354,6 +2354,79 @@ TEST(TripleTest, getOSVersion) { T.getMacOSXVersion(Version); EXPECT_EQ(VersionTuple(10, 16), Version); + // 16 forms a valid triple, even though it's not + // a version of a macOS. + T = Triple("x86_64-apple-macos16.0"); + EXPECT_TRUE(T.isMacOSX()); + T.getMacOSXVersion(Version); + EXPECT_EQ(VersionTuple(16, 0), Version); + + T = Triple("arm64-apple-macosx26.1"); + EXPECT_TRUE(T.isMacOSX()); + EXPECT_FALSE(T.isiOS()); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + T.getMacOSXVersion(Version); + EXPECT_EQ(VersionTuple(26, 1), Version); + + // 19.0 forms a valid triple, even though it's not + // a version of a iOS. + T = Triple("arm64-apple-ios19.0"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isiOS()); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + T.getiOSVersion(); + EXPECT_EQ(VersionTuple(19, 0), T.getOSVersion()); + + T = Triple("arm64-apple-ios27.0"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isiOS()); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_EQ(VersionTuple(27, 0), T.getiOSVersion()); + + T = Triple("arm64-apple-watchos12.0"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isWatchOS()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_EQ(VersionTuple(26, 0), T.getiOSVersion()); + + T = Triple("arm64-apple-visionos3.0"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isXROS()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_EQ(VersionTuple(26, 0), T.getiOSVersion()); + + T = Triple("x86_64-apple-darwin26"); + EXPECT_TRUE(T.isMacOSX()); + T.getMacOSXVersion(Version); + EXPECT_EQ(VersionTuple(27), Version); + + // Check invalid ranges are remapped. + T = Triple("arm64-apple-visionos6.0"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isXROS()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_EQ(VersionTuple(29, 0), T.getiOSVersion()); + + T = Triple("arm64-apple-watchos14.0"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isWatchOS()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_EQ(VersionTuple(28, 0), T.getiOSVersion()); + + T = Triple("arm64-apple-ios21.1"); + EXPECT_FALSE(T.isMacOSX()); + EXPECT_TRUE(T.isiOS()); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_EQ(VersionTuple(28, 1), T.getiOSVersion()); + T = Triple("x86_64-apple-darwin20"); EXPECT_TRUE(T.isMacOSX()); T.getMacOSXVersion(Version); @@ -2468,11 +2541,76 @@ TEST(TripleTest, isMacOSVersionLT) { TEST(TripleTest, CanonicalizeOSVersion) { EXPECT_EQ(VersionTuple(10, 15, 4), Triple::getCanonicalVersionForOS(Triple::MacOSX, - VersionTuple(10, 15, 4))); - EXPECT_EQ(VersionTuple(11, 0), Triple::getCanonicalVersionForOS( - Triple::MacOSX, VersionTuple(10, 16))); + VersionTuple(10, 15, 4), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(11, 0), + Triple::getCanonicalVersionForOS( + Triple::MacOSX, VersionTuple(10, 16), /*IsInValidRange=*/true)); EXPECT_EQ(VersionTuple(20), - Triple::getCanonicalVersionForOS(Triple::Darwin, VersionTuple(20))); + Triple::getCanonicalVersionForOS(Triple::Darwin, VersionTuple(20), + /*IsInValidRange=*/true)); + + // Validate mappings for all expected OS versions remapping to 26. + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::MacOSX, VersionTuple(16), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::IOS, VersionTuple(19), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::TvOS, VersionTuple(19), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::WatchOS, VersionTuple(12), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::XROS, VersionTuple(3), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::Darwin, VersionTuple(26), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::BridgeOS, VersionTuple(26), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(26), + Triple::getCanonicalVersionForOS(Triple::BridgeOS, VersionTuple(26), + /*IsInValidRange=*/true)); + EXPECT_EQ(VersionTuple(10), + Triple::getCanonicalVersionForOS(Triple::BridgeOS, VersionTuple(10), + /*IsInValidRange=*/true)); + + // Verify invalid ranges can be remapped. + EXPECT_EQ(VersionTuple(28), + Triple::getCanonicalVersionForOS(Triple::MacOSX, VersionTuple(18), + /*IsInValidRange=*/false)); + EXPECT_EQ(VersionTuple(28), + Triple::getCanonicalVersionForOS(Triple::IOS, VersionTuple(21), + /*IsInValidRange=*/false)); + EXPECT_EQ(VersionTuple(28), + Triple::getCanonicalVersionForOS(Triple::WatchOS, VersionTuple(14), + /*IsInValidRange=*/false)); + EXPECT_EQ(VersionTuple(28), + Triple::getCanonicalVersionForOS(Triple::TvOS, VersionTuple(21), + /*IsInValidRange=*/false)); +} + +TEST(TripleTest, CheckValidOSVersion) { + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::MacOSX, VersionTuple(16))); + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::IOS, VersionTuple(19))); + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::TvOS, VersionTuple(19))); + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::TvOS, VersionTuple(18, 2))); + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::WatchOS, VersionTuple(12))); + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::XROS, VersionTuple(3))); + EXPECT_TRUE(Triple::isValidVersionForOS(Triple::Darwin, VersionTuple(26))); + EXPECT_TRUE( + Triple::isValidVersionForOS(Triple::BridgeOS, VersionTuple(26, 1, 1))); + + EXPECT_FALSE( + Triple::isValidVersionForOS(Triple::MacOSX, VersionTuple(16, 1))); + EXPECT_FALSE(Triple::isValidVersionForOS(Triple::MacOSX, VersionTuple(18))); + EXPECT_FALSE(Triple::isValidVersionForOS(Triple::IOS, VersionTuple(21))); + EXPECT_FALSE(Triple::isValidVersionForOS(Triple::WatchOS, VersionTuple(14))); + EXPECT_FALSE(Triple::isValidVersionForOS(Triple::TvOS, VersionTuple(21))); } TEST(TripleTest, FileFormat) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits