summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp53
-rw-r--r--clang/test/Sema/attr-availability-macosx.c11
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;
+}
OpenPOWER on IntegriCloud