Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions clang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ endif()

include(CMakeParseArguments)
include(AddClang)
include(AddDarwinPlatform)
clang_add_additional_platform()

set(CMAKE_INCLUDE_CURRENT_DIR ON)

Expand Down
23 changes: 23 additions & 0 deletions clang/cmake/modules/AddDarwinPlatform.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# FIXME: How to generalize this to be driven by discovered SDKs?
function(clang_add_additional_platform)
# Add a platform.
set(name "xros")
set(CLANG_PLATFORM_${name}_PLATFORM_AVAILABILITY_NAME "xros" PARENT_SCOPE)
set(platformFallBack "iphoneos")

if (NOT "${platformFallBack}" STREQUAL "")
set(fallbackTripleName "${platformFallBack}")
# FIXME: we need a generic platform -> triple mapping.
if ("${fallbackTripleName}" STREQUAL "iphoneos")
set(fallbackTripleName "ios")
endif()

message(STATUS "Platform ${name} has fallback platform - ${fallbackTripleName}")
set(CLANG_PLATFORM_${name}_FALLBACK_PLATFORM_AVAILABILITY_NAME "${fallbackTripleName}" PARENT_SCOPE)

# FIXME: This is a hack for xrOS, but should be in the SDKSettings too.
set(CLANG_PLATFORM_${name}_INFER_UNAVAILABLE 1 PARENT_SCOPE)
set(CLANG_PLATFORM_${name}_PLATFORM_TRIPLE_OS_VALUE "XROS" PARENT_SCOPE)
set(CLANG_PLATFORM_${name}_FALLBACK_PLATFORM_TRIPLE_OS_VALUE "IOS" PARENT_SCOPE)
endif()
endfunction()
33 changes: 33 additions & 0 deletions clang/lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@ clang_tablegen(OpenCLBuiltins.inc -gen-clang-opencl-builtins
TARGET ClangOpenCLBuiltinsImpl
)

# Configure additional platform-specific code that controls things like
# availability attributes.
set(TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE "")

foreach(supported_platform ${LLVM_SUPPORTED_PLATFORMS})
if (${CLANG_PLATFORM_${supported_platform}_INFER_UNAVAILABLE})
# Generate code that infers availability(unavailable) attribute if a platform
# requires that.
set(output_file_name "InferUnavailableAvailabilityFromFallbackPlatform_${supported_platform}.def")
message(STATUS "Adding platform specific availability attribute code - ${output_file_name}")

set(PLATFORM_TRIPLE_OS_VALUE
"${CLANG_PLATFORM_${supported_platform}_PLATFORM_TRIPLE_OS_VALUE}")
set(FALLBACK_PLATFORM_TRIPLE_OS_VALUE
"${CLANG_PLATFORM_${supported_platform}_FALLBACK_PLATFORM_TRIPLE_OS_VALUE}")
set(PLATFORM_AVAILABILITY_NAME
"${CLANG_PLATFORM_${supported_platform}_PLATFORM_AVAILABILITY_NAME}")
set(FALLBACK_PLATFORM_AVAILABILITY_NAME
"${CLANG_PLATFORM_${supported_platform}_FALLBACK_PLATFORM_AVAILABILITY_NAME}")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/PlatformTemplates/InferUnavailableAvailabilityFromFallbackPlatform.def.in
${CMAKE_CURRENT_BINARY_DIR}/PlatformTemplates/${output_file_name}
)
set(TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE "${TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE}\n#include \"PlatformTemplates/${output_file_name}\"")
endif()
endforeach()

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/InferAvailabilityAttribute.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/InferAvailabilityAttribute.cpp
)

