summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp39
1 files changed, 38 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 32244e9e195..a9cc0d61be9 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -3167,6 +3167,26 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
return true;
}
+static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodInList) {
+ auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());
+ auto *MethodInListProtocol =
+ dyn_cast<ObjCProtocolDecl>(MethodInList->getDeclContext());
+ // If this method belongs to a protocol but the method in list does not, or
+ // vice versa, we say the context is not the same.
+ if ((MethodProtocol && !MethodInListProtocol) ||
+ (!MethodProtocol && MethodInListProtocol))
+ return false;
+
+ if (MethodProtocol && MethodInListProtocol)
+ return true;
+
+ ObjCInterfaceDecl *MethodInterface = Method->getClassInterface();
+ ObjCInterfaceDecl *MethodInListInterface =
+ MethodInList->getClassInterface();
+ return MethodInterface == MethodInListInterface;
+}
+
void Sema::addMethodToGlobalList(ObjCMethodList *List,
ObjCMethodDecl *Method) {
// Record at the head of the list whether there were 0, 1, or >= 2 methods
@@ -3185,13 +3205,17 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List,
// We've seen a method with this name, see if we have already seen this type
// signature.
+ ObjCMethodList *Head = List;
ObjCMethodList *Previous = List;
for (; List; Previous = List, List = List->getNext()) {
// If we are building a module, keep all of the methods.
if (getLangOpts().CompilingModule)
continue;
- if (!MatchTwoMethodDeclarations(Method, List->getMethod())) {
+ // Looking for method with a type bound requires the correct context exists.
+ // We need to insert this method into the list if the context is different.
+ if (!MatchTwoMethodDeclarations(Method, List->getMethod()) ||
+ !isMethodContextSameForKindofLookup(Method, List->getMethod())) {
// Even if two method types do not match, we would like to say
// there is more than one declaration so unavailability/deprecated
// warning is not too noisy.
@@ -3232,6 +3256,19 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List,
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+
+ // We tried to prioritize the list by putting deprecated and unavailable
+ // methods in the front.
+ if ((Method->isDeprecated() && !Head->getMethod()->isDeprecated()) ||
+ (Method->isUnavailable() &&
+ Head->getMethod()->getAvailability() < AR_Deprecated)) {
+ auto *List = new (Mem) ObjCMethodList(*Head);
+ // FIXME: should we clear the other bits in Head?
+ Head->setMethod(Method);
+ Head->setNext(List);
+ return;
+ }
+
Previous->setNext(new (Mem) ObjCMethodList(Method));
}
OpenPOWER on IntegriCloud