diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 3c24d05dc5b0..46f3c7dfe3c4 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -803,6 +803,8 @@ public: return hasDesignatedInitializers() || inheritsDesignatedInitializers(); } + bool hasDesignatedInitializersInSuperClass() const; + const ObjCProtocolList &getReferencedProtocols() const { assert(hasDefinition() && "Caller did not check for forward reference!"); if (data().ExternallyCompleted) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index aa7107a259d1..0b36d58806ae 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2923,8 +2923,7 @@ public: void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); void DiagnoseMissingDesignatedInitOverrides( - const ObjCImplementationDecl *ImplD, - const ObjCInterfaceDecl *IFD); + const ObjCImplementationDecl *ImplD); void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 77995b5261f6..abd9b33f5db0 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1213,6 +1213,16 @@ bool ObjCInterfaceDecl::hasDesignatedInitializers() const { return data().HasDesignatedInitializers; } +bool ObjCInterfaceDecl::hasDesignatedInitializersInSuperClass() const { + ObjCInterfaceDecl *OSC = getSuperClass(); + while (OSC) { + if (OSC->hasDesignatedInitializers()) + return true; + OSC = OSC->getSuperClass(); + } + return false; +} + StringRef ObjCInterfaceDecl::getObjCRuntimeNameAsString() const { if (ObjCRuntimeNameAttr *ObjCRTName = getAttr()) diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 33d9e95f27f0..d958db582afe 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2715,8 +2715,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, AtomicPropertySetterGetterRules(IC, IDecl); DiagnoseOwningPropertyGetterSynthesis(IC); DiagnoseUnusedBackingIvarInAccessor(S, IC); - if (IDecl->hasDesignatedInitializers()) - DiagnoseMissingDesignatedInitOverrides(IC, IDecl); + if (IDecl->hasDesignatedInitializers() || + IDecl->hasDesignatedInitializersInSuperClass()) + DiagnoseMissingDesignatedInitOverrides(IC); bool HasRootClassAttr = IDecl->hasAttr(); if (IDecl->getSuperClass() == nullptr) { diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index f4f43360f5e1..716fb50ea691 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1894,9 +1894,11 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D } void Sema::DiagnoseMissingDesignatedInitOverrides( - const ObjCImplementationDecl *ImplD, - const ObjCInterfaceDecl *IFD) { - assert(IFD->hasDesignatedInitializers()); + const ObjCImplementationDecl *ImplD) { + const ObjCInterfaceDecl *IFD = ImplD->getClassInterface(); + assert(IFD); + assert(IFD->hasDesignatedInitializers() || + IFD->hasDesignatedInitializersInSuperClass()); const ObjCInterfaceDecl *SuperD = IFD->getSuperClass(); if (!SuperD) return; diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index a8673e1b0191..f990c35bac82 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -39,7 +39,7 @@ __attribute__((objc_root_class)) @end @interface B1() --(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}} +-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 6 {{method marked as designated initializer of the class here}} @end; @implementation B1 @@ -182,7 +182,7 @@ __attribute__((objc_root_class)) -(id)initB1; @end -@implementation SS4 +@implementation SS4 // expected-warning {{method override for the designated initializer of the superclass '-initB3' not found}} -(id)initB1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} return 0; } @@ -233,7 +233,7 @@ __attribute__((objc_root_class)) -(id)initB1; @end -@implementation SS9 +@implementation SS9 // expected-warning {{method override for the designated initializer of the superclass '-initB3' not found}} -(id)initB1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} return 0; } @@ -418,3 +418,41 @@ __attribute__((objc_root_class)) @interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}} - (instancetype)init NS_DESIGNATED_INITIALIZER; // expected-error{{only applies to init methods of interface or class extension declarations}} @end + +// rdar://19653785 +@class NSCoder; + +@interface NSView +- (instancetype)initWithFrame:(int)frameRect NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} +- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} +@end + +@interface MyHappyView : NSView +- (instancetype)initWithFrame:(int)frameRect andOtherThing:(id)otherThing NS_DESIGNATED_INITIALIZER; +@end + +@implementation MyHappyView // expected-warning {{method override for the designated initializer of the superclass '-initWithCoder:' not found}} +- (instancetype)initWithFrame:(int)frameRect andOtherThing:(id)otherThing { + if (self = [super initWithFrame:frameRect]) { + } + return self; +} + +- (instancetype)initWithFrame:(int)frameRect { + return [self initWithFrame:frameRect andOtherThing:((void *)0)]; +} +@end + +@interface MySadView : NSView +@end + +@implementation MySadView // expected-warning {{method override for the designated initializer of the superclass '-initWithFrame:' not found}} \ + // expected-warning {{method override for the designated initializer of the superclass '-initWithCoder:' not found}} +- (instancetype)initWithFrame:(int)frameRect andOtherThing:(id)otherThing { + if (self = [super initWithFrame:frameRect]) { + } + + return self; +} +@end +