r307175 - [Sema] Don't allow -Wunguarded-availability to be silenced with redecls

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 6 14:12:50 PDT 2017


We currently rely on this for chromium; that's how the warning used to work
when I added it. What's the transition plan? Can we have a flag to
incrementally transition to whatever the new way is? (Is it documented
anywhere?)

Also, I think the replacement somehow needs the new runtime stuff from
libbuiltin -- does the driver know when to add that to the link line? If
so, where's the logic for that? If not, what library is supposed to provide
the runtime check function?

On Jul 5, 2017 7:09 PM, "Erik Pilkington via cfe-commits" <
cfe-commits at lists.llvm.org> wrote:

Author: epilk
Date: Wed Jul  5 10:08:56 2017
New Revision: 307175

URL: http://llvm.org/viewvc/llvm-project?rev=307175&view=rev
Log:
[Sema] Don't allow -Wunguarded-availability to be silenced with redecls

Differential revision: https://reviews.llvm.org/D33816

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/DelayedDiagnostic.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/DelayedDiagnostic.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/attr-availability.c
    cfe/trunk/test/Sema/attr-deprecated.c
    cfe/trunk/test/Sema/attr-unavailable-message.c
    cfe/trunk/test/SemaCXX/attr-deprecated.cpp
    cfe/trunk/test/SemaObjC/attr-availability.m
    cfe/trunk/test/SemaObjC/unguarded-availability-new.m
    cfe/trunk/test/SemaObjC/unguarded-availability.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
DiagnosticSemaKinds.td?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul  5
10:08:56 2017
@@ -2880,7 +2880,7 @@ def warn_partial_availability : Warning<
 def warn_partial_availability_new : Warning<warn_partial_
availability.Text>,
   InGroup<UnguardedAvailabilityNew>;
 def note_partial_availability_silence : Note<
-  "explicitly redeclare %0 to silence this warning">;
+  "annotate %select{%1|anonymous %1}0 with an availability attribute to
silence">;
 def note_unguarded_available_silence : Note<
   "enclose %0 in %select{an @available|a __builtin_available}1 check to
silence"
   " this warning">;

Modified: cfe/trunk/include/clang/Sema/DelayedDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
clang/Sema/DelayedDiagnostic.h?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/include/clang/Sema/DelayedDiagnostic.h (original)
+++ cfe/trunk/include/clang/Sema/DelayedDiagnostic.h Wed Jul  5 10:08:56
2017
@@ -124,7 +124,8 @@ public:

   static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
                                             SourceLocation Loc,
-                                            const NamedDecl *D,
+                                            const NamedDecl *ReferringDecl,
+                                            const NamedDecl *OffendingDecl,
                                             const ObjCInterfaceDecl
*UnknownObjCClass,
                                             const ObjCPropertyDecl
*ObjCProperty,
                                             StringRef Msg,
@@ -164,9 +165,13 @@ public:
     return *reinterpret_cast<const AccessedEntity*>(AccessData);
   }

-  const NamedDecl *getAvailabilityDecl() const {
+  const NamedDecl *getAvailabilityReferringDecl() const {
     assert(Kind == Availability && "Not an availability diagnostic.");
-    return AvailabilityData.Decl;
+    return AvailabilityData.ReferringDecl;
+  }
+
+  const NamedDecl *getAvailabilityOffendingDecl() const {
+    return AvailabilityData.OffendingDecl;
   }

   StringRef getAvailabilityMessage() const {
@@ -213,7 +218,8 @@ public:
 private:

   struct AD {
-    const NamedDecl *Decl;
+    const NamedDecl *ReferringDecl;
+    const NamedDecl *OffendingDecl;
     const ObjCInterfaceDecl *UnknownObjCClass;
     const ObjCPropertyDecl  *ObjCProperty;
     const char *Message;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
clang/Sema/Sema.h?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jul  5 10:08:56 2017
@@ -3881,7 +3881,9 @@ public:

   void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);

-  void EmitAvailabilityWarning(AvailabilityResult AR, NamedDecl *D,
+  void EmitAvailabilityWarning(AvailabilityResult AR,
+                               const NamedDecl *ReferringDecl,
+                               const NamedDecl *OffendingDecl,
                                StringRef Message, SourceLocation Loc,
                                const ObjCInterfaceDecl *UnknownObjCClass,
                                const ObjCPropertyDecl *ObjCProperty,
@@ -10413,16 +10415,14 @@ public:
     return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
   }

-  /// \brief The diagnostic we should emit for \c D, or \c AR_Available.
-  ///
-  /// \param D The declaration to check. Note that this may be altered to
point
-  /// to another declaration that \c D gets it's availability from. i.e.,
we
-  /// walk the list of typedefs to find an availability attribute.
+  /// The diagnostic we should emit for \c D, and the declaration that
+  /// originated it, or \c AR_Available.
   ///
+  /// \param D The declaration to check.
   /// \param Message If non-null, this will be populated with the message
from
   /// the availability attribute that is selected.
-  AvailabilityResult ShouldDiagnoseAvailabilityOfDecl(NamedDecl *&D,
-                                                      std::string
*Message);
+  std::pair<AvailabilityResult, const NamedDecl *>
+  ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string
*Message);

   const DeclContext *getCurObjCLexicalContext() const {
     const DeclContext *DC = getCurLexicalContext();

Modified: cfe/trunk/lib/Sema/DelayedDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
DelayedDiagnostic.cpp?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/lib/Sema/DelayedDiagnostic.cpp (original)
+++ cfe/trunk/lib/Sema/DelayedDiagnostic.cpp Wed Jul  5 10:08:56 2017
@@ -22,7 +22,8 @@ using namespace sema;
 DelayedDiagnostic
 DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
                                     SourceLocation Loc,
-                                    const NamedDecl *D,
+                                    const NamedDecl *ReferringDecl,
+                                    const NamedDecl *OffendingDecl,
                                     const ObjCInterfaceDecl
*UnknownObjCClass,
                                     const ObjCPropertyDecl  *ObjCProperty,
                                     StringRef Msg,
@@ -31,7 +32,8 @@ DelayedDiagnostic::makeAvailability(Avai
   DD.Kind = Availability;
   DD.Triggered = false;
   DD.Loc = Loc;
-  DD.AvailabilityData.Decl = D;
+  DD.AvailabilityData.ReferringDecl = ReferringDecl;
+  DD.AvailabilityData.OffendingDecl = OffendingDecl;
   DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
   DD.AvailabilityData.ObjCProperty = ObjCProperty;
   char *MessageData = nullptr;

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
SemaDeclAttr.cpp?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Jul  5 10:08:56 2017
@@ -6929,8 +6929,34 @@ shouldDiagnoseAvailabilityByDefault(cons
          DeclVersion >= ForceAvailabilityFromVersion;
 }

+static NamedDecl *findEnclosingDeclToAnnotate(Decl *OrigCtx) {
+  for (Decl *Ctx = OrigCtx; Ctx;
+       Ctx = cast_or_null<Decl>(Ctx->getDeclContext())) {
+    if (isa<TagDecl>(Ctx) || isa<FunctionDecl>(Ctx) ||
isa<ObjCMethodDecl>(Ctx))
+      return cast<NamedDecl>(Ctx);
+    if (auto *CD = dyn_cast<ObjCContainerDecl>(Ctx)) {
+      if (auto *Imp = dyn_cast<ObjCImplDecl>(Ctx))
+        return Imp->getClassInterface();
+      return CD;
+    }
+  }
+
+  return dyn_cast<NamedDecl>(OrigCtx);
+}
+
+/// Actually emit an availability diagnostic for a reference to an
unavailable
+/// decl.
+///
+/// \param Ctx The context that the reference occurred in
+/// \param ReferringDecl The exact declaration that was referenced.
+/// \param OffendingDecl A related decl to \c ReferringDecl that has an
+/// availability attribute corrisponding to \c K attached to it. Note that
this
+/// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated
and
+/// we refer to a member EnumConstantDecl, ReferringDecl is the
EnumConstantDecl
+/// and OffendingDecl is the EnumDecl.
 static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
-                                      Decl *Ctx, const NamedDecl *D,
+                                      Decl *Ctx, const NamedDecl
*ReferringDecl,
+                                      const NamedDecl *OffendingDecl,
                                       StringRef Message, SourceLocation
Loc,
                                       const ObjCInterfaceDecl
*UnknownObjCClass,
                                       const ObjCPropertyDecl *ObjCProperty,
@@ -6938,7 +6964,7 @@ static void DoEmitAvailabilityWarning(Se
   // Diagnostics for deprecated or unavailable.
   unsigned diag, diag_message, diag_fwdclass_message;
   unsigned diag_available_here = diag::note_availability_specified_here;
-  SourceLocation NoteLocation = D->getLocation();
+  SourceLocation NoteLocation = OffendingDecl->getLocation();

   // Matches 'diag::note_property_attribute' options.
   unsigned property_note_select;
@@ -6947,7 +6973,7 @@ static void DoEmitAvailabilityWarning(Se
   unsigned available_here_select_kind;

   VersionTuple DeclVersion;
-  if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, D))
+  if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context,
OffendingDecl))
     DeclVersion = AA->getIntroduced();

   if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
@@ -6961,7 +6987,7 @@ static void DoEmitAvailabilityWarning(Se
     diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
     property_note_select = /* deprecated */ 0;
     available_here_select_kind = /* deprecated */ 2;
-    if (const auto *attr = D->getAttr<DeprecatedAttr>())
+    if (const auto *attr = OffendingDecl->getAttr<DeprecatedAttr>())
       NoteLocation = attr->getLocation();
     break;

@@ -6973,13 +6999,14 @@ static void DoEmitAvailabilityWarning(Se
     property_note_select = /* unavailable */ 1;
     available_here_select_kind = /* unavailable */ 0;

-    if (auto attr = D->getAttr<UnavailableAttr>()) {
+    if (auto attr = OffendingDecl->getAttr<UnavailableAttr>()) {
       if (attr->isImplicit() && attr->getImplicitReason()) {
         // Most of these failures are due to extra restrictions in ARC;
         // reflect that in the primary diagnostic when applicable.
         auto flagARCError = [&] {
           if (S.getLangOpts().ObjCAutoRefCount &&
-              S.getSourceManager().isInSystemHeader(D->getLocation()))
+              S.getSourceManager().isInSystemHeader(
+                  OffendingDecl->getLocation()))
             diag = diag::err_unavailable_in_arc;
         };

@@ -7022,7 +7049,8 @@ static void DoEmitAvailabilityWarning(Se
     // 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);
+    const AvailabilityAttr *AA =
+        getAttrForPlatform(S.getASTContext(), OffendingDecl);
     VersionTuple Introduced = AA->getIntroduced();
     bool NewWarning = shouldDiagnoseAvailabilityByDefault(
         S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
@@ -7045,9 +7073,9 @@ static void DoEmitAvailabilityWarning(Se
   CharSourceRange UseRange;
   StringRef Replacement;
   if (K == AR_Deprecated) {
-    if (auto attr = D->getAttr<DeprecatedAttr>())
+    if (auto attr = OffendingDecl->getAttr<DeprecatedAttr>())
       Replacement = attr->getReplacement();
-    if (auto attr = getAttrForPlatform(S.Context, D))
+    if (auto attr = getAttrForPlatform(S.Context, OffendingDecl))
       Replacement = attr->getReplacement();

     if (!Replacement.empty())
@@ -7056,21 +7084,21 @@ static void DoEmitAvailabilityWarning(Se
   }

   if (!Message.empty()) {
-    S.Diag(Loc, diag_message) << D << Message
+    S.Diag(Loc, diag_message) << ReferringDecl << Message
       << (UseRange.isValid() ?
           FixItHint::CreateReplacement(UseRange, Replacement) :
FixItHint());
     if (ObjCProperty)
       S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
           << ObjCProperty->getDeclName() << property_note_select;
   } else if (!UnknownObjCClass) {
-    S.Diag(Loc, diag) << D
+    S.Diag(Loc, diag) << ReferringDecl
       << (UseRange.isValid() ?
           FixItHint::CreateReplacement(UseRange, Replacement) :
FixItHint());
     if (ObjCProperty)
       S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
           << ObjCProperty->getDeclName() << property_note_select;
   } else {
-    S.Diag(Loc, diag_fwdclass_message) << D
+    S.Diag(Loc, diag_fwdclass_message) << ReferringDecl
       << (UseRange.isValid() ?
           FixItHint::CreateReplacement(UseRange, Replacement) :
FixItHint());
     S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
@@ -7078,16 +7106,16 @@ static void DoEmitAvailabilityWarning(Se

   // The declaration can have multiple availability attributes, we are
looking
   // at one of them.
-  const AvailabilityAttr *A = getAttrForPlatform(S.Context, D);
+  const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
   if (A && A->isInherited()) {
-    for (const Decl *Redecl = D->getMostRecentDecl(); Redecl;
+    for (const Decl *Redecl = OffendingDecl->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
+        S.Diag(Redecl->getLocation(), diag_available_here) << OffendingDecl
             << available_here_select_kind;
         break;
       }
@@ -7095,10 +7123,19 @@ static void DoEmitAvailabilityWarning(Se
   }
   else
     S.Diag(NoteLocation, diag_available_here)
-        << D << available_here_select_kind;
+        << OffendingDecl << available_here_select_kind;

   if (K == AR_NotYetIntroduced)
-    S.Diag(Loc, diag::note_partial_availability_silence) << D;
+    if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
+      if (auto *TD = dyn_cast<TagDecl>(Enclosing))
+        if (TD->getDeclName().isEmpty()) {
+          S.Diag(TD->getLocation(), diag::note_partial_
availability_silence)
+              << /*Anonymous*/1 << TD->getKindName();
+          return;
+        }
+      S.Diag(Enclosing->getLocation(), diag::note_partial_
availability_silence)
+          << /*Named*/0 << Enclosing;
+    }
 }

 static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
@@ -7108,9 +7145,9 @@ static void handleDelayedAvailabilityChe

   DD.Triggered = true;
   DoEmitAvailabilityWarning(
-      S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityDecl(),
-      DD.getAvailabilityMessage(), DD.Loc, DD.getUnknownObjCClass(),
-      DD.getObjCProperty(), false);
+      S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl()
,
+      DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(),
DD.Loc,
+      DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
 }

 void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -7169,22 +7206,25 @@ void Sema::redelayDiagnostics(DelayedDia
 }

 void Sema::EmitAvailabilityWarning(AvailabilityResult AR,
-                                   NamedDecl *D, StringRef Message,
-                                   SourceLocation Loc,
+                                   const NamedDecl *ReferringDecl,
+                                   const NamedDecl *OffendingDecl,
+                                   StringRef Message, SourceLocation Loc,
                                    const ObjCInterfaceDecl
*UnknownObjCClass,
-                                   const ObjCPropertyDecl  *ObjCProperty,
+                                   const ObjCPropertyDecl *ObjCProperty,
                                    bool ObjCPropertyAccess) {
   // Delay if we're currently parsing a declaration.
   if (DelayedDiagnostics.shouldDelayDiagnostics()) {
-    DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
-        AR, Loc, D, UnknownObjCClass, ObjCProperty, Message,
-        ObjCPropertyAccess));
+    DelayedDiagnostics.add(
+        DelayedDiagnostic::makeAvailability(
+            AR, Loc, ReferringDecl, OffendingDecl, UnknownObjCClass,
+            ObjCProperty, Message, ObjCPropertyAccess));
     return;
   }

   Decl *Ctx = cast<Decl>(getCurLexicalContext());
-  DoEmitAvailabilityWarning(*this, AR, Ctx, D, Message, Loc,
UnknownObjCClass,
-                            ObjCProperty, ObjCPropertyAccess);
+  DoEmitAvailabilityWarning(*this, AR, Ctx, ReferringDecl, OffendingDecl,
+                            Message, Loc, UnknownObjCClass, ObjCProperty,
+                            ObjCPropertyAccess);
 }

 namespace {
@@ -7336,19 +7376,21 @@ public:

 void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
     NamedDecl *D, SourceRange Range) {
-
-  VersionTuple ContextVersion = AvailabilityStack.back();
-  if (AvailabilityResult Result =
-          SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr)) {
+  AvailabilityResult Result;
+  const NamedDecl *OffendingDecl;
+  std::tie(Result, OffendingDecl) =
+      SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr);
+  if (Result != AR_Available) {
     // All other diagnostic kinds have already been handled in
     // DiagnoseAvailabilityOfDecl.
     if (Result != AR_NotYetIntroduced)
       return;

-    const AvailabilityAttr *AA = getAttrForPlatform(SemaRef.getASTContext(),
D);
+    const AvailabilityAttr *AA =
+      getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
     VersionTuple Introduced = AA->getIntroduced();

-    if (ContextVersion >= Introduced)
+    if (AvailabilityStack.back() >= Introduced)
       return;

     // If the context of this function is less available than D, we should
not
@@ -7373,8 +7415,9 @@ void DiagnoseUnguardedAvailability::Diag
                SemaRef.getASTContext().getTargetInfo().getPlatformName())
         << Introduced.getAsString();

-    SemaRef.Diag(D->getLocation(), diag::note_availability_specified_here)
-        << D << /* partial */ 3;
+    SemaRef.Diag(OffendingDecl->getLocation(),
+                 diag::note_availability_specified_here)
+        << OffendingDecl << /* partial */ 3;

     auto FixitDiag =
         SemaRef.Diag(Range.getBegin(), diag::note_unguarded_
available_silence)

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
SemaExpr.cpp?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jul  5 10:08:56 2017
@@ -87,24 +87,9 @@ static void DiagnoseUnusedOfDecl(Sema &S
   }
 }

-static bool HasRedeclarationWithoutAvailabilityInCategory(const Decl *D) {
-  const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
-  if (!OMD)
-    return false;
-  const ObjCInterfaceDecl *OID = OMD->getClassInterface();
-  if (!OID)
-    return false;
-
-  for (const ObjCCategoryDecl *Cat : OID->visible_categories())
-    if (ObjCMethodDecl *CatMeth =
-            Cat->getMethod(OMD->getSelector(), OMD->isInstanceMethod()))
-      if (!CatMeth->hasAttr<AvailabilityAttr>())
-        return true;
-  return false;
-}
-
-AvailabilityResult
-Sema::ShouldDiagnoseAvailabilityOfDecl(NamedDecl *&D, std::string
*Message) {
+std::pair<AvailabilityResult, const NamedDecl *>
+Sema::ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D,
+                                       std::string *Message) {
   AvailabilityResult Result = D->getAvailability(Message);

   // For typedefs, if the typedef declaration appears available look
@@ -121,45 +106,23 @@ Sema::ShouldDiagnoseAvailabilityOfDecl(N
   }

   // Forward class declarations get their attributes from their definition.
-  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
+  if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
     if (IDecl->getDefinition()) {
       D = IDecl->getDefinition();
       Result = D->getAvailability(Message);
     }
   }

-  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
+  if (const auto *ECD = dyn_cast<EnumConstantDecl>(D))
     if (Result == AR_Available) {
       const DeclContext *DC = ECD->getDeclContext();
-      if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC))
+      if (const auto *TheEnumDecl = dyn_cast<EnumDecl>(DC)) {
         Result = TheEnumDecl->getAvailability(Message);
+        D = TheEnumDecl;
+      }
     }

-  if (Result == AR_NotYetIntroduced) {
-    // Don't do this for enums, they can't be redeclared.
-    if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D))
-      return AR_Available;
-
-    bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited();
-    // Objective-C method declarations in categories are not modelled as
-    // redeclarations, so manually look for a redeclaration in a category
-    // if necessary.
-    if (Warn && HasRedeclarationWithoutAvailabilityInCategory(D))
-      Warn = false;
-    // In general, D will point to the most recent redeclaration. However,
-    // for `@class A;` decls, this isn't true -- manually go through the
-    // redecl chain in that case.
-    if (Warn && isa<ObjCInterfaceDecl>(D))
-      for (Decl *Redecl = D->getMostRecentDecl(); Redecl && Warn;
-           Redecl = Redecl->getPreviousDecl())
-        if (!Redecl->hasAttr<AvailabilityAttr>() ||
-            Redecl->getAttr<AvailabilityAttr>()->isInherited())
-          Warn = false;
-
-    return Warn ? AR_NotYetIntroduced : AR_Available;
-  }
-
-  return Result;
+  return {Result, D};
 }

 static void
@@ -167,32 +130,34 @@ DiagnoseAvailabilityOfDecl(Sema &S, Name
                            const ObjCInterfaceDecl *UnknownObjCClass,
                            bool ObjCPropertyAccess) {
   std::string Message;
+  AvailabilityResult Result;
+  const NamedDecl* OffendingDecl;
   // See if this declaration is unavailable, deprecated, or partial.
-  if (AvailabilityResult Result =
-          S.ShouldDiagnoseAvailabilityOfDecl(D, &Message)) {
+  std::tie(Result, OffendingDecl) = S.ShouldDiagnoseAvailabilityOfDecl(D,
&Message);
+  if (Result == AR_Available)
+    return;

-    if (Result == AR_NotYetIntroduced) {
-      if (S.getCurFunctionOrMethodDecl()) {
-        S.getEnclosingFunction()->HasPotentialAvailabilityViolations =
true;
-        return;
-      } else if (S.getCurBlock() || S.getCurLambda()) {
-        S.getCurFunction()->HasPotentialAvailabilityViolations = true;
-        return;
-      }
+  if (Result == AR_NotYetIntroduced) {
+    if (S.getCurFunctionOrMethodDecl()) {
+      S.getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
+      return;
+    } else if (S.getCurBlock() || S.getCurLambda()) {
+      S.getCurFunction()->HasPotentialAvailabilityViolations = true;
+      return;
     }
+  }

-    const ObjCPropertyDecl *ObjCPDecl = nullptr;
-    if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
-      if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
-        AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
-        if (PDeclResult == Result)
-          ObjCPDecl = PD;
-      }
+  const ObjCPropertyDecl *ObjCPDecl = nullptr;
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
+      AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
+      if (PDeclResult == Result)
+        ObjCPDecl = PD;
     }
-
-    S.EmitAvailabilityWarning(Result, D, Message, Loc, UnknownObjCClass,
-                              ObjCPDecl, ObjCPropertyAccess);
   }
+
+  S.EmitAvailabilityWarning(Result, D, OffendingDecl, Message, Loc,
+                            UnknownObjCClass, ObjCPDecl,
ObjCPropertyAccess);
 }

 /// \brief Emit a note explaining that this function is deleted.

Modified: cfe/trunk/test/Sema/attr-availability.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/
attr-availability.c?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/Sema/attr-availability.c (original)
+++ cfe/trunk/test/Sema/attr-availability.c Wed Jul  5 10:08:56 2017
@@ -21,6 +21,9 @@ ATSFontGetPostScriptName(int flags) __at
 extern void
 PartiallyAvailable() __attribute__((availability(macosx,introduced=10.8)));

+#ifdef WARN_PARTIAL
+// expected-note at +2 2 {{marked partial here}}
+#endif
 enum __attribute__((availability(macosx,introduced=10.8))) PartialEnum {
   kPartialEnumConstant,
 };
@@ -35,11 +38,19 @@ void test_10095131() {
   PartiallyAvailable();
 }

+#ifdef WARN_PARTIAL
+// FIXME: This note should point to the declaration with the availability
+// attribute.
+// expected-note at +2 {{marked partial here}}
+#endif
 extern void PartiallyAvailable() ;
 void with_redeclaration() {
-  PartiallyAvailable();  // Don't warn.
-
-  // enums should never warn.
+#ifdef WARN_PARTIAL
+  // expected-warning at +4 {{'PartiallyAvailable' is only available on macOS
10.8 or newer}} expected-note at +4 {{__builtin_available}}
+  // expected-warning at +4 {{'PartialEnum' is only available on macOS 10.8
or newer}} expected-note at +4 {{__builtin_available}}
+  // expected-warning at +3 {{'kPartialEnumConstant' is only available on
macOS 10.8 or newer}} expected-note at +3 {{__builtin_available}}
+#endif
+  PartiallyAvailable();
   enum PartialEnum p = kPartialEnumConstant;
 }

@@ -86,13 +97,13 @@ enum Original {
   OriginalUnavailable __attribute__((availability(macosx, unavailable)))
// expected-note + {{'OriginalUnavailable' has been explicitly marked
unavailable here}}
 };

-enum AllDeprecated {
-  AllDeprecatedCase, // expected-note + {{'AllDeprecatedCase' has been
explicitly marked deprecated here}}
+enum AllDeprecated { // expected-note + {{'AllDeprecated' has been
explicitly marked deprecated here}}
+  AllDeprecatedCase,
   AllDeprecatedUnavailable __attribute__((availability(macosx,
unavailable))) // expected-note + {{'AllDeprecatedUnavailable' has been
explicitly marked unavailable here}}
 } __attribute__((availability(macosx, deprecated=10.2)));

-enum AllUnavailable {
-  AllUnavailableCase, // expected-note + {{'AllUnavailableCase' has been
explicitly marked unavailable here}}
+enum AllUnavailable { // expected-note + {{'AllUnavailable' has been
explicitly marked unavailable here}}
+  AllUnavailableCase,
 } __attribute__((availability(macosx, unavailable)));

 enum User {

Modified: cfe/trunk/test/Sema/attr-deprecated.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/
attr-deprecated.c?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/Sema/attr-deprecated.c (original)
+++ cfe/trunk/test/Sema/attr-deprecated.c Wed Jul  5 10:08:56 2017
@@ -104,9 +104,9 @@ foo_dep test17, // expected-warning {{'f
         test19;

 // rdar://problem/8518751
-enum __attribute__((deprecated)) Test20 { // expected-note {{'Test20' has
been explicitly marked deprecated here}}
+enum __attribute__((deprecated)) Test20 { // expected-note 2 {{'Test20'
has been explicitly marked deprecated here}}
   test20_a __attribute__((deprecated)), // expected-note {{'test20_a' has
been explicitly marked deprecated here}}
-  test20_b // expected-note {{'test20_b' has been explicitly marked
deprecated here}}
+  test20_b
 };
 void test20() {
   enum Test20 f; // expected-warning {{'Test20' is deprecated}}

Modified: cfe/trunk/test/Sema/attr-unavailable-message.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/
attr-unavailable-message.c?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/Sema/attr-unavailable-message.c (original)
+++ cfe/trunk/test/Sema/attr-unavailable-message.c Wed Jul  5 10:08:56 2017
@@ -36,13 +36,13 @@ void unavail(void) {

 // rdar://10201690
 enum foo {
-    a = 1, // expected-note {{'a' has been explicitly marked deprecated
here}}
+    a = 1,
     b __attribute__((deprecated())) = 2, // expected-note {{'b' has been
explicitly marked deprecated here}}
     c = 3
-}__attribute__((deprecated()));
+}__attribute__((deprecated())); // expected-note {{'foo' has been
explicitly marked deprecated here}}

-enum fee { // expected-note {{'fee' has been explicitly marked unavailable
here}}
-    r = 1, // expected-note {{'r' has been explicitly marked unavailable
here}}
+enum fee { // expected-note 2 {{'fee' has been explicitly marked
unavailable here}}
+    r = 1,
     s = 2,
     t = 3
 }__attribute__((unavailable()));

Modified: cfe/trunk/test/SemaCXX/attr-deprecated.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
SemaCXX/attr-deprecated.cpp?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/SemaCXX/attr-deprecated.cpp (original)
+++ cfe/trunk/test/SemaCXX/attr-deprecated.cpp Wed Jul  5 10:08:56 2017
@@ -199,8 +199,8 @@ namespace test5 {

 // rdar://problem/8518751
 namespace test6 {
-  enum __attribute__((deprecated)) A { // expected-note {{'A' has been
explicitly marked deprecated here}}
-    a0 // expected-note {{'a0' has been explicitly marked deprecated here}}
+  enum __attribute__((deprecated)) A { // expected-note 2 {{'A' has been
explicitly marked deprecated here}}
+    a0
   };
   void testA() {
     A x; // expected-warning {{'A' is deprecated}}
@@ -218,8 +218,8 @@ namespace test6 {
   }

   template <class T> struct C {
-    enum __attribute__((deprecated)) Enum { // expected-note {{'Enum' has
been explicitly marked deprecated here}}
-      c0 // expected-note {{'c0' has been explicitly marked deprecated
here}}
+    enum __attribute__((deprecated)) Enum { // expected-note 2 {{'Enum'
has been explicitly marked deprecated here}}
+      c0
     };
   };
   void testC() {

Modified: cfe/trunk/test/SemaObjC/attr-availability.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
SemaObjC/attr-availability.m?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/SemaObjC/attr-availability.m (original)
+++ cfe/trunk/test/SemaObjC/attr-availability.m Wed Jul  5 10:08:56 2017
@@ -13,7 +13,7 @@
 @interface A <P>
 - (void)method
__attribute__((availability(macosx,introduced=10.1,deprecated=10.2)));
// expected-note {{'method' has been explicitly marked deprecated here}}
 #if defined(WARN_PARTIAL)
-  // expected-note at +2 {{'partialMethod' has been explicitly marked partial
here}}
+  // expected-note at +2 2 {{'partialMethod' has been explicitly marked
partial here}}
 #endif
 - (void)partialMethod __attribute__((availability(
macosx,introduced=10.8)));

@@ -66,7 +66,10 @@ void f(A *a, B *b) {
 @end

 void f_after_redecl(A *a, B *b) {
-  [a partialMethod]; // no warning
+#ifdef WARN_PARTIAL
+  // expected-warning at +2{{'partialMethod' is only available on macOS 10.8
or newer}} expected-note at +2 {{@available}}
+#endif
+  [a partialMethod];
   [b partialMethod]; // no warning
   [a partial_proto_method]; // no warning
   [b partial_proto_method]; // no warning
@@ -133,6 +136,10 @@ id NSNibOwner, topNibObjects;
 @end

 @interface PartialI <PartialProt>
+#ifdef WARN_PARTIAL
+// expected-note at +3{{marked partial here}}
+// expected-note at +3{{marked partial here}}
+#endif
 - (void)partialMethod __attribute__((availability(
macosx,introduced=10.8)));
 + (void)partialMethod __attribute__((availability(
macosx,introduced=10.8)));
 @end
@@ -160,14 +167,20 @@ id NSNibOwner, topNibObjects;
 @end

 void partialfun(PartialI* a) {
-  [a partialMethod]; // no warning
+#ifdef WARN_PARTIAL
+  // expected-warning at +2 {{'partialMethod' is only available on macOS 10.8
or newer}} expected-note at +2{{@available}}
+#endif
+  [a partialMethod];
   [a ipartialMethod1]; // no warning
 #if defined(WARN_PARTIAL)
   // expected-warning at +2 {{'ipartialMethod2' is only available on macOS
