diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 42 | ||||
-rw-r--r-- | clang/test/SemaObjC/kindof.m | 13 | ||||
-rw-r--r-- | clang/test/SemaObjC/multiple-method-names.m | 4 |
3 files changed, 45 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 58ee123688d..8090bec4fab 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3213,22 +3213,43 @@ 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; + ObjCMethodList *ListWithSameDeclaration = nullptr; for (; List; Previous = List, List = List->getNext()) { // If we are building a module, keep all of the methods. if (getLangOpts().CompilingModule) continue; + bool SameDeclaration = 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()) || + // We need to insert a method into the list if the context is different. + // If the method's declaration matches the list + // a> the method belongs to a different context: we need to insert it, in + // order to emit the availability message, we need to prioritize over + // availability among the methods with the same declaration. + // b> the method belongs to the same context: there is no need to insert a + // new entry. + // If the method's declaration does not match the list, we insert it to the + // end. + if (!SameDeclaration || !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. if (!Method->isDefined()) List->setHasMoreThanOneDecl(true); + + // For methods with the same declaration, the one that is deprecated + // should be put in the front for better diagnostics. + if (Method->isDeprecated() && SameDeclaration && + !ListWithSameDeclaration && !List->getMethod()->isDeprecated()) + ListWithSameDeclaration = List; + + if (Method->isUnavailable() && SameDeclaration && + !ListWithSameDeclaration && + List->getMethod()->getAvailability() < AR_Deprecated) + ListWithSameDeclaration = List; continue; } @@ -3265,15 +3286,12 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, // 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); + // We insert it right before ListWithSameDeclaration. + if (ListWithSameDeclaration) { + auto *List = new (Mem) ObjCMethodList(*ListWithSameDeclaration); + // FIXME: should we clear the other bits in ListWithSameDeclaration? + ListWithSameDeclaration->setMethod(Method); + ListWithSameDeclaration->setNext(List); return; } diff --git a/clang/test/SemaObjC/kindof.m b/clang/test/SemaObjC/kindof.m index 95c7f993d17..919ca960a9d 100644 --- a/clang/test/SemaObjC/kindof.m +++ b/clang/test/SemaObjC/kindof.m @@ -25,6 +25,7 @@ __attribute__((objc_root_class)) @end @interface NSString : NSObject <NSCopying> // expected-note{{receiver is instance of class declared here}} +- (void)compare:(NSString *)string; - (NSString *)stringByAppendingString:(NSString *)string; + (instancetype)string; @end @@ -289,6 +290,18 @@ void foo() { } } +typedef const struct CGPath *CGPathRef; +@interface C : NSObject +@property (copy) NSString *path; +@end +@interface D : NSObject +@property CGPathRef path __attribute__((availability(macosx,unavailable))); +@end +// Make sure we choose "NSString *path" for [s1 path]. +void bar(id s1, id s2) { + return [[s1 path] compare:[s2 path]]; +} + // --------------------------------------------------------------------------- // __kindof within specialized types // --------------------------------------------------------------------------- diff --git a/clang/test/SemaObjC/multiple-method-names.m b/clang/test/SemaObjC/multiple-method-names.m index a8707904b56..9fd83b208ab 100644 --- a/clang/test/SemaObjC/multiple-method-names.m +++ b/clang/test/SemaObjC/multiple-method-names.m @@ -2,11 +2,11 @@ // PR22047 @interface Face0 -- (void)foo:(float)i; // expected-note {{also found}} +- (void)foo:(float)i; // expected-note {{using}} @end @interface Face1 -- (void)foo:(int)i __attribute__((unavailable)); // expected-note {{using}} +- (void)foo:(int)i __attribute__((unavailable)); @end @interface Face2 |