Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -98,7 +98,9 @@ def DeprecatedAttributes : DiagGroup<"deprecated-attributes">; def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; def UnavailableDeclarations : DiagGroup<"unavailable-declarations">; -def UnguardedAvailability : DiagGroup<"unguarded-availability">; +def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">; +def UnguardedAvailability : DiagGroup<"unguarded-availability", + [UnguardedAvailabilityNew]>; // partial-availability is an alias of unguarded-availability. def : DiagGroup<"partial-availability", [UnguardedAvailability]>; def DeprecatedDynamicExceptionSpec Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2870,8 +2870,13 @@ def warn_unguarded_availability : Warning<"%0 is only available on %1 %2 or newer">, InGroup, DefaultIgnore; +def warn_unguarded_availability_new : + Warning, + InGroup; def warn_partial_availability : Warning<"%0 is only available conditionally">, InGroup, DefaultIgnore; +def warn_partial_availability_new : Warning, + InGroup; def note_partial_availability_silence : Note< "explicitly redeclare %0 to silence this warning">; def note_unguarded_available_silence : Note< @@ -2879,9 +2884,14 @@ " this warning">; def warn_partial_message : Warning<"%0 is partial: %1">, InGroup, DefaultIgnore; +def warn_partial_message_new : Warning, + InGroup; def warn_partial_fwdclass_message : Warning< "%0 may be partial because the receiver type is unknown">, InGroup, DefaultIgnore; +def warn_partial_fwdclass_message_new : + Warning, + InGroup; def warn_at_available_unchecked_use : Warning< "%select{@available|__builtin_available}0 does not guard availability here; " "use if (%select{@available|__builtin_available}0) instead">, Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -6903,6 +6903,32 @@ return true; } +static bool +shouldDiagnoseAvailabilityByDefault(const ASTContext &Context, + const VersionTuple &DeploymentVersion, + const VersionTuple &DeclVersion) { + const auto &Triple = Context.getTargetInfo().getTriple(); + VersionTuple ForceAvailabilityFromVersion; + switch (Triple.getOS()) { + case llvm::Triple::IOS: + case llvm::Triple::TvOS: + ForceAvailabilityFromVersion = VersionTuple(/*Major=*/11); + break; + case llvm::Triple::WatchOS: + ForceAvailabilityFromVersion = VersionTuple(/*Major=*/4); + break; + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13); + break; + default: + // New targets should always warn about availability. + return Triple.getVendor() == llvm::Triple::Apple; + } + return DeploymentVersion >= ForceAvailabilityFromVersion || + DeclVersion >= ForceAvailabilityFromVersion; +} + static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, Decl *Ctx, const NamedDecl *D, StringRef Message, SourceLocation Loc, @@ -6991,13 +7017,26 @@ } break; - case AR_NotYetIntroduced: - diag = diag::warn_partial_availability; - diag_message = diag::warn_partial_message; - diag_fwdclass_message = diag::warn_partial_fwdclass_message; + case AR_NotYetIntroduced: { + // We would like to emit the diagnostic even if -Wunguarded-availability is + // not specified for deployment targets >= to iOS 11 or equivalent or + // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or + // later. + const AvailabilityAttr *AA = getAttrForPlatform(S.getASTContext(), D); + VersionTuple Introduced = AA->getIntroduced(); + bool NewWarning = shouldDiagnoseAvailabilityByDefault( + S.Context, S.Context.getTargetInfo().getPlatformMinVersion(), + Introduced); + diag = NewWarning ? diag::warn_partial_availability_new + : diag::warn_partial_availability; + diag_message = NewWarning ? diag::warn_partial_message_new + : diag::warn_partial_message; + diag_fwdclass_message = NewWarning ? diag::warn_partial_fwdclass_message_new + : diag::warn_partial_fwdclass_message; property_note_select = /* partial */ 2; available_here_select_kind = /* partial */ 3; break; + } case AR_Available: llvm_unreachable("Warning for availability of available declaration?"); @@ -7317,7 +7356,18 @@ if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx)) return; - SemaRef.Diag(Range.getBegin(), diag::warn_unguarded_availability) + // We would like to emit the diagnostic even if -Wunguarded-availability is + // not specified for deployment targets >= to iOS 11 or equivalent or + // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or + // later. + unsigned DiagKind = + shouldDiagnoseAvailabilityByDefault( + SemaRef.Context, + SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced) + ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability; + + SemaRef.Diag(Range.getBegin(), DiagKind) << Range << D << AvailabilityAttr::getPrettyPlatformName( SemaRef.getASTContext().getTargetInfo().getPlatformName()) Index: test/SemaObjC/unguarded-availability-new.m =================================================================== --- /dev/null +++ test/SemaObjC/unguarded-availability-new.m @@ -0,0 +1,160 @@ +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -xobjective-c++ -DMAC -triple x86_64-apple-macosx10.13 -fblocks -fsyntax-only -verify %s + +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -Wunguarded-availability-new -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -Wno-unguarded-availability-new -DNO_WARNING -fblocks -fsyntax-only -verify %s + +// unguarded-availability implies unguarded-availability-new: +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -Wunguarded-availability -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.11 -Wunguarded-availability -Wno-unguarded-availability-new -DNO_WARNING -DWARN_PREV -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -Wno-unguarded-availability -DNO_WARNING -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -Wno-unguarded-availability -Wunguarded-availability-new -fblocks -fsyntax-only -verify %s + +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -D TEST_FUNC_CURRENT -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.13 -D TEST_FUNC_NEXT -DNO_WARNING -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-ios11 -DNO_WARNING -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DMAC -triple x86_64-apple-macosx10.12 -DWARN_CURRENT -fblocks -fsyntax-only -verify %s + +// RUN: %clang_cc1 -DIOS -triple x86_64-apple-ios11 -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DIOS -triple x86_64-apple-ios11 -D TEST_FUNC_CURRENT -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DIOS -triple x86_64-apple-ios11 -D TEST_FUNC_NEXT -DNO_WARNING -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DIOS -triple x86_64-apple-ios10.3 -DWARN_CURRENT -fblocks -fsyntax-only -verify %s + +// RUN: %clang_cc1 -DTVOS -triple x86_64-apple-tvos11 -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DTVOS -triple x86_64-apple-tvos11 -D TEST_FUNC_CURRENT -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DTVOS -triple x86_64-apple-tvos11 -D TEST_FUNC_NEXT -DNO_WARNING -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DTVOS -triple x86_64-apple-tvos10 -DWARN_CURRENT -fblocks -fsyntax-only -verify %s + +// RUN: %clang_cc1 -DWATCHOS -triple i386-apple-watchos4 -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DWATCHOS -triple i386-apple-watchos4 -D TEST_FUNC_CURRENT -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DWATCHOS -triple i386-apple-watchos4 -D TEST_FUNC_NEXT -DNO_WARNING -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -DWATCHOS -triple i386-apple-watchos3 -DWARN_CURRENT -fblocks -fsyntax-only -verify %s + +#ifdef MAC +#define PLATFORM macos +#define NEXT 10.14 + +#define AVAILABLE_PREV __attribute__((availability(macos, introduced = 10.12))) +#define AVAILABLE_CURRENT __attribute__((availability(macos, introduced = 10.13))) +#define AVAILABLE_NEXT __attribute__((availability(macos, introduced = 10.14))) +#endif + +#ifdef IOS +#define PLATFORM ios +#define NEXT 12 + +#define AVAILABLE_PREV __attribute__((availability(ios, introduced = 10))) +#define AVAILABLE_CURRENT __attribute__((availability(ios, introduced = 11))) +#define AVAILABLE_NEXT __attribute__((availability(ios, introduced = 12))) +#endif + +#ifdef TVOS +#define PLATFORM tvos +#define NEXT 13 + +#define AVAILABLE_PREV __attribute__((availability(tvos, introduced = 10))) +#define AVAILABLE_CURRENT __attribute__((availability(tvos, introduced = 11))) +#define AVAILABLE_NEXT __attribute__((availability(tvos, introduced = 13))) +#endif + +#ifdef WATCHOS +#define PLATFORM watchos +#define NEXT 5 + +#define AVAILABLE_PREV __attribute__((availability(watchos, introduced = 3))) +#define AVAILABLE_CURRENT __attribute__((availability(watchos, introduced = 4))) +#define AVAILABLE_NEXT __attribute__((availability(watchos, introduced = 5))) +#endif + +void previouslyAvailable() AVAILABLE_PREV; +#ifdef WARN_PREV + // expected-note@-2 {{'previouslyAvailable' has been explicitly marked partial here}} +#endif +void currentlyAvailable() AVAILABLE_CURRENT; +#ifdef WARN_CURRENT + // expected-note@-2 {{'currentlyAvailable' has been explicitly marked partial here}} +#endif +void willBeAvailabile() AVAILABLE_NEXT; +#ifndef NO_WARNING + // expected-note@-2 {{'willBeAvailabile' has been explicitly marked partial here}} +#endif + +#ifdef TEST_FUNC_CURRENT +#define FUNC_AVAILABLE AVAILABLE_CURRENT +#endif +#ifdef TEST_FUNC_NEXT +#define FUNC_AVAILABLE AVAILABLE_NEXT +#endif +#ifndef FUNC_AVAILABLE +#define FUNC_AVAILABLE +#endif + +typedef int AVAILABLE_NEXT new_int; +#ifndef NO_WARNING + // expected-note@-2 {{'new_int' has been explicitly marked partial here}} +#endif +FUNC_AVAILABLE new_int x; +#ifndef NO_WARNING +#ifdef MAC + // expected-warning@-3 {{'new_int' is partial: introduced in macOS 10.14}} expected-note@-3 {{explicitly redeclare 'new_int' to silence this warning}} +#endif +#ifdef IOS + // expected-warning@-6 {{'new_int' is partial: introduced in iOS 12}} expected-note@-6 {{explicitly redeclare 'new_int' to silence this warning}} +#endif +#ifdef TVOS + // expected-warning@-9 {{'new_int' is partial: introduced in tvOS 13}} expected-note@-9 {{explicitly redeclare 'new_int' to silence this warning}} +#endif +#ifdef WATCHOS + // expected-warning@-12 {{'new_int' is partial: introduced in watchOS 5}} expected-note@-12 {{explicitly redeclare 'new_int' to silence this warning}} +#endif +#endif + +void test() FUNC_AVAILABLE { + previouslyAvailable(); +#ifdef WARN_PREV +#ifdef MAC + // expected-warning@-3 {{'previouslyAvailable' is only available on macOS 10.12 or newer}} +#endif + // expected-note@-5 {{enclose 'previouslyAvailable' in an @available check to silence this warning}} +#endif + currentlyAvailable(); +#ifdef WARN_CURRENT +#ifdef MAC + // expected-warning@-3 {{'currentlyAvailable' is only available on macOS 10.13 or newer}} +#endif +#ifdef IOS + // expected-warning@-6 {{'currentlyAvailable' is only available on iOS 11 or newer}} +#endif +#ifdef TVOS + // expected-warning@-9 {{'currentlyAvailable' is only available on tvOS 11 or newer}} +#endif +#ifdef WATCHOS + // expected-warning@-12 {{'currentlyAvailable' is only available on watchOS 4 or newer}} +#endif + // expected-note@-14 {{enclose 'currentlyAvailable' in an @available check to silence this warning}} +#endif + willBeAvailabile(); +#ifndef NO_WARNING +#ifdef MAC + // expected-warning@-3 {{'willBeAvailabile' is only available on macOS 10.14 or newer}} +#endif +#ifdef IOS + // expected-warning@-6 {{'willBeAvailabile' is only available on iOS 12 or newer}} +#endif +#ifdef TVOS + // expected-warning@-9 {{'willBeAvailabile' is only available on tvOS 13 or newer}} +#endif +#ifdef WATCHOS + // expected-warning@-12 {{'willBeAvailabile' is only available on watchOS 5 or newer}} +#endif + // expected-note@-14 {{enclose 'willBeAvailabile' in an @available check to silence this warning}} +#endif + if (@available(PLATFORM NEXT, *)) + willBeAvailabile(); // OK +} + +#ifdef NO_WARNING +#ifndef WARN_PREV +// expected-no-diagnostics +#endif +#endif