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];
"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, "
"%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">;
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) {
::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)) {
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;
// 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);
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;
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;
--- /dev/null
+// 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
+
@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.
- (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