Allow objc_requires_super to be used to check class methods as well.

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
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 51bb9f5..18600a4 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -754,9 +754,6 @@
 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<
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index c0c907e..0bfc6dc 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -91,13 +91,10 @@
   /// \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 @@
       HasBranchProtectedScope(false),
       HasBranchIntoScope(false),
       HasIndirectGoto(false),
-      ObjCShouldCallSuperDealloc(false),
-      ObjCShouldCallSuperFinalize(false),
+      ObjCShouldCallSuper(false),
       ErrorTrap(Diag) { }
 
   virtual ~FunctionScopeInfo();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 6791273..f554159 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7944,23 +7944,16 @@
       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.");
 
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index fa330d6..a4fec7a 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -383,19 +383,23 @@
     // 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;
     }
   }
 }
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 3f9c14c..e43b6bf 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1772,20 +1772,10 @@
 
   // 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);
diff --git a/test/SemaObjC/super-dealloc-attribute.m b/test/SemaObjC/super-dealloc-attribute.m
index 0ba65cc..35f6dac 100644
--- a/test/SemaObjC/super-dealloc-attribute.m
+++ b/test/SemaObjC/super-dealloc-attribute.m
@@ -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
@@ -64,3 +68,20 @@
 - (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