erik.pilkington created this revision.
erik.pilkington added a reviewer: manmanren.
erik.pilkington added a subscriber: cfe-commits.

Note: this patch depends on: https://reviews.llvm.org/D25283

This patch delays handling of `AR_NotYetIntroduced` diagnostics, so that the 
following compiles with no warnings:

  typedef int new_int __attribute__((availability(macos, introduced=100)));
  
  new_int f() __attribute__((availability(macos, introduced=100)));

This is done by treating `AR_NotYetIntroduced` diagnostics as delayed, just 
like `AR_Unavailable` and `AR_Deprecated`. This means that we emit the 
diagnostic once we finished parsing `f()`, at which point we have the context 
to determine if we should diagnose `new_int`.

Thanks!


https://reviews.llvm.org/D25284

Files:
  include/clang/Sema/DelayedDiagnostic.h
  lib/Sema/DelayedDiagnostic.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaObjC/unguarded-availability.m

Index: test/SemaObjC/unguarded-availability.m
===================================================================
--- test/SemaObjC/unguarded-availability.m
+++ test/SemaObjC/unguarded-availability.m
@@ -63,7 +63,7 @@
 #ifdef OBJCPP
 // expected-note@+2 {{marked partial here}}
 #endif
-typedef int int_10_12 AVAILABLE_10_12; // expected-note 3 {{'int_10_12' has been explicitly marked partial here}}
+typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been explicitly marked partial here}}
 
 void use_typedef() {
   int_10_11 x; // expected-warning{{'int_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'int_10_11' in an @available check to silence this warning}}
@@ -127,8 +127,7 @@
 
 void test_params(int_10_12 x); // expected-warning {{'int_10_12' is partial: introduced in macOS 10.12}} expected-note{{redeclare}}
 
-// FIXME: This should be fine!
-void test_params2(int_10_12 x) AVAILABLE_10_12; // expected-warning {{'int_10_12' is partial: introduced in macOS 10.12}} expected-note{{redeclare}}
+void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn
 
 #ifdef OBJCPP
 
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -6464,9 +6464,6 @@
     break;
 
   case AR_NotYetIntroduced:
-    assert(!S.getCurFunctionOrMethodDecl() &&
-           "Function-level partial availablity should not be diagnosed here!");
-
     diag = diag::warn_partial_availability;
     diag_message = diag::warn_partial_message;
     diag_fwdclass_message = diag::warn_partial_fwdclass_message;
@@ -6539,15 +6536,14 @@
 
 static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
                                            Decl *Ctx) {
-  assert(DD.Kind == DelayedDiagnostic::Deprecation ||
-         DD.Kind == DelayedDiagnostic::Unavailable);
-  AvailabilityResult AR = DD.Kind == DelayedDiagnostic::Deprecation
-                              ? AR_Deprecated
-                              : AR_Unavailable;
+  assert(DD.Kind == DelayedDiagnostic::Availability &&
+         "Expected an availability diagnostic here");
+
   DD.Triggered = true;
-  DoEmitAvailabilityWarning(
-      S, AR, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc,
-      DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
+  DoEmitAvailabilityWarning(S, DD.getAvailabilityResult(), Ctx,
+                            DD.getDeprecationDecl(), DD.getDeprecationMessage(),
+                            DD.Loc, DD.getUnknownObjCClass(),
+                            DD.getObjCProperty(), false);
 }
 
 void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -6577,8 +6573,7 @@
         continue;
 
       switch (diag.Kind) {
-      case DelayedDiagnostic::Deprecation:
-      case DelayedDiagnostic::Unavailable:
+      case DelayedDiagnostic::Availability:
         // Don't bother giving deprecation/unavailable diagnostics if
         // the decl is invalid.
         if (!decl->isInvalidDecl())
@@ -6613,8 +6608,7 @@
                                    const ObjCPropertyDecl  *ObjCProperty,
                                    bool ObjCPropertyAccess) {
   // Delay if we're currently parsing a declaration.
-  if (DelayedDiagnostics.shouldDelayDiagnostics() &&
-      AR != AR_NotYetIntroduced) {
+  if (DelayedDiagnostics.shouldDelayDiagnostics()) {
     DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
         AR, Loc, D, UnknownObjCClass, ObjCProperty, Message,
         ObjCPropertyAccess));
Index: lib/Sema/DelayedDiagnostic.cpp
===================================================================
--- lib/Sema/DelayedDiagnostic.cpp
+++ lib/Sema/DelayedDiagnostic.cpp
@@ -20,24 +20,15 @@
 using namespace sema;
 
 DelayedDiagnostic
-DelayedDiagnostic::makeAvailability(AvailabilityResult AD,
+DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
                                     SourceLocation Loc,
                                     const NamedDecl *D,
                                     const ObjCInterfaceDecl *UnknownObjCClass,
                                     const ObjCPropertyDecl  *ObjCProperty,
                                     StringRef Msg,
                                     bool ObjCPropertyAccess) {
   DelayedDiagnostic DD;
-  switch (AD) {
-  case AR_Deprecated:
-    DD.Kind = Deprecation;
-    break;
-  case AR_Unavailable:
-    DD.Kind = Unavailable;
-    break;
-  default:
-    llvm_unreachable("partial diags should not be delayed");
-  }
+  DD.Kind = Availability;
   DD.Triggered = false;
   DD.Loc = Loc;
   DD.DeprecationData.Decl = D;
@@ -51,18 +42,18 @@
 
   DD.DeprecationData.Message = MessageData;
   DD.DeprecationData.MessageLen = Msg.size();
+  DD.DeprecationData.AR = AR;
   DD.DeprecationData.ObjCPropertyAccess = ObjCPropertyAccess;
   return DD;
 }
 
 void DelayedDiagnostic::Destroy() {
-  switch (static_cast<DDKind>(Kind)) {
+  switch (Kind) {
   case Access: 
     getAccessData().~AccessedEntity(); 
     break;
 
-  case Deprecation:
-  case Unavailable:
+  case Availability:
     delete [] DeprecationData.Message;
     break;
 
Index: include/clang/Sema/DelayedDiagnostic.h
===================================================================
--- include/clang/Sema/DelayedDiagnostic.h
+++ include/clang/Sema/DelayedDiagnostic.h
@@ -113,9 +113,9 @@
 /// the complete parsing of the current declaration.
 class DelayedDiagnostic {
 public:
-  enum DDKind { Deprecation, Unavailable, Access, ForbiddenType };
+  enum DDKind : unsigned char { Availability, Access, ForbiddenType };
 
-  unsigned char Kind; // actually a DDKind
+  DDKind Kind;
   bool Triggered;
 
   SourceLocation Loc;
@@ -165,16 +165,18 @@
   }
 
   const NamedDecl *getDeprecationDecl() const {
-    assert((Kind == Deprecation || Kind == Unavailable) &&
-           "Not a deprecation diagnostic.");
+    assert(Kind == Availability && "Not an availability diagnostic.");
     return DeprecationData.Decl;
   }
 
   StringRef getDeprecationMessage() const {
-    assert((Kind == Deprecation || Kind == Unavailable) &&
-           "Not a deprecation diagnostic.");
-    return StringRef(DeprecationData.Message,
-                           DeprecationData.MessageLen);
+    assert(Kind == Availability && "Not an availability diagnostic.");
+    return StringRef(DeprecationData.Message, DeprecationData.MessageLen);
+  }
+
+  AvailabilityResult getAvailabilityResult() const {
+    assert(Kind == Availability && "Not an availability diagnostic.");
+    return DeprecationData.AR;
   }
 
   /// The diagnostic ID to emit.  Used like so:
@@ -216,6 +218,7 @@
     const ObjCPropertyDecl  *ObjCProperty;
     const char *Message;
     size_t MessageLen;
+    AvailabilityResult AR;
     bool ObjCPropertyAccess;
   };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to