From: Fariborz Jahanian Date: Fri, 4 Oct 2013 18:06:08 +0000 (+0000) Subject: ObjectiveC. Allow readonly properties without an explicit ownership X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1cd6fab3930d5c058c201895654c6b0bd6ecb8c1;p=clang ObjectiveC. Allow readonly properties without an explicit ownership (assign/unsafe_unretained/weak/retain/strong/copy) in super class to be overridden by a property with any explicit ownership in the subclass. // rdar://15014468 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191971 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a7df4365b5..f0dd57fa8b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6645,7 +6645,8 @@ public: void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, - const IdentifierInfo *Name); + const IdentifierInfo *Name, + bool OverridingProtocolProperty); void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, ObjCInterfaceDecl *ID); diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index cd5be5e35d..5323ad47ca 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -126,7 +126,7 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName()); for (unsigned I = 0, N = R.size(); I != N; ++I) { if (ObjCPropertyDecl *ProtoProp = dyn_cast(R[I])) { - S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier()); + S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true); return; } } @@ -208,7 +208,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, DeclContext::lookup_result R = Super->lookup(Res->getDeclName()); for (unsigned I = 0, N = R.size(); I != N; ++I) { if (ObjCPropertyDecl *SuperProp = dyn_cast(R[I])) { - DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier()); + DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false); FoundInSuper = true; break; } @@ -1353,31 +1353,41 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, void Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, - const IdentifierInfo *inheritedName) { + const IdentifierInfo *inheritedName, + bool OverridingProtocolProperty) { ObjCPropertyDecl::PropertyAttributeKind CAttr = - Property->getPropertyAttributes(); + Property->getPropertyAttributes(); ObjCPropertyDecl::PropertyAttributeKind SAttr = - SuperProperty->getPropertyAttributes(); - if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) - && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) - Diag(Property->getLocation(), diag::warn_readonly_property) - << Property->getDeclName() << inheritedName; - if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) - != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) - Diag(Property->getLocation(), diag::warn_property_attribute) - << Property->getDeclName() << "copy" << inheritedName; - else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ - unsigned CAttrRetain = - (CAttr & - (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); - unsigned SAttrRetain = - (SAttr & - (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); - bool CStrong = (CAttrRetain != 0); - bool SStrong = (SAttrRetain != 0); - if (CStrong != SStrong) + SuperProperty->getPropertyAttributes(); + + // We allow readonly properties without an explicit ownership + // (assign/unsafe_unretained/weak/retain/strong/copy) in super class + // to be overridden by a property with any explicit ownership in the subclass. + if (!OverridingProtocolProperty && + !getOwnershipRule(SAttr) && getOwnershipRule(CAttr)) + ; + else { + if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) + && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) + Diag(Property->getLocation(), diag::warn_readonly_property) + << Property->getDeclName() << inheritedName; + if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) + != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) Diag(Property->getLocation(), diag::warn_property_attribute) - << Property->getDeclName() << "retain (or strong)" << inheritedName; + << Property->getDeclName() << "copy" << inheritedName; + else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ + unsigned CAttrRetain = + (CAttr & + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); + unsigned SAttrRetain = + (SAttr & + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); + bool CStrong = (CAttrRetain != 0); + bool SStrong = (SAttrRetain != 0); + if (CStrong != SStrong) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "retain (or strong)" << inheritedName; + } } if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) diff --git a/test/SemaObjC/property-ownership-attr.m b/test/SemaObjC/property-ownership-attr.m new file mode 100644 index 0000000000..f83c560acb --- /dev/null +++ b/test/SemaObjC/property-ownership-attr.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://15014468 + +@protocol P + @property(readonly) id z; +@end + +@interface Foo + @property (readonly) id x; +@end + +@interface MutableFoo : Foo + @property (copy) id x; +@end + +@interface Foo (Cat)

+@property (copy) id z; // expected-warning {{'copy' attribute on property 'z' does not match the property inherited from 'P'}} +@end +