diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index fed76aecdaa2a6..ca70afd9db2530 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -958,10 +958,18 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { auto *CtxD = cast(getDeclContext()); if (auto *ImplD = dyn_cast(CtxD)) { - if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) + if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) { if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(), isInstanceMethod())) return MD; + // readwrite properties may have been re-declared in an extension. + // look harder. + if (isPropertyAccessor()) + for (auto *Ext : IFD->known_extensions()) + if (ObjCMethodDecl *MD = + Ext->getMethod(getSelector(), isInstanceMethod())) + return MD; + } } else if (auto *CImplD = dyn_cast(CtxD)) { if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(), diff --git a/clang/test/CodeGenObjC/direct-method.m b/clang/test/CodeGenObjC/direct-method.m index 373bd22a84cddf..c42910c1676a26 100644 --- a/clang/test/CodeGenObjC/direct-method.m +++ b/clang/test/CodeGenObjC/direct-method.m @@ -191,6 +191,14 @@ int useRoot(Root *r) { return [r getInt] + [r intProperty] + [r intProperty2]; } +int useFoo(Foo *f) { + // CHECK-LABEL: define i32 @useFoo + // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]" + // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]" + [f setGetDynamic_setDirect:1]; + return [f getDirect_setDynamic]; +} + __attribute__((objc_root_class)) @interface RootDeclOnly @property(direct, readonly) int intProperty;