objective-C: introduce __attribute((objc_requires_super)) on method
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
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b3db840..5ed06d6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7832,7 +7832,8 @@
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) {
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 8ffffab..119ce7d 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -3974,6 +3974,33 @@
::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 @@
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;
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index e800a6a..709a868 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -371,8 +371,10 @@
// 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 @@
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;
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 17850bb..58e28a9 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1780,6 +1780,14 @@
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;