From 4ab2452c1f5294a96120164bf4b0b5b95e2d141a Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Sat, 26 Jul 2014 20:52:26 +0000 Subject: [PATCH] Objective-C. Issue more warning diagnostic when certain properties are not synthesized in property auto-synthesis, as it can potentiall lead to runtime errors. rdar://17774815 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214032 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++++ lib/Sema/SemaObjCProperty.cpp | 21 +++++++++++-------- test/Analysis/objc_invalidation.m | 4 ++-- test/SemaObjC/attr-deprecated.m | 4 ++-- test/SemaObjC/default-synthesize-1.m | 17 +++++++++++++++ test/SemaObjC/default-synthesize-3.m | 12 +++++------ test/SemaObjC/default-synthesize.m | 6 +++--- .../SemaObjC/protocols-suppress-conformance.m | 10 +++++---- test/SemaObjC/super-property-notation.m | 4 ++-- 9 files changed, 54 insertions(+), 28 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 366f6d2766..3a8365243f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -783,6 +783,10 @@ def warn_no_autosynthesis_property : Warning< "%0 because it is 'readwrite' but it will be synthesized 'readonly' " "via another property">, InGroup; +def warn_autosynthesis_property_in_superclass : Warning< + "auto property synthesis will not synthesize property " + "%0 because it will be synthesize by its super class">, + InGroup; 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 8eb806ba30..0032294926 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1555,20 +1555,23 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCPropertyDecl::OBJC_PR_readonly) && !IMPDecl->getInstanceMethod(Prop->getSetterName()) && !IDecl->HasUserDeclaredSetterMethod(Prop)) { - Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) - << Prop->getIdentifier(); - Diag(PropInSuperClass->getLocation(), diag::note_property_declare); + Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) + << Prop->getIdentifier(); + Diag(PropInSuperClass->getLocation(), diag::note_property_declare); + } + else { + Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass) + << Prop->getIdentifier(); + Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); } continue; } if (ObjCPropertyImplDecl *PID = IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { - if (PID->getPropertyDecl() != Prop) { - Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) - << Prop->getIdentifier(); - if (!PID->getLocation().isInvalid()) - Diag(PID->getLocation(), diag::note_property_synthesize); - } + Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) + << Prop->getIdentifier(); + if (!PID->getLocation().isInvalid()) + Diag(PID->getLocation(), diag::note_property_synthesize); continue; } if (ObjCProtocolDecl *Proto = diff --git a/test/Analysis/objc_invalidation.m b/test/Analysis/objc_invalidation.m index cd66444f40..9ac98284b4 100644 --- a/test/Analysis/objc_invalidation.m +++ b/test/Analysis/objc_invalidation.m @@ -199,7 +199,7 @@ extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, // synthesized in the parent, let the parent invalidate it. @protocol IDEBuildable -@property (readonly, strong) id ObjB; +@property (readonly, strong) id ObjB; // expected-warning {{auto property synthesis will not synthesize property 'ObjB'}} @end @interface Parent : NSObject { @@ -231,7 +231,7 @@ extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, } @end -@implementation Child +@implementation Child // expected-note {{detected while default synthesizing properties in class implementation}} - (void)invalidate{ // no-warning } diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m index ca30d0a27d..f18f99f013 100644 --- a/test/SemaObjC/attr-deprecated.m +++ b/test/SemaObjC/attr-deprecated.m @@ -201,14 +201,14 @@ expected-note {{'setObject:' has been explicitly marked deprecated here}} @end @interface TestDerived : TestBase -@property (nonatomic, strong) id object; +@property (nonatomic, strong) id object; //expected-warning {{auto property synthesis will not synthesize property 'object' because it will be synthesize by its super class}} @end @interface TestUse @end @implementation TestBase @end -@implementation TestDerived @end +@implementation TestDerived @end // expected-note {{detected while default synthesizing properties in class implementation}} @implementation TestUse diff --git a/test/SemaObjC/default-synthesize-1.m b/test/SemaObjC/default-synthesize-1.m index f9f2e72eaf..31dd669405 100644 --- a/test/SemaObjC/default-synthesize-1.m +++ b/test/SemaObjC/default-synthesize-1.m @@ -124,3 +124,20 @@ // expected-note {{detected while default synthesizing properties in class implementation}} @synthesize x; // expected-error {{cannot synthesize property 'x' with incomplete type 'enum A'}} @end + +// rdar://17774815 +@interface ZXParsedResult +@property (nonatomic, copy, readonly) NSString *description; +@end + +@interface ZXCalendarParsedResult : ZXParsedResult + +@property (nonatomic, copy, readonly) NSString *description; // expected-warning {{auto property synthesis will not synthesize property 'description' because it will be synthesize by its super class}} + +@end + +@implementation ZXCalendarParsedResult // expected-note {{detected while default synthesizing properties in class implementation}} +- (NSString *) Meth { + return _description; // expected-error {{use of undeclared identifier '_description'}} +} +@end diff --git a/test/SemaObjC/default-synthesize-3.m b/test/SemaObjC/default-synthesize-3.m index c91597462d..879335e26b 100644 --- a/test/SemaObjC/default-synthesize-3.m +++ b/test/SemaObjC/default-synthesize-3.m @@ -66,10 +66,10 @@ __attribute ((objc_requires_property_definitions)) // expected-error {{'objc_req @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; -@property (readwrite) char isNotFree; +@property (readwrite) char isNotFree; // expected-warning {{auto property synthesis will not synthesize property 'isNotFree'}} @end -@implementation Baz { +@implementation Baz { // expected-note {{detected while default synthesizing properties in class implementation}} char _isFoo; char _isNotFree; } @@ -104,12 +104,12 @@ __attribute ((objc_requires_property_definitions)) // expected-error {{'objc_req @end @interface S : B -@property (assign,readwrite) id prop; -@property (assign,readwrite) id prop1; -@property (assign,readwrite) id prop2; +@property (assign,readwrite) id prop; // expected-warning {{auto property synthesis will not synthesize property 'prop'}} +@property (assign,readwrite) id prop1; // expected-warning {{auto property synthesis will not synthesize property 'prop1'}} +@property (assign,readwrite) id prop2; // expected-warning {{auto property synthesis will not synthesize property 'prop2'}} @end -@implementation S +@implementation S // expected-note 3 {{detected while default synthesizing properties in class implementation}} @end // rdar://14085456 diff --git a/test/SemaObjC/default-synthesize.m b/test/SemaObjC/default-synthesize.m index 9356b9f5b3..a3abe2eca8 100644 --- a/test/SemaObjC/default-synthesize.m +++ b/test/SemaObjC/default-synthesize.m @@ -88,7 +88,7 @@ @end @protocol TopProtocol - @property (readonly) id myString; + @property (readonly) id myString; // expected-warning {{auto property synthesis will not synthesize property 'myString' because it will be synthesize by its super class}} @end @interface TopClass @@ -97,10 +97,10 @@ } @end -@interface SubClass : TopClass +@interface SubClass : TopClass @end -@implementation SubClass @end +@implementation SubClass @end // expected-note {{detected while default synthesizing properties in class implementation}} // rdar://7920807 @interface C @end diff --git a/test/SemaObjC/protocols-suppress-conformance.m b/test/SemaObjC/protocols-suppress-conformance.m index 299e44e807..dffa6c2235 100644 --- a/test/SemaObjC/protocols-suppress-conformance.m +++ b/test/SemaObjC/protocols-suppress-conformance.m @@ -5,7 +5,8 @@ __attribute__((objc_protocol_requires_explicit_implementation)) @protocol Protocol - (void) theBestOfTimes; // expected-note {{method 'theBestOfTimes' declared here}} -@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} +@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} \ + // expected-warning 2 {{auto property synthesis will not synthesize property 'theWorstOfTimes'}} @end // In this example, ClassA adopts the protocol. We won't @@ -20,7 +21,8 @@ __attribute__((objc_protocol_requires_explicit_implementation)) @interface ClassB : ClassA @end -@implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} +@implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} \ + // expected-note {{detected while default synthesizing properties in class implementation}} @end @interface ClassB_Good : ClassA @@ -32,7 +34,7 @@ __attribute__((objc_protocol_requires_explicit_implementation)) @end @interface ClassB_AlsoGood : ClassA -@property (readonly) id theWorstOfTimes; +@property (readonly) id theWorstOfTimes; // expected-warning {{auto property synthesis will not synthesize property 'theWorstOfTimes' because it will be synthesize by its super class}} @end // Default synthesis acts as if @dynamic @@ -40,7 +42,7 @@ __attribute__((objc_protocol_requires_explicit_implementation)) // it is declared in ClassA. This is okay, since // the author of ClassB_AlsoGood needs explicitly // write @property in the @interface. -@implementation ClassB_AlsoGood // no-warning +@implementation ClassB_AlsoGood // expected-note 2 {{detected while default synthesizing properties in class implementation}} - (void) theBestOfTimes {} @end diff --git a/test/SemaObjC/super-property-notation.m b/test/SemaObjC/super-property-notation.m index aa67f0af39..0f90f617c6 100644 --- a/test/SemaObjC/super-property-notation.m +++ b/test/SemaObjC/super-property-notation.m @@ -41,10 +41,10 @@ __attribute__((objc_root_class)) @interface ClassBase @end @interface ClassDerived : ClassBase -@property (nonatomic, retain) ClassDerived * foo; +@property (nonatomic, retain) ClassDerived * foo; // expected-warning {{auto property synthesis will not synthesize property 'foo' because it will be synthesize by its super class}} @end -@implementation ClassDerived +@implementation ClassDerived // expected-note {{detected while default synthesizing properties in class implementation}} - (void) Meth:(ClassBase*)foo { super.foo = foo; // must work with no warning [super setFoo:foo]; // works with no warning -- 2.40.0