r196318 - [objc] Emit warning when the implementation of a secondary initializer calls on

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Dec 3 13:11:49 PST 2013


Author: akirtzidis
Date: Tue Dec  3 15:11:49 2013
New Revision: 196318

URL: http://llvm.org/viewvc/llvm-project?rev=196318&view=rev
Log:
[objc] Emit warning when the implementation of a secondary initializer calls on
super another initializer and when the implementation does not delegate to
another initializer via a call on 'self'.

A secondary initializer is an initializer method not marked as a designated
initializer within a class that has at least one initializer marked as a
designated initializer.

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/ScopeInfo.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/attr-designated-init.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Dec  3 15:11:49 2013
@@ -750,6 +750,10 @@ public:
   /// marked with the 'objc_designated_initializer' attribute.
   void setHasDesignatedInitializers();
 
+  /// Returns true if this interface decl contains at least one initializer
+  /// marked with the 'objc_designated_initializer' attribute.
+  bool hasDesignatedInitializers() const;
+
   const ObjCProtocolList &getReferencedProtocols() const {
     assert(hasDefinition() && "Caller did not check for forward reference!");
     if (data().ExternallyCompleted)

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Dec  3 15:11:49 2013
@@ -2443,6 +2443,12 @@ def warn_objc_designated_init_non_super_
 def warn_objc_designated_init_non_designated_init_call : Warning<
   "designated initializer invoked a non-designated initializer">,
   InGroup<ObjCDesignatedInit>;
+def warn_objc_secondary_init_super_init_call : Warning<
+  "secondary initializer should not invoke an initializer on 'super'">,
+  InGroup<ObjCDesignatedInit>;
+def warn_objc_secondary_init_missing_init_call : Warning<
+  "secondary initializer missing a 'self' call to another initializer">,
+  InGroup<ObjCDesignatedInit>;
 
 def err_ns_bridged_not_interface : Error<
   "parameter of 'ns_bridged' attribute does not name an Objective-C class">;

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Tue Dec  3 15:11:49 2013
@@ -117,6 +117,14 @@ public:
   /// the super class.
   bool ObjCWarnForNoDesignatedInitChain;
 
+  /// True when this is an initializer method not marked as a designated
+  /// initializer within a class that has at least one initializer marked as a
+  /// designated initializer.
+  bool ObjCIsSecondaryInit;
+  /// This starts true for a secondary initializer method and will be set to
+  /// false if there is an invocation of an initializer on 'self'.
+  bool ObjCWarnForNoInitDelegation;
+
   /// \brief Used to determine if errors occurred in this function or block.
   DiagnosticErrorTrap ErrorTrap;
 
@@ -327,6 +335,8 @@ public:
       ObjCShouldCallSuper(false),
       ObjCIsDesignatedInit(false),
       ObjCWarnForNoDesignatedInitChain(false),
+      ObjCIsSecondaryInit(false),
+      ObjCWarnForNoInitDelegation(false),
       ErrorTrap(Diag) { }
 
   virtual ~FunctionScopeInfo();

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Dec  3 15:11:49 2013
@@ -1197,6 +1197,14 @@ void ObjCInterfaceDecl::setHasDesignated
   data().HasDesignatedInitializers = true;
 }
 
+bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
+  assert(hasDefinition() && "Forward declarations can't contain methods");
+  if (data().ExternallyCompleted)
+    LoadExternalDefinition();
+
+  return data().HasDesignatedInitializers;
+}
+
 ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
   if (const ObjCInterfaceDecl *Def = getDefinition()) {
     if (data().ExternallyCompleted)

Modified: cfe/trunk/lib/Sema/ScopeInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ScopeInfo.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/ScopeInfo.cpp (original)
+++ cfe/trunk/lib/Sema/ScopeInfo.cpp Tue Dec  3 15:11:49 2013
@@ -30,6 +30,8 @@ void FunctionScopeInfo::Clear() {
   ObjCShouldCallSuper = false;
   ObjCIsDesignatedInit = false;
   ObjCWarnForNoDesignatedInitChain = false;
+  ObjCIsSecondaryInit = false;
+  ObjCWarnForNoInitDelegation = false;
 
   SwitchStack.clear();
   Returns.clear();

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec  3 15:11:49 2013
@@ -9826,6 +9826,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl
            diag::note_objc_designated_init_marked_here);
       getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
     }
