diff options
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 53 | ||||
-rw-r--r-- | clang/test/Sema/attr-availability-macosx.c | 11 |
2 files changed, 61 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; } diff --git a/clang/test/Sema/attr-availability-macosx.c b/clang/test/Sema/attr-availability-macosx.c index 21a79ff17a1..6991f14d950 100644 --- a/clang/test/Sema/attr-availability-macosx.c +++ b/clang/test/Sema/attr-availability-macosx.c @@ -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; +} |