forked from OSchip/llvm-project
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 llvm-svn: 163434
This commit is contained in:
parent
625fca7c5a
commit
566fff0dac
|
@ -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];
|
||||
|
|
|
@ -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">;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue