]> granicus.if.org Git - clang/commitdiff
objective-C: introduce __attribute((objc_requires_super)) on method
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 7 Sep 2012 23:46:23 +0000 (23:46 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 7 Sep 2012 23:46:23 +0000 (23:46 +0000)
in classes. Use it to flag those method implementations which don't
contain call to 'super' if they have 'super' class and it has the method
with this attribute set. This is wip. // rdar://6386358

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

include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/super-dealloc-attribute.m [new file with mode: 0644]
test/SemaObjC/warn-missing-super.m
test/SemaObjCXX/warn-missing-super.mm

index fade83ef9361cfcfc7c5bfe32f17349beebdd8b5..7406ce2647065f3438bf1c2ddaf879334f41a797 100644 (file)
@@ -528,6 +528,11 @@ def ObjCReturnsInnerPointer : Attr {
   let Subjects = [ObjCMethod];
 }
 
+def ObjCRequiresSuper : InheritableAttr {
+  let Spellings = [GNU<"objc_requires_super">];
+  let Subjects = [ObjCMethod];
+}
+
 def ObjCRootClass : Attr {
   let Spellings = [GNU<"objc_root_class">];
   let Subjects = [ObjCInterface];
index 75c98b1159af04641e8fc654e168a53fa262c23d..2b6cb4c34e7e5cdcbf190c2e2251ced89989b3b3 100644 (file)
@@ -740,7 +740,7 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
   "property attributes '%0' and '%1' are mutually exclusive">,
   InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
 def warn_objc_missing_super_dealloc : Warning<
-  "method possibly missing a [super dealloc] call">,
+  "method possibly missing a [super %0] call">,
   InGroup<ObjCMissingSuperCalls>;
 def error_dealloc_bad_result_type : Error<
   "dealloc return type must be correctly specified as 'void' under ARC, "
@@ -2057,6 +2057,12 @@ def warn_ns_attribute_wrong_parameter_type : Warning<
   "%0 attribute only applies to %select{Objective-C object|pointer}1 "
   "parameters">,
   InGroup<IgnoredAttributes>;
+def warn_objc_requires_super_protocol : Warning<
+  "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">,
+  InGroup<DiagGroup<"requires-super-attribute">>;
+def note_protocol_decl : Note<
+  "protocol is declared here">;
+
 def err_ns_bridged_not_interface : Error<
   "parameter of 'ns_bridged' attribute does not name an Objective-C class">;
 
index b3db84039738542262f39ba07fd0214a12a5a988..5ed06d6daa549309b2ad68f2620440503e2a2de0 100644 (file)
@@ -7832,7 +7832,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
         computeNRVO(Body, getCurFunction());
     }
     if (getCurFunction()->ObjCShouldCallSuperDealloc) {
-      Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc);
+      Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc)
+        << MD->getDeclName();
       getCurFunction()->ObjCShouldCallSuperDealloc = false;
     }
     if (getCurFunction()->ObjCShouldCallSuperFinalize) {
index 8ffffab8b59fe04a8135cf717c93075276a3b492..119ce7dfff7be5037f7d6f323676929ac289ed6b 100644 (file)
@@ -3974,6 +3974,33 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
     ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context));
 }
 
+static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
+                                        const AttributeList &attr) {
+  SourceLocation loc = attr.getLoc();
+  ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
+  
+  if (!method) {
+   S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+   << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
+    return;
+  }
+  DeclContext *DC = method->getDeclContext();
+  if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
+    S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
+    << attr.getName() << 0;
+    S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
+    return;
+  }
+  if (method->getMethodFamily() == OMF_dealloc) {
+    S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
+    << attr.getName() << 1;
+    return;
+  }
+  
+  method->addAttr(
+    ::new (S.Context) ObjCRequiresSuperAttr(attr.getRange(), S.Context));
+}
+
 /// Handle cf_audited_transfer and cf_unknown_transfer.
 static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
   if (!isa<FunctionDecl>(D)) {
@@ -4281,6 +4308,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
   case AttributeList::AT_ObjCReturnsInnerPointer:
     handleObjCReturnsInnerPointerAttr(S, D, Attr); break;
 
+  case AttributeList::AT_ObjCRequiresSuper:
+      handleObjCRequiresSuperAttr(S, D, Attr); break;
+      
   case AttributeList::AT_NSBridged:
     handleNSBridgedAttr(S, scope, D, Attr); break;
 
index e800a6a7a486d13e374c0c56f73a59c0d43d78db..709a868582696b5df36230696b21ef3eb441aa8d 100644 (file)
@@ -371,8 +371,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
   // Warn on deprecated methods under -Wdeprecated-implementations,
   // and prepare for warning on missing super calls.
   if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {
-    if (ObjCMethodDecl *IMD = 
-          IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()))
+    ObjCMethodDecl *IMD = 
+      IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());
+    
+    if (IMD)
       DiagnoseObjCImplementedDeprecations(*this, 
                                           dyn_cast<NamedDecl>(IMD), 
                                           MDecl->getLocation(), 0);
