r268786 - Availability: attach the note to the declaration with the attributes.

Manman Ren via cfe-commits cfe-commits at lists.llvm.org
Fri May 6 12:57:17 PDT 2016


Author: mren
Date: Fri May  6 14:57:16 2016
New Revision: 268786

URL: http://llvm.org/viewvc/llvm-project?rev=268786&view=rev
Log:
Availability: attach the note to the declaration with the attributes.

Sometimes, the declaration we found has inherited availability
attributes, attaching the note to it does not tell us where the
availability attributes are in the source.

Go through the redecl chain to find the declaration with actual
availability attributes.

rdar://25221771

Modified:
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/Sema/attr-availability-macosx.c

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=268786&r1=268785&r2=268786&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri May  6 14:57:16 2016
@@ -6171,6 +6171,34 @@ static bool isDeclUnavailable(Decl *D) {
   return false;
 }
 
+static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
+                                                  const Decl *D) {
+  // Check each AvailabilityAttr to find the one for this platform.
+  for (const auto *A : D->attrs()) {
+    if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
+      // FIXME: this is copied from CheckAvailability. We should try to
+      // de-duplicate.
+
+      // Check if this is an App Extension "platform", and if so chop off
+      // the suffix for matching with the actual platform.
+      StringRef ActualPlatform = Avail->getPlatform()->getName();
+      StringRef RealizedPlatform = ActualPlatform;
+      if (Context.getLangOpts().AppExt) {
+        size_t suffix = RealizedPlatform.rfind("_app_extension");
+        if (suffix != StringRef::npos)
+          RealizedPlatform = RealizedPlatform.slice(0, suffix);
+      }
+
+      StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
+
+      // Match the platform name.
+      if (RealizedPlatform == TargetPlatform)
+        return Avail;
+    }
+  }
+  return nullptr;
+}
+
 static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
                                       Decl *Ctx, const NamedDecl *D,
                                       StringRef Message, SourceLocation Loc,
@@ -6268,7 +6296,7 @@ static void DoEmitAvailabilityWarning(Se
   if (K == Sema::AD_Deprecation) {
     if (auto attr = D->getAttr<DeprecatedAttr>())
       Replacement = attr->getReplacement();
-    if (auto attr = D->getAttr<AvailabilityAttr>())
+    if (auto attr = getAttrForPlatform(S.Context, D))
       Replacement = attr->getReplacement();
 
     if (!Replacement.empty())
@@ -6297,8 +6325,27 @@ static void DoEmitAvailabilityWarning(Se
     S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
   }
 
-  S.Diag(D->getLocation(), diag_available_here)
-      << D << available_here_select_kind;
+  // The declaration can have multiple availability attributes, we are looking
+  // at one of them.
+  const AvailabilityAttr *A = getAttrForPlatform(S.Context, D);
+  if (A && A->isInherited()) {
+    for (const Decl *Redecl = D->getMostRecentDecl(); Redecl;
+         Redecl = Redecl->getPreviousDecl()) {
+      const AvailabilityAttr *AForRedecl = getAttrForPlatform(S.Context,
+                                                              Redecl);
+      if (AForRedecl && !AForRedecl->isInherited()) {
+        // If D is a declaration with inherited attributes, the note should
+        // point to the declaration with actual attributes.
+        S.Diag(Redecl->getLocation(), diag_available_here) << D
+            << available_here_select_kind;
+        break;
+      }
+    }
+  }
+  else
+    S.Diag(D->getLocation(), diag_available_here)
+        << D << available_here_select_kind;
+
   if (K == Sema::AD_Partial)
     S.Diag(Loc, diag::note_partial_availability_silence) << D;
 }

Modified: cfe/trunk/test/Sema/attr-availability-macosx.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability-macosx.c?rev=268786&r1=268785&r2=268786&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-availability-macosx.c (original)
+++ cfe/trunk/test/Sema/attr-availability-macosx.c Fri May  6 14:57:16 2016
@@ -45,3 +45,14 @@ enum {
 enum __attribute__((availability(macosx,introduced=8.0,deprecated=9.0))) {
     bar1 = foo
 };
+
+// Make sure the note is on the declaration with the actual availability attributes.
+struct __attribute__((availability(macosx,strict,introduced=10.9))) type_info // \
+    expected-note{{'type_info' has been explicitly marked unavailable here}}
+{
+};
+struct type_info;
+int test2() {
+  struct type_info *t; // expected-error{{'type_info' is unavailable: introduced in OS X 10.9}}
+  return 0;
+}




More information about the cfe-commits mailing list