summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorManman Ren <manman.ren@gmail.com>2016-05-06 19:57:16 +0000
committerManman Ren <manman.ren@gmail.com>2016-05-06 19:57:16 +0000
commit45b1ab11b7aae8b9877071b4e79aeb8dd7ac99af (patch)
tree47a51d842bdec0485af7b32ad6f95b9ac4c276a6 /clang/lib/Sema/SemaDeclAttr.cpp
parent72315ab4e4a290ab33a4100fa5ad03109bf8e204 (diff)
downloadbcm5719-llvm-45b1ab11b7aae8b9877071b4e79aeb8dd7ac99af.tar.gz
bcm5719-llvm-45b1ab11b7aae8b9877071b4e79aeb8dd7ac99af.zip
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 llvm-svn: 268786
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp53
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;
}
OpenPOWER on IntegriCloud