arphaman created this revision.

This patch adds a new warning flag called `-Wunguarded-availability-new`. If 
`-Wunguarded-availability` is off, this warning only warns about uses of APIs 
that have been introduced in macOS >= 10.13, iOS >= 11, watchOS >= 4 and tvOS 
>= 11. This warning is on by default. We decided to use this kind of solution 
as we didn't want to turn on `-Wunguarded-availability` by default, as we 
didn't want our users to get warnings about uses of old APIs in their existing 
projects.


Repository:
  rL LLVM

https://reviews.llvm.org/D34264

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDeclAttr.cpp
  test/SemaObjC/unguarded-availability-new.m

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
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: 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<UnguardedAvailability>, DefaultIgnore;
+def warn_unguarded_availability_new :
+  Warning<warn_unguarded_availability.Text>,
+  InGroup<UnguardedAvailabilityNew>;
 def warn_partial_availability : Warning<"%0 is only available conditionally">,
     InGroup<UnguardedAvailability>, DefaultIgnore;
 def note_partial_availability_silence : Note<
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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to