Skip to content

Commit f5f9333

Browse files
committed
Infer visionOS availability from iOS availability
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
1 parent d604b9b commit f5f9333

File tree

13 files changed

+408
-0
lines changed

13 files changed

+408
-0
lines changed

clang/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*")
370370
endif()
371371

372372
include(AddClang)
373+
include(AddDarwinPlatform)
374+
clang_add_additional_platform()
373375

374376
set(CMAKE_INCLUDE_CURRENT_DIR ON)
375377

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# FIXME: How to generalize this to be driven by discovered SDKs?
2+
function(clang_add_additional_platform)
3+
# Add a platform.
4+
set(name "xros")
5+
set(CLANG_PLATFORM_${name}_PLATFORM_AVAILABILITY_NAME "xros" PARENT_SCOPE)
6+
set(platformFallBack "iphoneos")
7+
8+
if (NOT "${platformFallBack}" STREQUAL "")
9+
set(fallbackTripleName "${platformFallBack}")
10+
# FIXME: we need a generic platform -> triple mapping.
11+
if ("${fallbackTripleName}" STREQUAL "iphoneos")
12+
set(fallbackTripleName "ios")
13+
endif()
14+
15+
message(STATUS "Platform ${name} has fallback platform - ${fallbackTripleName}")
16+
set(CLANG_PLATFORM_${name}_FALLBACK_PLATFORM_AVAILABILITY_NAME "${fallbackTripleName}" PARENT_SCOPE)
17+
18+
# FIXME: This is a hack for xrOS, but should be in the SDKSettings too.
19+
set(CLANG_PLATFORM_${name}_INFER_UNAVAILABLE 1 PARENT_SCOPE)
20+
set(CLANG_PLATFORM_${name}_PLATFORM_TRIPLE_OS_VALUE "XROS" PARENT_SCOPE)
21+
set(CLANG_PLATFORM_${name}_FALLBACK_PLATFORM_TRIPLE_OS_VALUE "IOS" PARENT_SCOPE)
22+
endif()
23+
endfunction()

clang/lib/Sema/CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,38 @@ clang_tablegen(OpenCLBuiltins.inc -gen-clang-opencl-builtins
1313
TARGET ClangOpenCLBuiltinsImpl
1414
)
1515