add_clang_library(clangSema
AnalysisBasedWarnings.cpp
# TO_UPSTREAM(BoundsSafety) ON
Expand Down Expand Up @@ -100,6 +132,7 @@ add_clang_library(clangSema
SemaWasm.cpp
SemaX86.cpp
TypeLocBuilder.cpp
${CMAKE_CURRENT_BINARY_DIR}/InferAvailabilityAttribute.cpp

DEPENDS
ClangOpenCLBuiltinsImpl
Expand Down
47 changes: 47 additions & 0 deletions clang/lib/Sema/InferAvailabilityAttribute.cpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/TargetParser/Triple.h"

namespace clang {

/// Returns true if the given availability attribute should be inferred, and
/// adjusts the value of the attribute as necessary to facilitate that.
bool shouldInferAvailabilityAttribute(const llvm::Triple &TT,
const DarwinSDKInfo *SDKInfo,
const ASTContext &Context,
IdentifierInfo *&II,
bool &IsUnavailable,
VersionTuple &Introduced,
VersionTuple &Deprecated,
VersionTuple &Obsolete) {
for (const auto &f : {
// function ptr promotion
+([] (const llvm::Triple &TT,
const DarwinSDKInfo *SDKInfo,
const ASTContext &Context,
IdentifierInfo *&II,
bool &IsUnavailable,
VersionTuple &Introduced,
VersionTuple &Deprecated,
VersionTuple &Obsolete) -> bool { return false; }),
@TEMPLATE_INCLUDES_INFER_AVAILABILITY_ATTRIBUTE@
}) {
if (f(TT, SDKInfo, Context, II, IsUnavailable, Introduced, Deprecated,
Obsolete))
return true;
}
return false;
}

} // end namespace clang
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This platform-specific template implements inferral of
// __attribute__((availability(platform, unavailable))) from a base platform
// attribute __attribute__((availability(fallback platform, unavailable))).
//
// INPUTS:
// PLATFORM_TRIPLE_OS_VALUE - the name of the target OS enum in the Triple.
// FALLBACK_PLATFORM_TRIPLE_OS_VALUE - the name of the fallback target OS
// enum in the Triple.
// PLATFORM_AVAILABILITY_NAME - the name of availability platform.
// FALLBACK_PLATFORM_AVAILABILITY_NAME - the name of availability for the
// fallback platform.
//
//===----------------------------------------------------------------------===//

// FIXME: This is now doing more than 'unavailable', the docs have to be updated.

// x introduced := map(ios introduced, 1.0, None)
// None -> x unavailable
// <version> -> x introduced <version>

// x deprecated := map(ios deprecated, 1.0, MaximumDeploymentVersion)
// None -> None
// <version> -> x deprecated <version>

// x obsoleted := map(ios obsoleted, 1.0, MaximumDeploymentVersion)
// None -> x unavailable
// <version> -> x obsoleted <version>

/// Returns true if the given availability attribute should be inferred.
+([] (const llvm::Triple &TT,
const DarwinSDKInfo *SDKInfo,
const ASTContext &Context,
IdentifierInfo *&II,
bool &IsUnavailable,
VersionTuple &Introduced,
VersionTuple &Deprecated,
VersionTuple &Obsolete) -> bool {
if (TT.getOS() != llvm::Triple::@PLATFORM_TRIPLE_OS_VALUE@)
return false;
IdentifierInfo *NewII = nullptr;
if (II->getName() == "@FALLBACK_PLATFORM_AVAILABILITY_NAME@")
NewII = &Context.Idents.get("@PLATFORM_AVAILABILITY_NAME@");
else if (II->getName() == "@FALLBACK_PLATFORM_AVAILABILITY_NAME@_app_extension")
NewII = &Context.Idents.get("@PLATFORM_AVAILABILITY_NAME@_app_extension");
if (!NewII)
return false;
II = NewII;

auto MakeUnavailable = [&]() {
IsUnavailable = true;
// Reset introduced, deprecated, obsoleted.
Introduced = VersionTuple();
Deprecated = VersionTuple();
Obsolete = VersionTuple();
};

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::@FALLBACK_PLATFORM_TRIPLE_OS_VALUE@,
llvm::Triple::UnknownEnvironment,
llvm::Triple::@PLATFORM_TRIPLE_OS_VALUE@,
llvm::Triple::UnknownEnvironment));
if (!Mapping) {
MakeUnavailable();
return true;
}

if (Introduced) {
auto NewIntroduced = Mapping->mapIntroducedAvailabilityVersion(Introduced);
if (!NewIntroduced) {
MakeUnavailable();
return true;
}
Introduced = *NewIntroduced;
}

if (Obsolete) {
auto NewObsolete =
Mapping->mapDeprecatedObsoletedAvailabilityVersion(Obsolete);
if (!NewObsolete) {
MakeUnavailable();
return true;
}
Obsolete = *NewObsolete;
}

if (Deprecated) {
auto NewDeprecated =
Mapping->mapDeprecatedObsoletedAvailabilityVersion(Deprecated);
Deprecated = NewDeprecated ? *NewDeprecated : VersionTuple();
}

return true;
}),
37 changes: 37 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2266,6 +2266,17 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(
return nullptr;
}

namespace clang {

/// Returns true if the given availability attribute should be inferred, and
/// adjusts the value of the attribute as necessary to facilitate that.
bool shouldInferAvailabilityAttribute(
const llvm::Triple &TT, const DarwinSDKInfo *SDKInfo,
const ASTContext &Context, IdentifierInfo *&II, bool &IsUnavailable,
VersionTuple &Introduced, VersionTuple &Deprecated, VersionTuple &Obsolete);

} // end namespace clang

static void handleFeatureAvailabilityAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
if (S.getLangOpts().CPlusPlus) {
Expand Down Expand Up @@ -2440,6 +2451,32 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (NewAttr)
D->addAttr(NewAttr);

/* TO_UPSTREAM(XROS) ON */
if (S.Context.getTargetInfo().getTriple().getOS() == llvm::Triple::XROS) {
// Infer availability attributes using platform-specific logic, driven by
// the SDKSettings if necessary.
IdentifierInfo *NewII = II;
bool NewIsUnavailable = IsUnavailable;
VersionTuple NewIntroduced = Introduced.Version;
VersionTuple NewDeprecated = Deprecated.Version;
VersionTuple NewObsoleted = Obsoleted.Version;
if (shouldInferAvailabilityAttribute(S.Context.getTargetInfo().getTriple(),
S.getDarwinSDKInfoForAvailabilityChecking(AL.getRange().getBegin(), "ios"),
S.Context, NewII,
NewIsUnavailable, NewIntroduced,
NewDeprecated, NewObsoleted)) {
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
NewObsoleted, NewIsUnavailable, Str, IsStrict, Replacement,
Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform,
IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
}

/* TO_UPSTREAM(XROS) OFF */

// 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,9 @@
{
"DefaultVariant": "xrOS", "DisplayName": "xrOS",
"Version": "1.0",
"CanonicalName": "xros1.0",
"MaximumDeploymentTarget": "1.0.99",
"VersionMap": {
"iOS_xrOS":{"15.0":"1.0"}
}
}
Loading