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,6 +2870,9 @@ 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 note_partial_availability_silence : Note< Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -7293,6 +7293,33 @@ bool VisitTypeLoc(TypeLoc Ty); }; +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: + assert(!Triple.isMacOSX() && "MacOS should be handled in the switch"); + // New targets should always warn about availability. + return Triple.getVendor() == llvm::Triple::Apple; + } + return DeploymentVersion >= ForceAvailabilityFromVersion || + DeclVersion >= ForceAvailabilityFromVersion; +} + void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( NamedDecl *D, SourceRange Range) { @@ -7315,7 +7342,21 @@ 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 = + !SemaRef.Diags.isIgnored(diag::warn_unguarded_availability_new, + Range.getBegin()) && + 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,129 @@ +// 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.13 -Wunguarded-availability -Wno-unguarded-availability-new -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; +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 + +void test() FUNC_AVAILABLE { + previouslyAvailable(); + 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 +// expected-no-diagnostics +#endif