diff --git a/clang/include/clang/Basic/DarwinSDKInfo.h b/clang/include/clang/Basic/DarwinSDKInfo.h --- a/clang/include/clang/Basic/DarwinSDKInfo.h +++ b/clang/include/clang/Basic/DarwinSDKInfo.h @@ -57,6 +57,20 @@ llvm::Triple::MacOSX, llvm::Triple::UnknownEnvironment); } + /// Returns the os-environment mapping pair that's used to represent the + /// iOS -> watchOS version mapping. + static inline constexpr OSEnvPair iOStoWatchOSPair() { + return OSEnvPair(llvm::Triple::IOS, llvm::Triple::UnknownEnvironment, + llvm::Triple::WatchOS, llvm::Triple::UnknownEnvironment); + } + + /// Returns the os-environment mapping pair that's used to represent the + /// iOS -> tvOS version mapping. + static inline constexpr OSEnvPair iOStoTvOSPair() { + return OSEnvPair(llvm::Triple::IOS, llvm::Triple::UnknownEnvironment, + llvm::Triple::TvOS, llvm::Triple::UnknownEnvironment); + } + private: StorageType Value; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1565,8 +1565,11 @@ /// assignment. llvm::DenseMap RefsMinusAssignments; +private: Optional> CachedDarwinSDKInfo; + bool WarnedDarwinSDKInfoMissing = false; + public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind = TU_Complete, @@ -1595,8 +1598,10 @@ ASTConsumer &getASTConsumer() const { return Consumer; } ASTMutationListener *getASTMutationListener() const; ExternalSemaSource* getExternalSource() const { return ExternalSource; } + DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, StringRef Platform); + DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(); ///Registers an external source. If an external source already exists, /// creates a multiplex external source and appends to it. diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -60,6 +60,16 @@ DarwinSDKInfo * Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, StringRef Platform) { + auto *SDKInfo = getDarwinSDKInfoForAvailabilityChecking(); + if (!SDKInfo && !WarnedDarwinSDKInfoMissing) { + Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking) + << Platform; + WarnedDarwinSDKInfoMissing = true; + } + return SDKInfo; +} + +DarwinSDKInfo *Sema::getDarwinSDKInfoForAvailabilityChecking() { if (CachedDarwinSDKInfo) return CachedDarwinSDKInfo->get(); auto SDKInfo = parseDarwinSDKInfo( @@ -71,8 +81,6 @@ } if (!SDKInfo) llvm::consumeError(SDKInfo.takeError()); - Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking) - << Platform; CachedDarwinSDKInfo = std::unique_ptr(); return nullptr; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2625,9 +2625,25 @@ NewII = &S.Context.Idents.get("watchos_app_extension"); if (NewII) { - auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple { + const auto *SDKInfo = S.getDarwinSDKInfoForAvailabilityChecking(); + const auto *IOSToWatchOSMapping = + SDKInfo ? SDKInfo->getVersionMapping( + DarwinSDKInfo::OSEnvPair::iOStoWatchOSPair()) + : nullptr; + + auto adjustWatchOSVersion = + [IOSToWatchOSMapping](VersionTuple Version) -> VersionTuple { if (Version.empty()) return Version; + auto MinimumWatchOSVersion = VersionTuple(2, 0); + + if (IOSToWatchOSMapping) { + if (auto MappedVersion = IOSToWatchOSMapping->map( + Version, MinimumWatchOSVersion, None)) { + return MappedVersion.getValue(); + } + } + auto Major = Version.getMajor(); auto NewMajor = Major >= 9 ? Major - 7 : 0; if (NewMajor >= 2) { @@ -2641,7 +2657,7 @@ return VersionTuple(NewMajor); } - return VersionTuple(2, 0); + return MinimumWatchOSVersion; }; auto NewIntroduced = adjustWatchOSVersion(Introduced.Version); @@ -2666,10 +2682,34 @@ NewII = &S.Context.Idents.get("tvos_app_extension"); if (NewII) { + const auto *SDKInfo = S.getDarwinSDKInfoForAvailabilityChecking(); + const auto *IOSToTvOSMapping = + SDKInfo ? SDKInfo->getVersionMapping( + DarwinSDKInfo::OSEnvPair::iOStoTvOSPair()) + : nullptr; + + auto AdjustTvOSVersion = + [IOSToTvOSMapping](VersionTuple Version) -> VersionTuple { + if (Version.empty()) + return Version; + + if (IOSToTvOSMapping) { + if (auto MappedVersion = + IOSToTvOSMapping->map(Version, VersionTuple(0, 0), None)) { + return MappedVersion.getValue(); + } + } + return Version; + }; + + auto NewIntroduced = AdjustTvOSVersion(Introduced.Version); + auto NewDeprecated = AdjustTvOSVersion(Deprecated.Version); + auto NewObsoleted = AdjustTvOSVersion(Obsoleted.Version); + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( - ND, AL, NewII, true /*Implicit*/, Introduced.Version, - Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, - Replacement, Sema::AMK_None, + ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, + NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, + Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform); if (NewAttr) D->addAttr(NewAttr); diff --git a/clang/test/Sema/Inputs/AppleTVOS15.0.sdk/SDKSettings.json b/clang/test/Sema/Inputs/AppleTVOS15.0.sdk/SDKSettings.json new file mode 100644 --- /dev/null +++ b/clang/test/Sema/Inputs/AppleTVOS15.0.sdk/SDKSettings.json @@ -0,0 +1,67 @@ +{ + "DisplayName": "tvOS 15.0", + "Version": "15.0", + "MaximumDeploymentTarget": "15.0.99", + "PropertyConditionFallbackNames": [], + "VersionMap": { + "iOS_tvOS": { + "10.0": "10.0", + "10.1": "10.0", + "10.2": "10.1", + "10.3": "10.2", + "10.3.1": "10.2", + "11.0": "11.0", + "11.1": "11.1", + "11.2": "11.2", + "11.3": "11.3", + "11.4": "11.4", + "12.0": "12.0", + "12.1": "12.1", + "12.2": "12.2", + "12.4": "12.4", + "13.0": "13.0", + "13.1": "13.0", + "13.2": "13.2", + "13.4": "13.4", + "13.5": "13.4", + "13.6": "13.4", + "13.7": "13.4", + "14.0": "14.0", + "14.1": "14.0", + "14.2": "14.2", + "14.3": "14.3", + "14.4": "14.3", + "14.5": "14.5", + "15.0": "15.0", + "9.0": "9.0", + "9.1": "9.0", + "9.2": "9.1", + "9.3": "9.2" + }, + "tvOS_iOS": { + "10.0": "10.0", + "10.1": "10.2", + "10.2": "10.3", + "11.0": "11.0", + "11.1": "11.1", + "11.2": "11.2", + "11.3": "11.3", + "11.4": "11.4", + "12.0": "12.0", + "12.1": "12.1", + "12.2": "12.2", + "12.4": "12.4", + "13.0": "13.0", + "13.2": "13.2", + "13.4": "13.4", + "14.0": "14.0", + "14.2": "14.2", + "14.3": "14.3", + "14.5": "14.5", + "15.0": "15.0", + "9.0": "9.0", + "9.1": "9.2", + "9.2": "9.3" + } + } +} diff --git a/clang/test/Sema/Inputs/WatchOS7.0.sdk/SDKSettings.json b/clang/test/Sema/Inputs/WatchOS7.0.sdk/SDKSettings.json new file mode 100644 --- /dev/null +++ b/clang/test/Sema/Inputs/WatchOS7.0.sdk/SDKSettings.json @@ -0,0 +1,57 @@ +{ + "DisplayName": "watchOS 7.0", + "Version": "7.0", + "MaximumDeploymentTarget": "7.0.99", + "PropertyConditionFallbackNames": [], + "VersionMap": { + "iOS_watchOS": { + "10.0": "3.0", + "10.1": "3.1", + "10.2": "3.1", + "10.3": "3.2", + "10.3.1": "3.2", + "11.0": "4.0", + "11.1": "4.1", + "11.2": "4.2", + "11.3": "4.3", + "11.4": "4.3", + "12.0": "5.0", + "12.1": "5.1", + "12.2": "5.2", + "12.4": "5.3", + "13.0": "6.0", + "13.1": "6.0", + "13.2": "6.1", + "13.4": "6.2", + "13.5": "6.2", + "13.6": "6.2", + "13.7": "6.2", + "14.0": "7.0", + "14.1": "7.0", + "9.0": "2.0", + "9.1": "2.0", + "9.2": "2.1", + "9.3": "2.2" + }, + "watchOS_iOS": { + "2.0": "9.0", + "2.1": "9.2", + "2.2": "9.3", + "3.0": "10.0", + "3.1": "10.1", + "3.2": "10.3", + "4.0": "11.0", + "4.1": "11.1", + "4.2": "11.2", + "4.3": "11.3", + "5.0": "12.0", + "5.1": "12.1", + "5.2": "12.2", + "5.3": "12.4", + "6.0": "13.0", + "6.1": "13.2", + "6.2": "13.4", + "7.0": "14.0" + } + } +} diff --git a/clang/test/Sema/attr-availability-tvos.c b/clang/test/Sema/attr-availability-tvos.c --- a/clang/test/Sema/attr-availability-tvos.c +++ b/clang/test/Sema/attr-availability-tvos.c @@ -1,63 +1,80 @@ -// RUN: %clang_cc1 "-triple" "x86_64-apple-tvos3.0" -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "x86_64-apple-tvos13.0" -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "x86_64-apple-tvos13.0" -DUSE_VERSION_MAP -isysroot %S/Inputs/AppleTVOS15.0.sdk -fsyntax-only -verify %s -void f0(int) __attribute__((availability(tvos,introduced=2.0,deprecated=2.1))); // expected-note {{'f0' has been explicitly marked deprecated here}} -void f1(int) __attribute__((availability(tvos,introduced=2.1))); -void f2(int) __attribute__((availability(tvos,introduced=2.0,deprecated=3.0))); // expected-note {{'f2' has been explicitly marked deprecated here}} -void f3(int) __attribute__((availability(tvos,introduced=3.0))); -void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(tvos,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}} +void f0(int) __attribute__((availability(tvos,introduced=12.0,deprecated=12.1))); // expected-note {{'f0' has been explicitly marked deprecated here}} +void f1(int) __attribute__((availability(tvos,introduced=12.1))); +void f2(int) __attribute__((availability(tvos,introduced=12.0,deprecated=13.0))); // expected-note {{'f2' has been explicitly marked deprecated here}} +void f3(int) __attribute__((availability(tvos,introduced=13.0))); +void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(tvos,introduced=12.0,deprecated=12.1,obsoleted=13.0))); // expected-note{{explicitly marked unavailable}} -void f5(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f5' has been explicitly marked deprecated here}} -void f6(int) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} -void f6(int) __attribute__((availability(tvos,introduced=2.0))); +void f5(int) __attribute__((availability(tvos,introduced=12.0))) __attribute__((availability(tvos,deprecated=13.0))); // expected-note {{'f5' has been explicitly marked deprecated here}} +void f6(int) __attribute__((availability(tvos,deprecated=13.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} +void f6(int) __attribute__((availability(tvos,introduced=12.0))); void test() { - f0(0); // expected-warning{{'f0' is deprecated: first deprecated in tvOS 2.1}} + f0(0); // expected-warning{{'f0' is deprecated: first deprecated in tvOS 12.1}} f1(0); - f2(0); // expected-warning{{'f2' is deprecated: first deprecated in tvOS 3.0}} + f2(0); // expected-warning{{'f2' is deprecated: first deprecated in tvOS 13.0}} f3(0); - f4(0); // expected-error{{f4' is unavailable: obsoleted in tvOS 3.0}} - f5(0); // expected-warning{{'f5' is deprecated: first deprecated in tvOS 3.0}} - f6(0); // expected-warning{{'f6' is deprecated: first deprecated in tvOS 3.0}} + f4(0); // expected-error{{f4' is unavailable: obsoleted in tvOS 13.0}} + f5(0); // expected-warning{{'f5' is deprecated: first deprecated in tvOS 13.0}} + f6(0); // expected-warning{{'f6' is deprecated: first deprecated in tvOS 13.0}} } -// Anything iOS later than 8 does not apply to tvOS. -void f9(int) __attribute__((availability(ios,introduced=2.0,deprecated=9.0))); +// Anything iOS later than 13 does not apply to tvOS. +void f9(int) __attribute__((availability(ios,introduced=12.0,deprecated=19.0))); void test_transcribed_availability() { f9(0); } -__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-warning 2{{availability does not match previous declaration}} -__attribute__((availability(ios,introduced=7_0))) // expected-note 2{{previous attribute is here}} +__attribute__((availability(ios,introduced=19_0,deprecated=19_0,message="" ))) // expected-warning 2{{availability does not match previous declaration}} +__attribute__((availability(ios,introduced=17_0))) // expected-note 2{{previous attribute is here}} void f10(int); // Test tvOS specific attributes. -void f0_tvos(int) __attribute__((availability(tvos,introduced=2.0,deprecated=2.1))); // expected-note {{'f0_tvos' has been explicitly marked deprecated here}} -void f1_tvos(int) __attribute__((availability(tvos,introduced=2.1))); -void f2_tvos(int) __attribute__((availability(tvOS,introduced=2.0,deprecated=3.0))); // expected-note {{'f2_tvos' has been explicitly marked deprecated here}} -void f3_tvos(int) __attribute__((availability(tvos,introduced=3.0))); -void f4_tvos(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(tvos,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}} -void f5_tvos(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); -void f5_attr_reversed_tvos(int) __attribute__((availability(ios, deprecated=3.0))) __attribute__((availability(tvos,introduced=2.0))); -void f5b_tvos(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f5b_tvos' has been explicitly marked deprecated here}} -void f5c_tvos(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5c_tvos' has been explicitly marked deprecated here}} -void f6_tvos(int) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f6_tvos' has been explicitly marked deprecated here}} -void f6_tvos(int) __attribute__((availability(tvOS,introduced=2.0))); +void f0_tvos(int) __attribute__((availability(tvos,introduced=12.0,deprecated=12.1))); // expected-note {{'f0_tvos' has been explicitly marked deprecated here}} +void f1_tvos(int) __attribute__((availability(tvos,introduced=12.1))); +void f2_tvos(int) __attribute__((availability(tvOS,introduced=12.0,deprecated=13.0))); // expected-note {{'f2_tvos' has been explicitly marked deprecated here}} +void f3_tvos(int) __attribute__((availability(tvos,introduced=13.0))); +void f4_tvos(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(tvos,introduced=12.0,deprecated=12.1,obsoleted=13.0))); // expected-note{{explicitly marked unavailable}} +void f5_tvos(int) __attribute__((availability(tvos,introduced=12.0))) __attribute__((availability(ios,deprecated=13.0))); +void f5_attr_reversed_tvos(int) __attribute__((availability(ios, deprecated=13.0))) __attribute__((availability(tvos,introduced=12.0))); +void f5b_tvos(int) __attribute__((availability(tvos,introduced=12.0))) __attribute__((availability(tvos,deprecated=13.0))); // expected-note {{'f5b_tvos' has been explicitly marked deprecated here}} +void f5c_tvos(int) __attribute__((availability(ios,introduced=12.0))) __attribute__((availability(ios,deprecated=13.0))); // expected-note {{'f5c_tvos' has been explicitly marked deprecated here}} +void f6_tvos(int) __attribute__((availability(tvos,deprecated=13.0))); // expected-note {{'f6_tvos' has been explicitly marked deprecated here}} +void f6_tvos(int) __attribute__((availability(tvOS,introduced=12.0))); void test_tvos() { - f0_tvos(0); // expected-warning{{'f0_tvos' is deprecated: first deprecated in tvOS 2.1}} + f0_tvos(0); // expected-warning{{'f0_tvos' is deprecated: first deprecated in tvOS 12.1}} f1_tvos(0); - f2_tvos(0); // expected-warning{{'f2_tvos' is deprecated: first deprecated in tvOS 3.0}} + f2_tvos(0); // expected-warning{{'f2_tvos' is deprecated: first deprecated in tvOS 13.0}} f3_tvos(0); - f4_tvos(0); // expected-error{{'f4_tvos' is unavailable: obsoleted in tvOS 3.0}} + f4_tvos(0); // expected-error{{'f4_tvos' is unavailable: obsoleted in tvOS 13.0}} // We get no warning here because any explicit 'tvos' availability causes // the ios availability to not implicitly become 'tvos' availability. Otherwise we'd get // a deprecated warning. f5_tvos(0); // no-warning f5_attr_reversed_tvos(0); // no-warning // We get a deprecated warning here because both attributes are explicitly 'tvos'. - f5b_tvos(0); // expected-warning {{'f5b_tvos' is deprecated: first deprecated in tvOS 3.0}} + f5b_tvos(0); // expected-warning {{'f5b_tvos' is deprecated: first deprecated in tvOS 13.0}} // We get a deprecated warning here because both attributes are 'ios' (both get mapped to 'tvos'). - f5c_tvos(0); // expected-warning {{'f5c_tvos' is deprecated: first deprecated in tvOS 3.0}} - f6_tvos(0); // expected-warning{{'f6_tvos' is deprecated: first deprecated in tvOS 3.0}} + f5c_tvos(0); // expected-warning {{'f5c_tvos' is deprecated: first deprecated in tvOS 13.0}} + f6_tvos(0); // expected-warning{{'f6_tvos' is deprecated: first deprecated in tvOS 13.0}} } + +#ifdef USE_VERSION_MAP +// iOS 9.3 corresponds to tvOS 9.2, as indicated in 'SDKSettings.json'. +void f11(int) __attribute__((availability(ios,deprecated=9.3))); // expected-note {{'f11' has been explicitly marked deprecated here}} + +void testWithVersionMap() { + f11(0); // expected-warning {{'f11' is deprecated: first deprecated in tvOS 9.2}} +} +#else +// Without VersionMap, tvOS version is inferred incorrectly as 9.3. +void f11(int) __attribute__((availability(ios,deprecated=9.3))); // expected-note {{'f11' has been explicitly marked deprecated here}} + +void testWithoutVersionMap() { + f11(0); // expected-warning {{'f11' is deprecated: first deprecated in tvOS 9.3}} +} +#endif diff --git a/clang/test/Sema/attr-availability-watchos.c b/clang/test/Sema/attr-availability-watchos.c --- a/clang/test/Sema/attr-availability-watchos.c +++ b/clang/test/Sema/attr-availability-watchos.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 "-triple" "arm64-apple-watchos3.0" -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "arm64-apple-watchos4.0" -fsyntax-only -verify %s +// RUN: %clang_cc1 "-triple" "arm64-apple-watchos4.0" -DUSE_VERSION_MAP -isysroot %S/Inputs/WatchOS7.0.sdk -fsyntax-only -verify %s void f0(int) __attribute__((availability(ios,introduced=2.0,deprecated=2.1))); // expected-note {{'f0' has been explicitly marked deprecated here}} void f1(int) __attribute__((availability(ios,introduced=2.1))); @@ -58,3 +59,19 @@ void test_ios_correctly_map_to_watchos() { deprecatedAfterIntroduced(); // expected-warning {{'deprecatedAfterIntroduced' is deprecated: first deprecated in watchOS 3}} } + +#ifdef USE_VERSION_MAP +// iOS 10.3.1 corresponds to watchOS 3.2, as indicated in 'SDKSettings.json'. +void f9(int) __attribute__((availability(ios,deprecated=10.3.1))); // expected-note {{'f9' has been explicitly marked deprecated here}} + +void testWithVersionMap() { + f9(0); // expected-warning {{'f9' is deprecated: first deprecated in watchOS 3.2}} +} +#else +// Without VersionMap, watchOS version is inferred incorrectly as 3.3.1. +void f9(int) __attribute__((availability(ios,deprecated=10.3.1))); // expected-note {{'f9' has been explicitly marked deprecated here}} + +void testWithoutVersionMap() { + f9(0); // expected-warning {{'f9' is deprecated: first deprecated in watchOS 3.3.1}} +} +#endif