16+
# Configure additional platform-specific code that controls things like
17+
# availability attributes.
18+
set(TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE "")
19+
20+
foreach(supported_platform ${LLVM_SUPPORTED_PLATFORMS})
21+
if (${CLANG_PLATFORM_${supported_platform}_INFER_UNAVAILABLE})
22+
# Generate code that infers availability(unavailable) attribute if a platform
23+
# requires that.
24+
set(output_file_name "InferUnavailableAvailabilityFromFallbackPlatform_${supported_platform}.def")
25+
message(STATUS "Adding platform specific availability attribute code - ${output_file_name}")
26+
27+
set(PLATFORM_TRIPLE_OS_VALUE
28+
"${CLANG_PLATFORM_${supported_platform}_PLATFORM_TRIPLE_OS_VALUE}")
29+
set(FALLBACK_PLATFORM_TRIPLE_OS_VALUE
30+
"${CLANG_PLATFORM_${supported_platform}_FALLBACK_PLATFORM_TRIPLE_OS_VALUE}")
31+
set(PLATFORM_AVAILABILITY_NAME
32+
"${CLANG_PLATFORM_${supported_platform}_PLATFORM_AVAILABILITY_NAME}")
33+
set(FALLBACK_PLATFORM_AVAILABILITY_NAME
34+
"${CLANG_PLATFORM_${supported_platform}_FALLBACK_PLATFORM_AVAILABILITY_NAME}")
35+
configure_file(
36+
${CMAKE_CURRENT_SOURCE_DIR}/PlatformTemplates/InferUnavailableAvailabilityFromFallbackPlatform.def.in
37+
${CMAKE_CURRENT_BINARY_DIR}/PlatformTemplates/${output_file_name}
38+
)
39+
set(TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE "${TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE}\n#include \"PlatformTemplates/${output_file_name}\"")
40+
endif()
41+
endforeach()
42+
43+
configure_file(
44+
${CMAKE_CURRENT_SOURCE_DIR}/InferAvailabilityAttribute.cpp.in
45+
${CMAKE_CURRENT_BINARY_DIR}/InferAvailabilityAttribute.cpp
46+
)
47+
1648
add_clang_library(clangSema
1749
AnalysisBasedWarnings.cpp
1850
# TO_UPSTREAM(BoundsSafety) ON
@@ -108,6 +140,7 @@ add_clang_library(clangSema
108140
SemaWasm.cpp
109141
SemaX86.cpp
110142
TypeLocBuilder.cpp
143+
${CMAKE_CURRENT_BINARY_DIR}/InferAvailabilityAttribute.cpp
111144

112145
DEPENDS
113146
ClangOpenCLBuiltinsImpl
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "clang/AST/ASTContext.h"
10+
#include "clang/Basic/DarwinSDKInfo.h"
11+
#include "clang/Basic/IdentifierTable.h"
12+
#include "clang/Basic/LLVM.h"
13+
#include "llvm/Support/VersionTuple.h"
14+
#include "llvm/TargetParser/Triple.h"
15+
16+
namespace clang {
17+
18+
/// Returns true if the given availability attribute should be inferred, and
19+
/// adjusts the value of the attribute as necessary to facilitate that.
20+
bool shouldInferAvailabilityAttribute(const llvm::Triple &TT,
21+
const DarwinSDKInfo *SDKInfo,
22+
const ASTContext &Context,
23+
IdentifierInfo *&II,
24+
bool &IsUnavailable,
25+
VersionTuple &Introduced,
26+
VersionTuple &Deprecated,
27+
VersionTuple &Obsolete) {
28+
for (const auto &f : {
29+
// function ptr promotion
30+
+([] (const llvm::Triple &TT,
31+
const DarwinSDKInfo *SDKInfo,
32+
const ASTContext &Context,
33+
IdentifierInfo *&II,
34+
bool &IsUnavailable,
35+
VersionTuple &Introduced,
36+
VersionTuple &Deprecated,
37+
VersionTuple &Obsolete) -> bool { return false; }),
38+
@TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE@
39+
}) {
40+
if (f(TT, SDKInfo, Context, II, IsUnavailable, Introduced, Deprecated,
41+
Obsolete))
42+
return true;
43+
}
44+
return false;
45+
}
46+
47+
} // end namespace clang
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This platform-specific template implements inferral of
10+
// __attribute__((availability(platform, unavailable))) from a base platform
11+
// attribute __attribute__((availability(fallback platform, unavailable))).
12+
//
13+
// INPUTS:
14+
// PLATFORM_TRIPLE_OS_VALUE - the name of the target OS enum in the Triple.
15+
// FALLBACK_PLATFORM_TRIPLE_OS_VALUE - the name of the fallback target OS
16+
// enum in the Triple.
17+
// PLATFORM_AVAILABILITY_NAME - the name of availability platform.
18+
// FALLBACK_PLATFORM_AVAILABILITY_NAME - the name of availability for the
19+
// fallback platform.
20+
//
21+
//===----------------------------------------------------------------------===//
22+
23+
// FIXME: This is now doing more than 'unavailable', the docs have to be updated.
24+
25+
// x introduced := map(ios introduced, 1.0, None)
26+
// None -> x unavailable
27+
// <version> -> x introduced <version>
28+
29+
// x deprecated := map(ios deprecated, 1.0, MaximumDeploymentVersion)
30+
// None -> None
31+
// <version> -> x deprecated <version>
32+
33+
// x obsoleted := map(ios obsoleted, 1.0, MaximumDeploymentVersion)
34+
// None -> x unavailable
35+
// <version> -> x obsoleted <version>
36+
37+
/// Returns true if the given availability attribute should be inferred.
38+
+([] (const llvm::Triple &TT,
39+
const DarwinSDKInfo *SDKInfo,
40+
const ASTContext &Context,
41+
IdentifierInfo *&II,
42+
bool &IsUnavailable,
43+
VersionTuple &Introduced,
44+
VersionTuple &Deprecated,
45+
VersionTuple &Obsolete) -> bool {
46+
if (TT.getOS() != llvm::Triple::@PLATFORM_TRIPLE_OS_VALUE@)
47+
return false;
48+
IdentifierInfo *NewII = nullptr;
49+
if (II->getName() == "@FALLBACK_PLATFORM_AVAILABILITY_NAME@")
50+
NewII = &Context.Idents.get("@PLATFORM_AVAILABILITY_NAME@");
51+
else if (II->getName() == "@FALLBACK_PLATFORM_AVAILABILITY_NAME@_app_extension")
52+
NewII = &Context.Idents.get("@PLATFORM_AVAILABILITY_NAME@_app_extension");
53+
if (!NewII)
54+
return false;
55+
II = NewII;
56+
57+
auto MakeUnavailable = [&]() {
58+
IsUnavailable = true;
59+
// Reset introduced, deprecated, obsoleted.
60+
Introduced = VersionTuple();
61+
Deprecated = VersionTuple();
62+
Obsolete = VersionTuple();
63+
};
64+
65+
if (!SDKInfo) {
66+
MakeUnavailable();
67+
return true;
68+
}
69+
// Map from the fallback platform availability to the current platform
70+
// availability.
71+
const auto *Mapping = SDKInfo->getVersionMapping(
72+
DarwinSDKInfo::OSEnvPair(
73+
llvm::Triple::@FALLBACK_PLATFORM_TRIPLE_OS_VALUE@,
74+
llvm::Triple::UnknownEnvironment,
75+
llvm::Triple::@PLATFORM_TRIPLE_OS_VALUE@,
76+
llvm::Triple::UnknownEnvironment));
77+
if (!Mapping) {
78+
MakeUnavailable();
79+
return true;
80+
}
81+
82+
if (Introduced) {
83+
auto NewIntroduced = Mapping->mapIntroducedAvailabilityVersion(Introduced);
84+
if (!NewIntroduced) {
85+
MakeUnavailable();
86+
return true;
87+
}
88+
Introduced = *NewIntroduced;
89+
}
90+
91+
if (Obsolete) {
92+
auto NewObsolete =
93+
Mapping->mapDeprecatedObsoletedAvailabilityVersion(Obsolete);
94+
if (!NewObsolete) {
95+
MakeUnavailable();
96+
return true;
97+
}
98+
Obsolete = *NewObsolete;
99+
}
100+
101+
if (Deprecated) {
102+
auto NewDeprecated =
103+
Mapping->mapDeprecatedObsoletedAvailabilityVersion(Deprecated);
104+
Deprecated = NewDeprecated ? *NewDeprecated : VersionTuple();
105+
}
106+
107+
return true;
108+
}),

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,17 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(
24202420
return nullptr;
24212421
}
24222422

2423+
namespace clang {
2424+
2425+
/// Returns true if the given availability attribute should be inferred, and
2426+
/// adjusts the value of the attribute as necessary to facilitate that.
2427+
bool shouldInferAvailabilityAttribute(
2428+
const llvm::Triple &TT, const DarwinSDKInfo *SDKInfo,
2429+
const ASTContext &Context, IdentifierInfo *&II, bool &IsUnavailable,
2430+
VersionTuple &Introduced, VersionTuple &Deprecated, VersionTuple &Obsolete);
2431+
2432+
} // end namespace clang
2433+
24232434
static void handleFeatureAvailabilityAttr(Sema &S, Decl *D,
24242435
const ParsedAttr &AL) {
24252436
if (S.getLangOpts().CPlusPlus) {
@@ -2601,6 +2612,32 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
26012612
if (NewAttr)
26022613
D->addAttr(NewAttr);
26032614

2615+
/* TO_UPSTREAM(XROS) ON */
2616+
if (S.Context.getTargetInfo().getTriple().getOS() == llvm::Triple::XROS) {
2617+
// Infer availability attributes using platform-specific logic, driven by
2618+
// the SDKSettings if necessary.
2619+
IdentifierInfo *NewII = II;
2620+
bool NewIsUnavailable = IsUnavailable;
2621+
VersionTuple NewIntroduced = Introduced.Version;
2622+
VersionTuple NewDeprecated = Deprecated.Version;
2623+
VersionTuple NewObsoleted = Obsoleted.Version;
2624+
if (shouldInferAvailabilityAttribute(S.Context.getTargetInfo().getTriple(),
2625+
S.getDarwinSDKInfoForAvailabilityChecking(AL.getRange().getBegin(), "ios"),
2626+
S.Context, NewII,
2627+
NewIsUnavailable, NewIntroduced,
2628+
NewDeprecated, NewObsoleted)) {
2629+
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
2630+
ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
2631+
NewObsoleted, NewIsUnavailable, Str, IsStrict, Replacement,
2632+
Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform,
2633+
IIEnvironment);
2634+
if (NewAttr)
2635+
D->addAttr(NewAttr);
2636+
}
2637+
}
2638+
2639+
/* TO_UPSTREAM(XROS) OFF */
2640+
26042641
// Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
26052642
// matches before the start of the watchOS platform.
26062643
if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"DefaultVariant": "xrOS", "DisplayName": "xrOS",
3+
"Version": "1.0",
4+
"CanonicalName": "xros1.0",
5+
"MaximumDeploymentTarget": "1.0.99",
6+
"VersionMap": {
7+
"iOS_xrOS":{"15.0":"1.0"}
8+
}
9+
}

0 commit comments

Comments
 (0)