]> granicus.if.org Git - clang/commitdiff
[objc] Emit warnings when the implementation of a designated initializer calls on
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 3 Dec 2013 21:11:43 +0000 (21:11 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 3 Dec 2013 21:11:43 +0000 (21:11 +0000)
super an initializer that is not a designated one or any initializer on self.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196317 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/DeclObjC.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/attr-designated-init.m

index 774de1a4fedb4692d0299b7c6fb44cd5738611a8..12e2a0b727ada831ad2002db6be4942fa5044fbf 100644 (file)
@@ -457,7 +457,12 @@ public:
 
   /// Returns true if the method selector resolves to a designated initializer
   /// in the class's interface.
-  bool isDesignatedInitializerForTheInterface() const;
+  ///
+  /// \param InitMethod if non-null and the function returns true, it receives
+  /// the method declaration that was marked with the designated initializer
+  /// attribute.
+  bool isDesignatedInitializerForTheInterface(
+      const ObjCMethodDecl **InitMethod = 0) const;
 
   /// \brief Determine whether this method has a body.
   virtual bool hasBody() const { return Body.isValid(); }
index 314d0375e671323e9bafc8ad701ecd6a729fba4b..52fc79810311d49128584ef1d63b9a963d0f9b42 100644 (file)
@@ -2437,6 +2437,12 @@ def warn_objc_designated_init_missing_super_call : Warning<
   InGroup<ObjCDesignatedInit>;
 def note_objc_designated_init_marked_here : Note<
   "method marked as designated initializer of the class here">;
+def warn_objc_designated_init_non_super_designated_init_call : Warning<
+  "designated initializer should only invoke a designated initializer on 'super'">,
+  InGroup<ObjCDesignatedInit>;
+def warn_objc_designated_init_non_designated_init_call : Warning<
+  "designated initializer invoked a non-designated initializer">,
+  InGroup<ObjCDesignatedInit>;
 
 def err_ns_bridged_not_interface : Error<
   "parameter of 'ns_bridged' attribute does not name an Objective-C class">;
index cb58ad482e101018df9385964279182698544df3..b392e2f661919f1c0a9176d46e18ee81c5adde0d 100644 (file)
@@ -655,12 +655,15 @@ bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
       hasAttr<ObjCDesignatedInitializerAttr>();
 }
 
-bool ObjCMethodDecl::isDesignatedInitializerForTheInterface() const {
+bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
+    const ObjCMethodDecl **InitMethod) const {
+  if (getMethodFamily() != OMF_init)
+    return false;
   const DeclContext *DC = getDeclContext();
   if (isa<ObjCProtocolDecl>(DC))
     return false;
   if (const ObjCInterfaceDecl *ID = getClassInterface())
-    return ID->isDesignatedInitializer(getSelector());
+    return ID->isDesignatedInitializer(getSelector(), InitMethod);
   return false;
 }
 
index c14cc4b8619f329a45a519d2284ca943e418706b..f243c0e8d18a1c09e732782b76ba053577ad0a6c 100644 (file)
@@ -9816,8 +9816,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
     }
     if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
       const ObjCMethodDecl *InitMethod = 0;
-      bool isDesignated = MD->getClassInterface()
-                      ->isDesignatedInitializer(MD->getSelector(), &InitMethod);
+      bool isDesignated =
+          MD->isDesignatedInitializerForTheInterface(&InitMethod);
       assert(isDesignated && InitMethod);
       (void)isDesignated;
       Diag(MD->getLocation(),
index 20f4b4f7248ae792c285fc22aaf324a63a40c3a9..c452306457993e8678f71899ea11fd18a57b2078 100644 (file)
@@ -2447,14 +2447,33 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
     }
   }
 
-  if (SuperLoc.isValid() && getCurFunction()->ObjCIsDesignatedInit) {
-    if (const ObjCObjectPointerType *
-          OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
-      if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
-        if (ID->isDesignatedInitializer(Sel))
-          getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
+  if (Method && Method->getMethodFamily() == OMF_init &&
+      getCurFunction()->ObjCIsDesignatedInit &&
+      (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+    bool isDesignatedInitChain = false;
+    if (SuperLoc.isValid()) {
+      if (const ObjCObjectPointerType *
+            OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
+        if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
+          if (ID->isDesignatedInitializer(Sel)) {
+            isDesignatedInitChain = true;
+            getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
+          }
+        }
       }
     }
+    if (!isDesignatedInitChain) {
+      const ObjCMethodDecl *InitMethod = 0;
+      bool isDesignated =
+        getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod);
+      assert(isDesignated && InitMethod);
+      (void)isDesignated;
+      Diag(SelLoc, SuperLoc.isValid() ?
+             diag::warn_objc_designated_init_non_designated_init_call :
+             diag::warn_objc_designated_init_non_super_designated_init_call);
+      Diag(InitMethod->getLocation(),
+           diag::note_objc_designated_init_marked_here);
+    }
   }
 
   // Check the message arguments.
index 3190d8a97fede90c8f8c550dfc3ab64b18a3dc75..59d1357d9e2d2fd360ab9a08a2b9b6ebc1845024 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
 
 #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
 
@@ -35,7 +35,7 @@ __attribute__((objc_root_class))
 @interface B1
 -(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}}
 -(id)initB2;
--(id)initB3 NS_DESIGNATED_INITIALIZER;
+-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
 @end
 
 @implementation B1
@@ -47,8 +47,8 @@ __attribute__((objc_root_class))
 @interface S1 : B1
 -(id)initS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
 -(id)initS2 NS_DESIGNATED_INITIALIZER;
--(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
--(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
+-(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
+-(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
 -(id)initB1;
 @end
 
@@ -60,10 +60,10 @@ __attribute__((objc_root_class))
   return [super initB1];
 }
 -(id)initS3 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
-  return [super initB2];
+  return [super initB2]; // expected-warning {{designated initializer invoked a non-designated initializer}}
 }
 -(id)initS4 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
-  return [self initB1];
+  return [self initB1]; // expected-warning {{designated initializer should only invoke a designated initializer on 'super'}}
 }
 -(id)initB1 {
   return [self initS1];
@@ -92,12 +92,12 @@ __attribute__((objc_root_class))
 @end
 
 @interface SS3 : S3
--(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
+-(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}}
 @end
 
 @implementation SS3
 -(id)initSS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}}
-  return [super initB1];
+  return [super initB1]; // expected-warning {{designated initializer invoked a non-designated initializer}}
 }
 @end
 
@@ -116,6 +116,7 @@ __attribute__((objc_root_class))
 @end
 
 @interface S5 : B1
+-(void)meth;
 @end
 
 @implementation S5
@@ -123,6 +124,14 @@ __attribute__((objc_root_class))
   return 0;
 }
 -(id)initB3 {
+  [self initB1]; // expected-warning {{designated initializer should only invoke a designated initializer on 'super'}}
+  S5 *s;
+  [s initB1];
+  [self meth];
+  void (^blk)(void) = ^{
+    [self initB1];
+  };
   return [super initB3];
 }
+-(void)meth {}
 @end