diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-09-07 23:46:23 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-09-07 23:46:23 +0000 |
commit | 841011373b345cf79d0da4b7242dcf2869a43502 (patch) | |
tree | 3fbcdca9e5e0bbcef3e0300c8bafadc5803b1aa2 /lib/Sema | |
parent | f9fdcc0531ca53651c1d7d0877290e232cb5468d (diff) |
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
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 8 |
4 files changed, 48 insertions, 4 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b3db840397..5ed06d6daa 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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) { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 8ffffab8b5..119ce7dfff 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index e800a6a7a4..709a868582 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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; diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 17850bb2d7..58e28a9404 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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; |