]> granicus.if.org Git - clang/commitdiff
[objc] Add a warning when a class that provides a designated initializer, does not
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 3 Dec 2013 21:11:54 +0000 (21:11 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 3 Dec 2013 21:11:54 +0000 (21:11 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaObjCProperty.cpp
test/SemaObjC/attr-designated-init.m

index 0ca9a082108113e1f6f5a76bf051924927bf1d65..e0eaf341adcc92ed82d785aad617264afeeda663 100644 (file)
@@ -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<ObjCDesignatedInit>;
+def warn_objc_implementation_missing_designated_init_override : Warning<
+  "method override for the designated initializer of the superclass %objcinstance0 not found">,
+  InGroup<ObjCDesignatedInit>;
 
 def err_ns_bridged_not_interface : Error<
   "parameter of 'ns_bridged' attribute does not name an Objective-C class">;
index 06edb443cdef0f72278f07a6e84fc3997b4c023d..3fbe2b78270310c190a7a359abd17d66b4534eed 100644 (file)
@@ -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 {
index a41bd22cdf13fa0a023e5da7cb5b4a4d312f0ac9..6020473e9794f0b2468f53cc3daa8998eb3ccae4 100644 (file)
@@ -2674,7 +2674,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
       ImplMethodsVsClassMethods(S, IC, IDecl);
       AtomicPropertySetterGetterRules(IC, IDecl);
       DiagnoseOwningPropertyGetterSynthesis(IC);
-  
+      if (IDecl->hasDesignatedInitializers())
+        DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
+
       bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
       if (IDecl->getSuperClass() == NULL) {
         // This class has no superclass, so check that it has been marked with
index d9d9cec1b700da510de72adb53cae7540a9f5990..f70e84d7a061c0efc9e7a2f800eede2235361c46 100644 (file)
@@ -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<const ObjCMethodDecl *, 8> DesignatedInits;
+  SuperD->getDesignatedInitializers(DesignatedInits);
+  for (SmallVector<const ObjCMethodDecl *, 8>::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,
index 513e51515d6d3db47a8070f07aad99ec433cddfe..3d8bd1c3e5ecc51a335da4773fcd7b554b281a0d 100644 (file)
@@ -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 {{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];
 }