@@ -385,7 +387,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
       getCurFunction()->ObjCShouldCallSuperDealloc = 
         !(Context.getLangOpts().ObjCAutoRefCount ||
           Context.getLangOpts().getGC() == LangOptions::GCOnly) &&
-        MDecl->getMethodFamily() == OMF_dealloc;
+          MDecl->getMethodFamily() == OMF_dealloc;
+      if (!getCurFunction()->ObjCShouldCallSuperDealloc)
+        getCurFunction()->ObjCShouldCallSuperDealloc = 
+          (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>());
       getCurFunction()->ObjCShouldCallSuperFinalize =
         Context.getLangOpts().getGC() != LangOptions::NonGC &&
         MDecl->getMethodFamily() == OMF_finalize;
index 17850bb2d7ef82bbb09a3eef386ce717ed9f48d9..58e28a94044b79733a7873d38dfc463dcd2af156 100644 (file)
@@ -1780,6 +1780,14 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
   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;
 
diff --git a/test/SemaObjC/super-dealloc-attribute.m b/test/SemaObjC/super-dealloc-attribute.m
new file mode 100644 (file)
index 0000000..c2da8e9
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1  -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1  -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fobjc-arc -fsyntax-only -verify -Wno-objc-root-class %s
+
+// rdar://6386358
+@protocol NSObject // expected-note {{protocol is declared here}}
+- MyDealloc __attribute((objc_requires_super)); // expected-warning {{'objc_requires_super' attribute cannot be applied to methods in protocols}}
+@end
+
+@interface Root
+- MyDealloc __attribute((objc_requires_super));
+- (void)XXX __attribute((objc_requires_super));
+- (void) dealloc __attribute((objc_requires_super)); // expected-warning {{'objc_requires_super' attribute cannot be applied to dealloc}}
+@end
+
+@interface Baz : Root<NSObject>
+- MyDealloc;
+@end
+
+@implementation Baz
+-  MyDealloc {
+   [super MyDealloc];
+        return 0;
+}
+
+- (void)XXX {
+  [super MyDealloc];
+} // expected-warning {{method possibly missing a [super 'XXX'] call}}
+@end
+
index 02b81651d7a21d0d9f8cdbdedaa90e251913b426..ba65ec8c8d61aaa00a4eaa8d1ac2e9d5ad186ad9 100644 (file)
@@ -41,11 +41,11 @@ __attribute__((objc_root_class))
 @end
 
 // RUN: %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
-// CHECK: warn-missing-super.m:24:1: warning: method possibly missing a [super dealloc] call
+// CHECK: warn-missing-super.m:24:1: warning: method possibly missing a [super 'dealloc'] call
 // CHECK: 1 warning generated.
 
 // RUN: %clang_cc1 -fsyntax-only -fobjc-gc %s 2>&1 | FileCheck --check-prefix=CHECK-GC %s
-// CHECK-GC: warn-missing-super.m:24:1: warning: method possibly missing a [super dealloc] call
+// CHECK-GC: warn-missing-super.m:24:1: warning: method possibly missing a [super 'dealloc'] call
 // CHECK-GC: warn-missing-super.m:26:1: warning: method possibly missing a [super finalize] call
 // CHECK-GC: 2 warnings generated.
 
index cd2a6cca767a0435bed482dff81fa7e075d5a286..7383781535ecbf94a9c84c29f5868cee34de19f3 100644 (file)
@@ -15,5 +15,5 @@ template<typename T> struct shared_ptr {
 - (void)dealloc
 {
        constexpr shared_ptr<int> dummy;
-} // expected-warning {{method possibly missing a [super dealloc] call}}
+} // expected-warning {{method possibly missing a [super 'dealloc'] call}}
 @end