10.8 or newer}} expected-note at +2 {{enclose 'ipartialMethod2' in an
@available check to silence this warning}}
 #endif
   [a ipartialMethod2];
   [a ppartialMethod]; // no warning
-  [PartialI partialMethod]; // no warning
+#ifdef WARN_PARTIAL
+  // expected-warning at +2 {{'partialMethod' is only available on macOS 10.8
or newer}} expected-note at +2 {{@available}}
+#endif
+  [PartialI partialMethod];
   [PartialI ipartialMethod1]; // no warning
 #if defined(WARN_PARTIAL)
   // expected-warning at +2 {{'ipartialMethod2' is only available on macOS
10.8 or newer}} expected-note at +2 {{enclose 'ipartialMethod2' in an
@available check to silence this warning}}
@@ -177,20 +190,23 @@ void partialfun(PartialI* a) {
 }

 #if defined(WARN_PARTIAL)
-  // expected-note at +2 {{'PartialI2' has been explicitly marked partial
here}}
+  // expected-note at +2 2 {{'PartialI2' has been explicitly marked partial
here}}
 #endif
 __attribute__((availability(macosx, introduced = 10.8))) @interface
PartialI2
 @end

 #if defined(WARN_PARTIAL)
-  // expected-warning at +2 {{'PartialI2' is partial: introduced in macOS
10.8}} expected-note at +2 {{explicitly redeclare 'PartialI2' to silence this
warning}}
+// expected-warning at +2 {{'PartialI2' is partial: introduced in macOS
10.8}} expected-note at +2 {{annotate 'partialinter1' with an availability
attribute to silence}}
 #endif
 void partialinter1(PartialI2* p) {
 }

 @class PartialI2;

-void partialinter2(PartialI2* p) { // no warning
+#ifdef WARN_PARTIAL
+// expected-warning at +2 {{'PartialI2' is partial: introduced in macOS
10.8}} expected-note at +2 {{annotate 'partialinter2' with an availability
attribute to silence}}
+#endif
+void partialinter2(PartialI2* p) {
 }



Modified: cfe/trunk/test/SemaObjC/unguarded-availability-new.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/unguarded-
availability-new.m?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/SemaObjC/unguarded-availability-new.m (original)
+++ cfe/trunk/test/SemaObjC/unguarded-availability-new.m Wed Jul  5
10:08:56 2017
@@ -96,16 +96,16 @@ typedef int AVAILABLE_NEXT new_int;
 FUNC_AVAILABLE new_int x;
 #ifndef NO_WARNING
 #ifdef MAC
