diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 61d5242803d01f01662408fd77d7b3b9aaab9eaf..a610f62c51326f5dd367a335ffa3b005257d5fac 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -490,6 +490,8 @@ def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">; def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">; +def ObjCNoPropertyAuthoSynthesis : DiagGroup<"objc-property-synthesis">; + // ObjC API warning groups. def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">; def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [ diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c7cd205b548e935ed96812dfd399b1e7f5cb34f9..87f95aca4ba04c20e23070658e5b9ed1c3cf2fca 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -666,6 +666,15 @@ def warn_auto_synthesizing_protocol_property :Warning< "auto property synthesis will not synthesize property" " declared in a protocol">, InGroup<DiagGroup<"objc-protocol-property-synthesis">>; +def warn_no_autosynthesis_shared_ivar_property : Warning < + "auto property synthesis will not synthesize property " + "'%0' because it cannot share an ivar with another synthesized property">, + InGroup<ObjCNoPropertyAuthoSynthesis>; +def warn_no_autosynthesis_property : Warning< + "auto property synthesis will not synthesize property " + "'%0' because it is 'readwrite' but it will be synthesized 'readonly' " + "via another property">, + InGroup<ObjCNoPropertyAuthoSynthesis>; def warn_autosynthesis_property_ivar_match :Warning< "autosynthesized property %0 will use %select{|synthesized}1 instance variable " "%2, not existing instance variable %3">, diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index e046faa04d0ae722c32aee34b507e073f904b1bb..2195541cd74198ad1598b491c95d2d9a605eb86c 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1585,13 +1585,31 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) { ObjCPropertyDecl *Prop = PropertyOrder[i]; // If property to be implemented in the super class, ignore. - if (SuperPropMap[Prop->getIdentifier()]) + if (SuperPropMap[Prop->getIdentifier()]) { + ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()]; + if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) && + (PropInSuperClass->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_readonly)) { + Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) + << Prop->getIdentifier()->getName(); + Diag(PropInSuperClass->getLocation(), diag::note_property_declare); + } continue; + } // Is there a matching property synthesize/dynamic? if (Prop->isInvalidDecl() || - Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || - IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) continue; + if (ObjCPropertyImplDecl *PID = + IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { + if (PID->getPropertyDecl() != Prop) { + Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) + << Prop->getIdentifier()->getName(); + if (!PID->getLocation().isInvalid()) + Diag(PID->getLocation(), diag::note_property_synthesize); + } + continue; + } // Property may have been synthesized by user. if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) continue; diff --git a/test/SemaObjC/default-synthesize-3.m b/test/SemaObjC/default-synthesize-3.m index 606ece33af8d48f0725236a42a595b383bf51a64..06741e119e5ba5ec1e4356141b8fe648e47b1a81 100644 --- a/test/SemaObjC/default-synthesize-3.m +++ b/test/SemaObjC/default-synthesize-3.m @@ -39,3 +39,33 @@ __attribute ((objc_requires_property_definitions)) __attribute ((objc_requires_property_definitions)) // expected-error {{objc_requires_property_definitions attribute may only be specified on a class}} @protocol P @end + +// rdar://13388503 +@interface NSObject @end +@protocol Foo +@property (readonly) char isFoo; // expected-note {{property declared here}} +@end + +@interface Bar : NSObject <Foo> +@end + +@implementation Bar +- (char)isFoo { + return 0; +} +@end + +@interface Baz : Bar +@end + +@interface Baz () +@property (readwrite) char isFoo; // expected-warning {{auto property synthesis will not synthesize property 'isFoo' because it is 'readwrite' but it will be synthesized 'readonly' via another property}} +@property char Property1; // expected-warning {{auto property synthesis will not synthesize property 'Property1' because it cannot share an ivar with another synthesized property}} +@property char Property2; +@end + +@implementation Baz { + char _isFoo; +} +@synthesize Property2 = Property1; // expected-note {{property synthesized here}} +@end