Skip to content
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
93 changes: 93 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2484,6 +2484,80 @@ static void handleFeatureAvailabilityAttr(Sema &S, Decl *D,
IsUnavailable, AL));
}

/// 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 (!AL.isAvailabilityAttribute()) {
handleFeatureAvailabilityAttr(S, D, AL);
Expand Down Expand Up @@ -2601,6 +2675,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()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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"}
}
}
117 changes: 117 additions & 0 deletions clang/test/PlatformSpecific/xrOS/Sema/infer-ios-availability.c
Original file line number Diff line number Diff line change
@@ -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();
}
Original file line number Diff line number Diff line change
@@ -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 }}
}