diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 39 |
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)); } |