diff options
-rw-r--r-- | include/clang/Basic/Attr.td | 5 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 8 | ||||
-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 | ||||
-rw-r--r-- | test/SemaObjC/super-dealloc-attribute.m | 31 | ||||
-rw-r--r-- | test/SemaObjC/warn-missing-super.m | 4 | ||||
-rw-r--r-- | test/SemaObjCXX/warn-missing-super.mm | 2 |
9 files changed, 94 insertions, 8 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index fade83ef93..7406ce2647 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -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]; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 75c98b1159..2b6cb4c34e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; 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; diff --git a/test/SemaObjC/super-dealloc-attribute.m b/test/SemaObjC/super-dealloc-attribute.m new file mode 100644 index 0000000000..c2da8e92af --- /dev/null +++ b/test/SemaObjC/super-dealloc-attribute.m @@ -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 + diff --git a/test/SemaObjC/warn-missing-super.m b/test/SemaObjC/warn-missing-super.m index 02b81651d7..ba65ec8c8d 100644 --- a/test/SemaObjC/warn-missing-super.m +++ b/test/SemaObjC/warn-missing-super.m @@ -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. diff --git a/test/SemaObjCXX/warn-missing-super.mm b/test/SemaObjCXX/warn-missing-super.mm index cd2a6cca76..7383781535 100644 --- a/test/SemaObjCXX/warn-missing-super.mm +++ b/test/SemaObjCXX/warn-missing-super.mm @@ -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 |