]> granicus.if.org Git - clang/commitdiff
Allow objc_requires_super to be used to check class methods as well.
authorJordan Rose <jordan_rose@apple.com>
Fri, 19 Oct 2012 16:05:26 +0000 (16:05 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 19 Oct 2012 16:05:26 +0000 (16:05 +0000)
Also, unify ObjCShouldCallSuperDealloc and ObjCShouldCallSuperFinalize.
The two have identical behavior and will never be active at the same time.

There's one last simplification now, which is that if we see a call to
[super foo] and we are currently in a method named 'foo', we will
/unconditionally/ clear the ObjCShouldCallSuper flag, rather than check
first to see if we're in a method where calling super is required. There's
no reason to pay the extra lookup price here.

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

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/ScopeInfo.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/super-dealloc-attribute.m

index 51bb9f51e1a58e146b42fef50de0bf8e9029b40a..18600a44463f1f06c683c57b3d22cea1b187aca3 100644 (file)
@@ -754,9 +754,6 @@ def warn_objc_missing_super_call : Warning<
 def error_dealloc_bad_result_type : Error<
   "dealloc return type must be correctly specified as 'void' under ARC, "
   "instead of %0">;
-def warn_objc_missing_super_finalize : Warning<
-  "method possibly missing a [super finalize] call">,
-  InGroup<ObjCMissingSuperCalls>;
 def warn_undeclared_selector : Warning<
   "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
 def warn_implicit_atomic_property : Warning<
index c0c907e834a8b0ceedcd04a39a4dc908415d4215..0bfc6dcae6d88ae9abe9299cdbfff31989230113 100644 (file)
@@ -91,13 +91,10 @@ public:
   /// \brief Whether this function contains any indirect gotos.
   bool HasIndirectGoto;
 
-  /// A flag that is set when parsing a -dealloc method and no [super dealloc]
-  /// call was found yet.
-  bool ObjCShouldCallSuperDealloc;
-
-  /// A flag that is set when parsing a -finalize method and no [super finalize]
-  /// call was found yet.
-  bool ObjCShouldCallSuperFinalize;
+  /// A flag that is set when parsing a method that must call super's
+  /// implementation, such as \c -dealloc, \c -finalize, or any method marked
+  /// with \c __attribute__((objc_requires_super)).
+  bool ObjCShouldCallSuper;
 
   /// \brief Used to determine if errors occurred in this function or block.
   DiagnosticErrorTrap ErrorTrap;
@@ -299,8 +296,7 @@ public:
       HasBranchProtectedScope(false),
       HasBranchIntoScope(false),
       HasIndirectGoto(false),
-      ObjCShouldCallSuperDealloc(false),
-      ObjCShouldCallSuperFinalize(false),
+      ObjCShouldCallSuper(false),
       ErrorTrap(Diag) { }
 
   virtual ~FunctionScopeInfo();
index 6791273384f52b58d25d38c84ff33786eca8280b..f55415996ba7b5de75f39dfd313bd56faf692a68 100644 (file)
@@ -7944,23 +7944,16 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
       if (Body)
         computeNRVO(Body, getCurFunction());
     }
-    if (getCurFunction()->ObjCShouldCallSuperDealloc) {
+    if (getCurFunction()->ObjCShouldCallSuper) {
       Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call)
         << MD->getSelector().getAsString();
-      getCurFunction()->ObjCShouldCallSuperDealloc = false;
-    }
-    if (getCurFunction()->ObjCShouldCallSuperFinalize) {
-      Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize);
-      getCurFunction()->ObjCShouldCallSuperFinalize = false;
+      getCurFunction()->ObjCShouldCallSuper = false;
     }
   } else {
     return 0;
   }
 
