Infer visionOS availability from iOS availability#176990
Merged
Merged
Conversation
Automatically infer and apply availability or unavailable attributes for visionOS based on the corresponding iOS availability of the same declaration using the version mapping information provided in SDKSettings.json. rdar://162148639
Member
|
@llvm/pr-subscribers-clang Author: Akira Hatanaka (ahatanak) ChangesAutomatically infer and apply availability or unavailable attributes for visionOS based on the corresponding iOS availability of the same declaration using the version mapping information provided in SDKSettings.json. rdar://162148639 Full diff: https://github.com/llvm/llvm-project/pull/176990.diff 4 Files Affected:
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d762bcd789bf5..dc954c3925596 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2518,6 +2518,80 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(
return nullptr;
}
+/// Returns true if the given availability attribute should be inferred, and
+/// adjusts the value of the attribute as necessary to facilitate that.
+static bool shouldInferAvailabilityAttribute(const ParsedAttr &AL,
+ IdentifierInfo *&II,
+ bool &IsUnavailable,
+ VersionTuple &Introduced,
+ VersionTuple &Deprecated,
+ VersionTuple &Obsolete, Sema &S) {
+ const llvm::Triple &TT = S.Context.getTargetInfo().getTriple();
+ const ASTContext &Context = S.Context;
+ if (TT.getOS() != llvm::Triple::XROS)
+ return false;
+ IdentifierInfo *NewII = nullptr;
+ if (II->getName() == "ios")
+ NewII = &Context.Idents.get("xros");
+ else if (II->getName() == "ios_app_extension")
+ NewII = &Context.Idents.get("xros_app_extension");
+ if (!NewII)
+ return false;
+ II = NewII;
+
+ auto MakeUnavailable = [&]() {
+ IsUnavailable = true;
+ // Reset introduced, deprecated, obsoleted.
+ Introduced = VersionTuple();
+ Deprecated = VersionTuple();
+ Obsolete = VersionTuple();
+ };
+
+ const DarwinSDKInfo *SDKInfo = S.getDarwinSDKInfoForAvailabilityChecking(
+ AL.getRange().getBegin(), "ios");
+
+ if (!SDKInfo) {
+ MakeUnavailable();
+ return true;
+ }
+ // Map from the fallback platform availability to the current platform
+ // availability.
+ const auto *Mapping = SDKInfo->getVersionMapping(DarwinSDKInfo::OSEnvPair(
+ llvm::Triple::IOS, llvm::Triple::UnknownEnvironment, llvm::Triple::XROS,
+ llvm::Triple::UnknownEnvironment));
+ if (!Mapping) {
+ MakeUnavailable();
+ return true;
+ }
+
+ if (!Introduced.empty()) {
+ auto NewIntroduced = Mapping->mapIntroducedAvailabilityVersion(Introduced);
+ if (!NewIntroduced) {
+ MakeUnavailable();
+ return true;
+ }
+ Introduced = *NewIntroduced;
+ }
+
+ if (!Obsolete.empty()) {
+ auto NewObsolete =
+ Mapping->mapDeprecatedObsoletedAvailabilityVersion(Obsolete);
+ if (!NewObsolete) {
+ MakeUnavailable();
+ return true;
+ }
+ Obsolete = *NewObsolete;
+ }
+
+ if (!Deprecated.empty()) {
+ auto NewDeprecated =
+ Mapping->mapDeprecatedObsoletedAvailabilityVersion(Deprecated);
+ Deprecated = NewDeprecated ? *NewDeprecated : VersionTuple();
+ }
+
+ return true;
+}
+
static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (isa<UsingDecl, UnresolvedUsingTypenameDecl, UnresolvedUsingValueDecl>(
D)) {
@@ -2630,6 +2704,25 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (NewAttr)
D->addAttr(NewAttr);
+ if (S.Context.getTargetInfo().getTriple().getOS() == llvm::Triple::XROS) {
+ IdentifierInfo *NewII = II;
+ bool NewIsUnavailable = IsUnavailable;
+ VersionTuple NewIntroduced = Introduced.Version;
+ VersionTuple NewDeprecated = Deprecated.Version;
+ VersionTuple NewObsoleted = Obsoleted.Version;
+ if (shouldInferAvailabilityAttribute(AL, NewII, NewIsUnavailable,
+ NewIntroduced, NewDeprecated,
+ NewObsoleted, S)) {
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
+ ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
+ NewObsoleted, NewIsUnavailable, Str, IsStrict, Replacement,
+ AvailabilityMergeKind::None,
+ PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ }
+ }
+
// Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
// matches before the start of the watchOS platform.
if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
diff --git a/clang/test/PlatformSpecific/xrOS/Sema/Inputs/XROS.sdk/SDKSettings.json b/clang/test/PlatformSpecific/xrOS/Sema/Inputs/XROS.sdk/SDKSettings.json
new file mode 100644
index 0000000000000..e4f7c87519805
--- /dev/null
+++ b/clang/test/PlatformSpecific/xrOS/Sema/Inputs/XROS.sdk/SDKSettings.json
@@ -0,0 +1,21 @@
+{
+ "DefaultVariant": "xrOS", "DisplayName": "xrOS",
+ "Version": "1.0",
+ "CanonicalName": "xros1.0",
+ "MaximumDeploymentTarget": "1.0.99",
+ "SupportedTargets": {
+ "xros": {
+ "Archs": ["arm64e", "arm64"],
+ "LLVMTargetTripleVendor": "apple",
+ "LLVMTargetTripleSys": "xros",
+ "LLVMTargetTripleEnvironment": "",
+ "SystemPrefix": ""
+ }
+ },
+ "VersionMap": {
+ "iOS_visionOS": {"17.1": "1.0"},
+ "iOS_xrOS": {"17.1": "1.0"},
+ "visionOS_iOS": {"1.0": "17.1"},
+ "xrOS_iOS": {"1.0": "17.1"}
+ }
+}
diff --git a/clang/test/PlatformSpecific/xrOS/Sema/infer-ios-availability.c b/clang/test/PlatformSpecific/xrOS/Sema/infer-ios-availability.c
new file mode 100644
index 0000000000000..76be32370e745
--- /dev/null
+++ b/clang/test/PlatformSpecific/xrOS/Sema/infer-ios-availability.c
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -triple arm64-apple-xros1 -verify=ios -isysroot %S/Inputs/XROS.sdk %s 2>&1
+// RUN: %clang_cc1 -triple arm64-apple-xros1 -fapplication-extension -verify=ios,ext -isysroot %S/Inputs/XROS.sdk %s 2>&1
+
+// RUN: %clang_cc1 -triple arm64-apple-xros2 -DXROS2 -verify=ios -isysroot %S/Inputs/XROS.sdk %s 2>&1
+
+__attribute__((availability(ios, unavailable)))
+void ios_unavail(); // ios-note {{}}
+
+__attribute__((availability(ios_app_extension, unavailable)))
+void ios_ext_unavail(); // ext-note {{}}
+
+void use() {
+ ios_unavail(); // ios-error {{'ios_unavail' is unavailable: not available on }}
+ ios_ext_unavail(); // ext-error {{'ios_ext_unavail' is unavailable: not available on }}
+}
+
+__attribute__((availability(ios, introduced=10)))
+void ios_introduced_10();
+
+__attribute__((availability(ios_app_extension, introduced=10)))
+void ios_ext_introduced_10();
+
+__attribute__((availability(ios, introduced=17.1)))
+void ios_introduced_17();
+
+__attribute__((availability(ios_app_extension, introduced=17.1)))
+void ios_ext_introduced_17();
+
+__attribute__((availability(ios, introduced=18)))
+void ios_introduced_18(); // ios-note {{}}
+
+__attribute__((availability(ios_app_extension, introduced=18)))
+void ios_ext_introduced_18(); // ext-note {{}}
+
+void useIntroduced() {
+ // introduced iOS < 10 => introduced xrOS 1
+ ios_introduced_10();
+ ios_ext_introduced_10();
+ // introduced iOS 17.1 => introduced xrOS 1
+ ios_introduced_17();
+ ios_ext_introduced_17();
+ // introduced iOS 18 => xros unavailable (no mapping)
+ ios_introduced_18(); // ios-error {{is unavailable: not available on }}
+ ios_ext_introduced_18(); // ext-error {{is unavailable: not available on }}
+}
+
+__attribute__((availability(ios, deprecated=10)))
+void ios_deprecated_10(); // ios-note {{}}
+
+__attribute__((availability(ios_app_extension, deprecated=10)))
+void ios_ext_deprecated_10(); // ext-note {{}}
+
+__attribute__((availability(ios, deprecated=17.1)))
+void ios_deprecated_17(); // ios-note {{}}
+
+__attribute__((availability(ios_app_extension, deprecated=17.1)))
+void ios_ext_deprecated_17(); // ext-note {{}}
+
+__attribute__((availability(ios, deprecated=18)))
+void ios_deprecated_18();
+#ifdef XROS2
+// ios-note@-2 {{}}
+#endif
+
+__attribute__((availability(ios_app_extension, deprecated=18)))
+void ios_ext_deprecated_18();
+
+void useDeprecated() {
+ // deprecated iOS < 10 => deprecated xrOS 1
+ ios_deprecated_10(); // ios-warning {{is deprecated: first deprecated in}}
+ ios_ext_deprecated_10(); // ext-warning {{is deprecated: first deprecated in}}
+ // deprecated iOS 17.1 => deprecated xrOS 1
+ ios_deprecated_17(); // ios-warning {{is deprecated: first deprecated in}}
+ ios_ext_deprecated_17(); // ext-warning {{is deprecated: first deprecated in}}
+ // deprecated iOS 18 => deprecated xrOS 1.0.99
+ ios_deprecated_18();
+#ifdef XROS2
+ // ios-warning@-2 {{is deprecated: first deprecated in}}
+#endif
+ ios_ext_deprecated_18();
+}
+
+__attribute__((availability(ios, obsoleted=10)))
+void ios_obsoleted_10(); // ios-note {{}}
+
+__attribute__((availability(ios_app_extension, obsoleted=10)))
+void ios_ext_obsoleted_10(); // ext-note {{}}
+
+__attribute__((availability(ios, obsoleted=17.1)))
+void ios_obsoleted_17(); // ios-note {{}}
+
+__attribute__((availability(ios_app_extension, obsoleted=17.1)))
+void ios_ext_obsoleted_17(); // ext-note {{}}
+
+__attribute__((availability(ios, obsoleted=18)))
+void ios_obsoleted_18();
+#ifdef XROS2
+// ios-note@-2 {{}}
+#endif
+
+__attribute__((availability(ios_app_extension, obsoleted=18)))
+void ios_ext_obsoleted_18();
+
+void useObsoleted() {
+ // deprecated iOS < 10 => deprecated xrOS 1
+ ios_obsoleted_10(); // ios-error {{is unavailable: obsoleted in}}
+ ios_ext_obsoleted_10(); // ext-error {{is unavailable: obsoleted in}}
+ // deprecated iOS 17.1 => deprecated xrOS 1
+ ios_obsoleted_17(); // ios-error {{is unavailable: obsoleted in}}
+ ios_ext_obsoleted_17(); // ext-error {{is unavailable: obsoleted in}}
+ // obsoleted iOS 18 => obsoleted xrOS 1.0.99
+ ios_obsoleted_18();
+#ifdef XROS2
+ // ios-error@-2 {{is unavailable: obsoleted in}}
+#endif
+ ios_ext_obsoleted_18();
+}
diff --git a/clang/test/PlatformSpecific/xrOS/Sema/infer-unavailable-from-missing-ios-availability-mapping.c b/clang/test/PlatformSpecific/xrOS/Sema/infer-unavailable-from-missing-ios-availability-mapping.c
new file mode 100644
index 0000000000000..2645b487ffd72
--- /dev/null
+++ b/clang/test/PlatformSpecific/xrOS/Sema/infer-unavailable-from-missing-ios-availability-mapping.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple arm64-apple-xros1 -verify=ios -DNOSDK %s 2>&1
+// RUN: %clang_cc1 -triple arm64-apple-xros1 -verify=ios -isysroot %S/Inputs/XROS.sdk %s 2>&1
+
+#ifdef NOSDK
+// ios-warning@+2 {{ios availability is ignored without a valid 'SDKSettings.json' in the SDK}}
+#endif
+__attribute__((availability(ios, introduced=18))) // note the version introduced has to be higher than the versions in SDKSettings
+void ios_introduced_10(); // ios-note {{}}
+
+void useIntroduced() {
+ ios_introduced_10(); // ios-error {{is unavailable: not available on }}
+}
|
cachemeifyoucan
approved these changes
Jan 20, 2026
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/3/builds/27622 Here is the relevant piece of the build log for the reference |
ahatanaka
pushed a commit
to swiftlang/llvm-project
that referenced
this pull request
Jan 23, 2026
Automatically infer and apply availability or unavailable attributes for visionOS based on the corresponding iOS availability of the same declaration using the version mapping information provided in SDKSettings.json. rdar://162148639
ahatanaka
pushed a commit
to swiftlang/llvm-project
that referenced
this pull request
Jan 26, 2026
Automatically infer and apply availability or unavailable attributes for visionOS based on the corresponding iOS availability of the same declaration using the version mapping information provided in SDKSettings.json. rdar://162148639
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatically infer and apply availability or unavailable attributes for visionOS based on the corresponding iOS availability of the same declaration using the version mapping information provided in SDKSettings.json.
rdar://162148639