diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -958,10 +958,18 @@ 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 --- a/clang/test/CodeGenObjC/direct-method.m +++ b/clang/test/CodeGenObjC/direct-method.m @@ -191,6 +191,14 @@ 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;