summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2018-09-10 22:20:09 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2018-09-10 22:20:09 +0000
commit04c9c6990ba088f1a07e4acce1faf91ce5adb1b1 (patch)
tree0f6bcd0724533531535a9408f3af7bf5ef445a99 /lib/Sema/SemaDeclAttr.cpp
parentfc73f1c46418634a9db66da860c9ce1ee57363f9 (diff)
downloadclang-04c9c6990ba088f1a07e4acce1faf91ce5adb1b1.tar.gz
[Sema][ObjC] Infer availability of +new from availability of -init.
When defined in NSObject, +new will call -init. If -init has been marked unavailable, diagnose uses of +new. rdar://18335828 Differential revision: https://reviews.llvm.org/D51189 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341874 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--lib/Sema/SemaDeclAttr.cpp43
1 files changed, 35 insertions, 8 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index db5df4db80..b58976a729 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -6967,8 +6967,12 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
/// \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.
+/// \param ClassReceiver If we're checking the the method of a class message
+/// send, the class. Otherwise nullptr.
static std::pair<AvailabilityResult, const NamedDecl *>
-ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
+ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D,
+ std::string *Message,
+ ObjCInterfaceDecl *ClassReceiver) {
AvailabilityResult Result = D->getAvailability(Message);
// For typedefs, if the typedef declaration appears available look
@@ -7001,6 +7005,20 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
}
}
+ // For +new, infer availability from -init.
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (S.NSAPIObj && ClassReceiver) {
+ ObjCMethodDecl *Init = ClassReceiver->lookupInstanceMethod(
+ S.NSAPIObj->getInitSelector());
+ if (Init && Result == AR_Available && MD->isClassMethod() &&
+ MD->getSelector() == S.NSAPIObj->getNewSelector() &&
+ MD->definedInNSObject(S.getASTContext())) {
+ Result = Init->getAvailability(Message);
+ D = Init;
+ }
+ }
+ }
+
return {Result, D};
}
@@ -7589,7 +7607,8 @@ class DiagnoseUnguardedAvailability
SmallVector<VersionTuple, 8> AvailabilityStack;
SmallVector<const Stmt *, 16> StmtStack;
- void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range);
+ void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range,
+ ObjCInterfaceDecl *ClassReceiver = nullptr);
public:
DiagnoseUnguardedAvailability(Sema &SemaRef, Decl *Ctx)
@@ -7631,9 +7650,15 @@ public:
}
bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
- if (ObjCMethodDecl *D = Msg->getMethodDecl())
+ if (ObjCMethodDecl *D = Msg->getMethodDecl()) {
+ ObjCInterfaceDecl *ID = nullptr;
+ QualType ReceiverTy = Msg->getClassReceiver();
+ if (!ReceiverTy.isNull() && ReceiverTy->getAsObjCInterfaceType())
+ ID = ReceiverTy->getAsObjCInterfaceType()->getInterface();
+
DiagnoseDeclAvailability(
- D, SourceRange(Msg->getSelectorStartLoc(), Msg->getEndLoc()));
+ D, SourceRange(Msg->getSelectorStartLoc(), Msg->getEndLoc()), ID);
+ }
return true;
}
@@ -7659,11 +7684,11 @@ public:
};
void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
- NamedDecl *D, SourceRange Range) {
+ NamedDecl *D, SourceRange Range, ObjCInterfaceDecl *ReceiverClass) {
AvailabilityResult Result;
const NamedDecl *OffendingDecl;
std::tie(Result, OffendingDecl) =
- ShouldDiagnoseAvailabilityOfDecl(D, nullptr);
+ ShouldDiagnoseAvailabilityOfDecl(SemaRef, D, nullptr, ReceiverClass);
if (Result != AR_Available) {
// All other diagnostic kinds have already been handled in
// DiagnoseAvailabilityOfDecl.
@@ -7845,12 +7870,14 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
- bool AvoidPartialAvailabilityChecks) {
+ bool AvoidPartialAvailabilityChecks,
+ ObjCInterfaceDecl *ClassReceiver) {
std::string Message;
AvailabilityResult Result;
const NamedDecl* OffendingDecl;
// See if this declaration is unavailable, deprecated, or partial.
- std::tie(Result, OffendingDecl) = ShouldDiagnoseAvailabilityOfDecl(D, &Message);
+ std::tie(Result, OffendingDecl) =
+ ShouldDiagnoseAvailabilityOfDecl(*this, D, &Message, ClassReceiver);
if (Result == AR_Available)
return;