From: Argyrios Kyrtzidis Date: Tue, 3 Dec 2013 21:11:54 +0000 (+0000) Subject: [objc] Add a warning when a class that provides a designated initializer, does not X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=20b2dbd23164eab75cca70b32efd47cab9949e53;p=clang [objc] Add a warning when a class that provides a designated initializer, does not override all of the designated initializers of its superclass. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196319 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0ca9a08210..e0eaf341ad 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2449,6 +2449,9 @@ def warn_objc_secondary_init_super_init_call : Warning< def warn_objc_secondary_init_missing_init_call : Warning< "secondary initializer missing a 'self' call to another initializer">, InGroup; +def warn_objc_implementation_missing_designated_init_override : Warning< + "method override for the designated initializer of the superclass %objcinstance0 not found">, + InGroup; def err_ns_bridged_not_interface : Error< "parameter of 'ns_bridged' attribute does not name an Objective-C class">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 06edb443cd..3fbe2b7827 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2686,6 +2686,10 @@ public: void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); + void DiagnoseMissingDesignatedInitOverrides( + const ObjCImplementationDecl *ImplD, + const ObjCInterfaceDecl *IFD); + void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); enum MethodMatchStrategy { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a41bd22cdf..6020473e97 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2674,7 +2674,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef allMethods, ImplMethodsVsClassMethods(S, IC, IDecl); AtomicPropertySetterGetterRules(IC, IDecl); DiagnoseOwningPropertyGetterSynthesis(IC); - + if (IDecl->hasDesignatedInitializers()) + DiagnoseMissingDesignatedInitOverrides(IC, IDecl); + bool HasRootClassAttr = IDecl->hasAttr(); if (IDecl->getSuperClass() == NULL) { // This class has no superclass, so check that it has been marked with diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index d9d9cec1b7..f70e84d7a0 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1830,6 +1830,34 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D } } +void Sema::DiagnoseMissingDesignatedInitOverrides( + const ObjCImplementationDecl *ImplD, + const ObjCInterfaceDecl *IFD) { + assert(IFD->hasDesignatedInitializers()); + const ObjCInterfaceDecl *SuperD = IFD->getSuperClass(); + if (!SuperD) + return; + + SelectorSet InitSelSet; + for (ObjCImplementationDecl::instmeth_iterator + I = ImplD->instmeth_begin(), E = ImplD->instmeth_end(); I!=E; ++I) + if ((*I)->getMethodFamily() == OMF_init) + InitSelSet.insert((*I)->getSelector()); + + SmallVector DesignatedInits; + SuperD->getDesignatedInitializers(DesignatedInits); + for (SmallVector::iterator + I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) { + const ObjCMethodDecl *MD = *I; + if (!InitSelSet.count(MD->getSelector())) { + Diag(ImplD->getLocation(), + diag::warn_objc_implementation_missing_designated_init_override) + << MD->getSelector(); + Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here); + } + } +} + /// AddPropertyAttrs - Propagates attributes from a property to the /// implicitly-declared getter or setter for that property. static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, diff --git a/test/SemaObjC/attr-designated-init.m b/test/SemaObjC/attr-designated-init.m index 513e51515d..3d8bd1c3e5 100644 --- a/test/SemaObjC/attr-designated-init.m +++ b/test/SemaObjC/attr-designated-init.m @@ -34,9 +34,9 @@ __attribute__((objc_root_class)) __attribute__((objc_root_class)) @interface B1 --(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} +-(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 4 {{method marked as designated initializer of the class here}} -(id)initB2; --(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} +-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note 3 {{method marked as designated initializer of the class here}} @end @implementation B1 @@ -82,21 +82,22 @@ __attribute__((objc_root_class)) -(id)initSS1 NS_DESIGNATED_INITIALIZER; @end -@implementation SS2 +@implementation SS2 // expected-warning {{method override for the designated initializer of the superclass '-initB1' not found}} \ + // expected-warning {{method override for the designated initializer of the superclass '-initB3' not found}} -(id)initSS1 { return [super initB1]; } @end @interface S3 : B1 --(id)initS1 NS_DESIGNATED_INITIALIZER; +-(id)initS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} @end @interface SS3 : S3 -(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} @end -@implementation SS3 +@implementation SS3 // expected-warning {{method override for the designated initializer of the superclass '-initS1' not found}} -(id)initSS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} return [super initB1]; // expected-warning {{designated initializer invoked a non-designated initializer}} } @@ -150,7 +151,8 @@ __attribute__((objc_root_class)) -(id)initS4; @end -@implementation S6 +@implementation S6 // expected-warning {{method override for the designated initializer of the superclass '-initB1' not found}} \ + // expected-warning {{method override for the designated initializer of the superclass '-initB3' not found}} -(id)initS1 { return [super initB1]; }