Skip to content

[clang] Upstream visionOS Availability & DarwinSDKInfo APIs #84279

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 2 commits into from
Mar 7, 2024
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
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,8 @@ def Availability : InheritableAttr {
.Case("watchos_app_extension", "watchOS (App Extension)")
.Case("maccatalyst", "macCatalyst")
.Case("maccatalyst_app_extension", "macCatalyst (App Extension)")
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOS (App Extension)")
.Case("swift", "Swift")
.Case("shadermodel", "HLSL ShaderModel")
.Case("ohos", "OpenHarmony OS")
Expand All @@ -1000,6 +1002,8 @@ static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) {
.Case("watchos_app_extension", "watchOSApplicationExtension")
.Case("maccatalyst", "macCatalyst")
.Case("maccatalyst_app_extension", "macCatalystApplicationExtension")
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOSApplicationExtension")
.Case("zos", "z/OS")
.Case("shadermodel", "ShaderModel")
.Default(Platform);
Expand All @@ -1016,6 +1020,10 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
.Case("watchOSApplicationExtension", "watchos_app_extension")
.Case("macCatalyst", "maccatalyst")
.Case("macCatalystApplicationExtension", "maccatalyst_app_extension")
.Case("visionOS", "xros")
.Case("visionOSApplicationExtension", "xros_app_extension")
.Case("visionos", "xros")
.Case("visionos_app_extension", "xros_app_extension")
.Case("ShaderModel", "shadermodel")
.Default(Platform);
} }];
Expand Down
24 changes: 24 additions & 0 deletions clang/include/clang/Basic/DarwinSDKInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,30 @@ class DarwinSDKInfo {
map(const VersionTuple &Key, const VersionTuple &MinimumValue,
std::optional<VersionTuple> MaximumValue) const;

/// Remap the 'introduced' availability version.
/// If None is returned, the 'unavailable' availability should be used
/// instead.
std::optional<VersionTuple>
mapIntroducedAvailabilityVersion(const VersionTuple &Key) const {
// API_TO_BE_DEPRECATED is 100000.
if (Key.getMajor() == 100000)
return VersionTuple(100000);
// Use None for maximum to force unavailable behavior for
return map(Key, MinimumValue, std::nullopt);
}

/// Remap the 'deprecated' and 'obsoleted' availability version.
/// If None is returned for 'obsoleted', the 'unavailable' availability
/// should be used instead. If None is returned for 'deprecated', the
/// 'deprecated' version should be dropped.
std::optional<VersionTuple>
mapDeprecatedObsoletedAvailabilityVersion(const VersionTuple &Key) const {
// API_TO_BE_DEPRECATED is 100000.
if (Key.getMajor() == 100000)
return VersionTuple(100000);
return map(Key, MinimumValue, MaximumValue);
}

static std::optional<RelatedTargetVersionMapping>
parseJSON(const llvm::json::Object &Obj,
VersionTuple MaximumDeploymentTarget);
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1234,8 +1234,11 @@ void Parser::ParseAvailabilityAttribute(
}
IdentifierLoc *Platform = ParseIdentifierLoc();
if (const IdentifierInfo *const Ident = Platform->Ident) {
// Disallow xrOS for availability attributes.
if (Ident->getName().contains("xrOS") || Ident->getName().contains("xros"))
Diag(Platform->Loc, diag::warn_availability_unknown_platform) << Ident;
// Canonicalize platform name from "macosx" to "macos".
if (Ident->getName() == "macosx")
else if (Ident->getName() == "macosx")
Platform->Ident = PP.getIdentifierInfo("macos");
// Canonicalize platform name from "macosx_app_extension" to
// "macos_app_extension".
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3863,7 +3863,8 @@ std::optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() {
StringRef Platform =
AvailabilityAttr::canonicalizePlatformName(GivenPlatform);

if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) {
if (AvailabilityAttr::getPrettyPlatformName(Platform).empty() ||
(GivenPlatform.contains("xros") || GivenPlatform.contains("xrOS"))) {
Diag(PlatformIdentifier->Loc,
diag::err_avail_query_unrecognized_platform_name)
<< GivenPlatform;
Expand Down
10 changes: 10 additions & 0 deletions clang/test/CodeGen/attr-availability-visionos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -triple arm64-apple-xros1 -emit-llvm -o - %s 2>&1 | FileCheck %s

__attribute__((availability(visionOS, introduced=1.1)))
void introduced_1_1();

void use() {
if (__builtin_available(visionOS 1.2, *))
introduced_1_1();
// CHECK: call i32 @__isPlatformVersionAtLeast(i32 11, i32 1, i32 2, i32 0)
}
39 changes: 39 additions & 0 deletions clang/test/Sema/attr-availability-visionos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %clang_cc1 -triple arm64-apple-xros1 -fapplication-extension -verify=visionos %s 2>&1

__attribute__((availability(xros, unavailable))) // visionos-warning {{unknown platform 'xros' in availability macro}}
void xros_unavail(); // visionos-note {{}}

__attribute__((availability(xros_app_extension, unavailable))) // visionos-warning {{unknown platform 'xros_app_extension' in availability macro}}
void xros_ext_unavail(); // visionos-note {{}}

__attribute__((availability(visionOSApplicationExtension, unavailable)))
void visionos_ext_unavail(); // visionos-note {{}}

void use() {
xros_unavail(); // visionos-error {{'xros_unavail' is unavailable: not available on visionOS}}
xros_ext_unavail(); // visionos-error {{'xros_ext_unavail' is unavailable: not available on visionOS}}
visionos_ext_unavail(); // visionos-error {{'visionos_ext_unavail' is unavailable: not available on visionOS}}
}

__attribute__((availability(visionOS, introduced=1.0)))
void visionos_introduced_1();

__attribute__((availability(visionos, introduced=1.1)))
void visionos_introduced_1_1(); // visionos-note 4 {{'visionos_introduced_1_1' has been marked as being introduced in visionOS 1.1 here, but the deployment target is visionOS 1}}

void use2() {
if (__builtin_available(iOS 16.1, *))
visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}

if (__builtin_available(xrOS 1.1, *)) // visionos-error {{unrecognized platform name xrOS}}
visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}

if (__builtin_available(xros_app_extension 1, *)) // visionos-error {{unrecognized platform name xros_app_extension}}
visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}

if (__builtin_available(visionOS 1.1, *))
visionos_introduced_1_1();

visionos_introduced_1();
visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}
}
10 changes: 10 additions & 0 deletions clang/unittests/Basic/DarwinSDKInfoTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ TEST(DarwinSDKInfoTest, ParseAndTestMappingIOSDerived) {
EXPECT_EQ(
*Mapping->map(VersionTuple(13, 0), VersionTuple(), VersionTuple(99, 99)),
VersionTuple(99, 99));

// Verify introduced, deprecated, and obsoleted mappings.
EXPECT_EQ(Mapping->mapIntroducedAvailabilityVersion(VersionTuple(10, 1)),
VersionTuple(10.0));
EXPECT_EQ(Mapping->mapDeprecatedObsoletedAvailabilityVersion(
VersionTuple(100000, 0)),
VersionTuple(100000));
EXPECT_EQ(
Mapping->mapDeprecatedObsoletedAvailabilityVersion(VersionTuple(13.0)),
VersionTuple(15, 0, 99));
}

TEST(DarwinSDKInfoTest, MissingKeys) {
Expand Down