+    if (getCurFunction()->ObjCWarnForNoInitDelegation) {
+      Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call);
+      getCurFunction()->ObjCWarnForNoInitDelegation = false;
+    }
   } else {
     return 0;
   }

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Dec  3 15:11:49 2013
@@ -391,8 +391,16 @@ void Sema::ActOnStartOfObjCMethodDef(Sco
                                           MDecl->getLocation(), 0);
     }
 
-    if (MDecl->isDesignatedInitializerForTheInterface())
-      getCurFunction()->ObjCIsDesignatedInit = true;
+    if (MDecl->getMethodFamily() == OMF_init) {
+      if (MDecl->isDesignatedInitializerForTheInterface()) {
+        getCurFunction()->ObjCIsDesignatedInit = true;
+        getCurFunction()->ObjCWarnForNoDesignatedInitChain =
+            IC->getSuperClass() != 0;
+      } else if (IC->hasDesignatedInitializers()) {
+        getCurFunction()->ObjCIsSecondaryInit = true;
+        getCurFunction()->ObjCWarnForNoInitDelegation = true;
+      }
+    }
 
     // If this is "dealloc" or "finalize", set some bit here.
     // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
@@ -416,9 +424,6 @@ void Sema::ActOnStartOfObjCMethodDef(Sco
         getCurFunction()->ObjCShouldCallSuper = 
           (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
       }
-
-      if (getCurFunction()->ObjCIsDesignatedInit)
-        getCurFunction()->ObjCWarnForNoDesignatedInitChain = true;
     }
   }
 }

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Dec  3 15:11:49 2013
@@ -2476,6 +2476,16 @@ ExprResult Sema::BuildInstanceMessage(Ex
     }
   }
 
+  if (Method && Method->getMethodFamily() == OMF_init &&
+      getCurFunction()->ObjCIsSecondaryInit &&
+      (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+    if (SuperLoc.isValid()) {
+      Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);
+    } else {
+      getCurFunction()->ObjCWarnForNoInitDelegation = false;
+    }
+  }
+
   // Check the message arguments.
   unsigned NumArgs = ArgsIn.size();
   Expr **Args = ArgsIn.data();

Modified: cfe/trunk/test/SemaObjC/attr-designated-init.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-designated-init.m?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/attr-designated-init.m (original)
+++ cfe/trunk/test/SemaObjC/attr-designated-init.m Tue Dec  3 15:11:49 2013
@@ -27,8 +27,9 @@ __attribute__((objc_root_class))
 -(void)meth {}
 -(id)init NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}}
 +(id)init { return 0; }
--(id)init3 { return 0; }
--(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}}
+-(id)init3 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
+-(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}} \
+									 			   // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
 @end
 
 __attribute__((objc_root_class))
@@ -40,7 +41,7 @@ __attribute__((objc_root_class))
 
 @implementation B1
 -(id)initB1 { return 0; }
--(id)initB2 { return 0; }
+-(id)initB2 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
 -(id)initB3 { return 0; }
 @end
 
@@ -134,4 +135,43 @@ __attribute__((objc_root_class))
   return [super initB3];
 }
 -(void)meth {}
+-(id)initS1 {
+  return 0;
+}
+-(id)initS2 {
+  return [super initB1];
+}
+ at end
+
+ at interface S6 : B1
+-(id)initS1 NS_DESIGNATED_INITIALIZER;
+-(id)initS2;
+-(id)initS3;
+-(id)initS4;
+ at end
+
+ at implementation S6
+-(id)initS1 {
+  return [super initB1];
+}
+-(id)initS2 { // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
+  return [super initB1]; // expected-warning {{secondary initializer should not invoke an initializer on 'super'}}
+}
+-(id)initS3 {
+  return [self initB1];
+}
+-(id)initS4 {
+  return [self initS1];
+}
+-(id)initS5 {
+  [super initB1]; // expected-warning {{secondary initializer should not invoke an initializer on 'super'}}
+  void (^blk)(void) = ^{
+    [super initB1];
+  };
+  return [self initS1];
+}
+-(id)initS6 { // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
+  S6 *s;
+  return [s initS1];
+}
 @end





More information about the cfe-commits mailing list