-  assert(!getCurFunction()->ObjCShouldCallSuperDealloc &&
-         "This should only be set for ObjC methods, which should have been "
-         "handled in the block above.");
-  assert(!getCurFunction()->ObjCShouldCallSuperFinalize &&
+  assert(!getCurFunction()->ObjCShouldCallSuper &&
          "This should only be set for ObjC methods, which should have been "
          "handled in the block above.");
 
index fa330d63c41a7ae19f57cc66085619a4f8748a5a..a4fec7aebf651a0a3768c5b2f389d7e6234d09f3 100644 (file)
@@ -383,19 +383,23 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
     // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
     // Only do this if the current class actually has a superclass.
     if (IC->getSuperClass()) {
-      getCurFunction()->ObjCShouldCallSuperDealloc = 
-        !(Context.getLangOpts().ObjCAutoRefCount ||
-          Context.getLangOpts().getGC() == LangOptions::GCOnly) &&
-          MDecl->getMethodFamily() == OMF_dealloc;
-      if (!getCurFunction()->ObjCShouldCallSuperDealloc) {
-        IMD = IC->getSuperClass()->lookupMethod(MDecl->getSelector(), 
-                                                MDecl->isInstanceMethod());
-        getCurFunction()->ObjCShouldCallSuperDealloc = 
-          (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>());
+      ObjCMethodFamily Family = MDecl->getMethodFamily();
+      if (Family == OMF_dealloc) {
+        if (!(getLangOpts().ObjCAutoRefCount ||
+              getLangOpts().getGC() == LangOptions::GCOnly))
+          getCurFunction()->ObjCShouldCallSuper = true;
+
+      } else if (Family == OMF_finalize) {
+        if (Context.getLangOpts().getGC() != LangOptions::NonGC)
+          getCurFunction()->ObjCShouldCallSuper = true;
+        
+      } else {
+        const ObjCMethodDecl *SuperMethod =
+          IC->getSuperClass()->lookupMethod(MDecl->getSelector(),
+                                            MDecl->isInstanceMethod());
+        getCurFunction()->ObjCShouldCallSuper = 
+          (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
       }
-      getCurFunction()->ObjCShouldCallSuperFinalize =
-        Context.getLangOpts().getGC() != LangOptions::NonGC &&
-        MDecl->getMethodFamily() == OMF_finalize;
     }
   }
 }
index 3f9c14c685232e2acfdf541cd7d04b629fd85aad..e43b6bff558658f9aef37901e4d9d257c3ed698e 100644 (file)
@@ -1772,20 +1772,10 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
 
   // We are in a method whose class has a superclass, so 'super'
   // is acting as a keyword.
-  if (Method->isInstanceMethod()) {
-    if (Sel.getMethodFamily() == OMF_dealloc)
-      getCurFunction()->ObjCShouldCallSuperDealloc = false;
-    else if (const ObjCMethodDecl *IMD =
-               Class->lookupMethod(Method->getSelector(), 
-                                   Method->isInstanceMethod()))
-          // Must check for name of message since the method could
-          // be another method with objc_requires_super attribute set.
-          if (IMD->hasAttr<ObjCRequiresSuperAttr>() && 
-              Sel == IMD->getSelector())
-            getCurFunction()->ObjCShouldCallSuperDealloc = false;
-    if (Sel.getMethodFamily() == OMF_finalize)
-      getCurFunction()->ObjCShouldCallSuperFinalize = false;
+  if (Method->getSelector() == Sel)
+    getCurFunction()->ObjCShouldCallSuper = false;
 
+  if (Method->isInstanceMethod()) {
     // Since we are in an instance method, this is an instance
     // message to the superclass instance.
     QualType SuperTy = Context.getObjCInterfaceType(Super);
index 0ba65cc078070495c5e6ae0339875927bc802282..35f6dac9bf42e006b76b9607312a6e457f1c972a 100644 (file)
@@ -19,6 +19,8 @@
 - (void) MyDeallocMeth; // Method in root is not annotated.
 - (void) AnnotMyDeallocMeth __attribute((objc_requires_super));
 - (void) AnnotMyDeallocMethCAT NS_REQUIRES_SUPER; 
+
++ (void)registerClass:(id)name __attribute((objc_requires_super));
 @end
 
 @interface Baz : Root<NSObject>
@@ -41,6 +43,8 @@
 - (void) MyDeallocMeth {} // No warning here.
 - (void) AnnotMyDeallocMeth{} // expected-warning {{method possibly missing a [super AnnotMyDeallocMeth] call}}
 - (void) AnnotMeth{}; // No warning here. Annotation is in its class.
+
++ (void)registerClass:(id)name {} // expected-warning {{method possibly missing a [super registerClass:] call}}
 @end
 
 @interface Bar : Baz
 - (void) AnnotMyDeallocMethCAT{}; // expected-warning {{method possibly missing a [super AnnotMyDeallocMethCAT] call}}
 - (void) AnnotMethCAT {};
 @end
+
+
+@interface Valid : Baz
+@end
+
+@implementation Valid
+
+- (void)MyDeallocMeth {
+  [super MyDeallocMeth]; // no-warning
+}
+
+
++ (void)registerClass:(id)name {
+  [super registerClass:name]; // no-warning
+}
+
+@end