-  // expected-warning at -3 {{'new_int' is partial: introduced in macOS
10.14}} expected-note at -3 {{explicitly redeclare 'new_int' to silence this
warning}}
+  // expected-warning at -3 {{'new_int' is partial: introduced in macOS
10.14}} expected-note at -3 {{annotate 'x' with an availability attribute to
silence}}
 #endif
 #ifdef IOS
-  // expected-warning at -6 {{'new_int' is partial: introduced in iOS 12}}
expected-note at -6 {{explicitly redeclare 'new_int' to silence this warning}}
+  // expected-warning at -6 {{'new_int' is partial: introduced in iOS 12}}
expected-note at -6 {{annotate 'x' with an availability attribute to silence}}
 #endif
 #ifdef TVOS
-  // expected-warning at -9 {{'new_int' is partial: introduced in tvOS 13}}
expected-note at -9 {{explicitly redeclare 'new_int' to silence this warning}}
+  // expected-warning at -9 {{'new_int' is partial: introduced in tvOS 13}}
expected-note at -9 {{annotate 'x' with an availability attribute to silence}}
 #endif
 #ifdef WATCHOS
-  // expected-warning at -12 {{'new_int' is partial: introduced in watchOS
5}} expected-note at -12 {{explicitly redeclare 'new_int' to silence this
warning}}
+  // expected-warning at -12 {{'new_int' is partial: introduced in watchOS
5}} expected-note at -12 {{annotate 'x' with an availability attribute to
silence}}
 #endif
 #endif


Modified: cfe/trunk/test/SemaObjC/unguarded-availability.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/unguarded-
availability.m?rev=307175&r1=307174&r2=307175&view=diff
============================================================
==================
--- cfe/trunk/test/SemaObjC/unguarded-availability.m (original)
+++ cfe/trunk/test/SemaObjC/unguarded-availability.m Wed Jul  5 10:08:56
2017
@@ -5,6 +5,8 @@
 #define AVAILABLE_10_11 __attribute__((availability(macos, introduced =
10.11)))
 #define AVAILABLE_10_12 __attribute__((availability(macos, introduced =
10.12)))

+typedef int AVAILABLE_10_12 new_int; // expected-note + {{marked partial
here}}
+
 int func_10_11() AVAILABLE_10_11; // expected-note 4 {{'func_10_11' has
been explicitly marked partial here}}

 #ifdef OBJCPP
@@ -70,9 +72,9 @@ void use_typedef() {
 }

 __attribute__((objc_root_class))
-AVAILABLE_10_11 @interface Class_10_11 {
+AVAILABLE_10_11 @interface Class_10_11 { // expected-note{{annotate
'Class_10_11' with an availability attribute to silence}}
   int_10_11 foo;
-  int_10_12 bar; // expected-warning {{'int_10_12' is partial: introduced
in macOS 10.12}} expected-note{{redeclare}}
+  int_10_12 bar; // expected-warning {{'int_10_12' is partial: introduced
in macOS 10.12}}
 }
 - (void)method1;
 - (void)method2;
@@ -125,7 +127,7 @@ void test_blocks() {
   };
 }

-void test_params(int_10_12 x); // expected-warning {{'int_10_12' is
partial: introduced in macOS 10.12}} expected-note{{redeclare}}
+void test_params(int_10_12 x); // expected-warning {{'int_10_12' is
partial: introduced in macOS 10.12}} expected-note{{annotate 'test_params'
with an availability attribute to silence}}

 void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn

@@ -234,3 +236,30 @@ void functionInFunction() {
 }

 #endif
+
+struct InStruct { // expected-note{{annotate 'InStruct' with an
availability attribute to silence}}
+  new_int mem; // expected-warning{{'new_int' is partial}}
+
+  struct { new_int mem; } anon; // expected-warning{{'new_int' is
partial}} expected-note{{annotate anonymous struct with an availability
attribute}}
+};
+
+#ifdef OBJCPP
+static constexpr int AVAILABLE_10_12 SomeConstexprValue = 2; //
expected-note{{marked partial here}}
+typedef enum { // expected-note{{annotate anonymous enum with an
availability attribute}}
+  SomeValue = SomeConstexprValue // expected-warning{{'SomeConstexprValue'
is partial}}
+} SomeEnum;
+#endif
+
+ at interface InInterface
+-(new_int)meth; // expected-warning{{'new_int' is partial}}
expected-note{{annotate 'meth' with an availability attribute}}
+ at end
+
+ at interface Proper // expected-note{{annotate 'Proper' with an availability
attribute}}
+ at property (class) new_int x; // expected-warning{{'new_int' is partial}}
+ at end
+
+void with_local_struct() {
+  struct local { // expected-note{{annotate 'local' with an availability
attribute}}
+    new_int x; // expected-warning{{'new_int' is partial}}
+  };
+}


_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170706/ab11e646/attachment-0001.html>


More information about the cfe-commits mailing list