diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index cbc95dc643d..e0272a0eb63 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -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(Sema &S, Sema::AvailabilityDiagnostic K, 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(Sema &S, Sema::AvailabilityDiagnostic K, 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; } |

