forked from OSchip/llvm-project
Allow objc_requires_super to be used to check class methods as well.
Also, unify ObjCShouldCallSuperDealloc and ObjCShouldCallSuperFinalize. The two have identical behavior and will never be active at the same time. There's one last simplification now, which is that if we see a call to [super foo] and we are currently in a method named 'foo', we will /unconditionally/ clear the ObjCShouldCallSuper flag, rather than check first to see if we're in a method where calling super is required. There's no reason to pay the extra lookup price here. llvm-svn: 166285
This commit is contained in:
parent
555d1c5ab8
commit
2afd661685
|
@ -754,9 +754,6 @@ def warn_objc_missing_super_call : Warning<
|
|||
def error_dealloc_bad_result_type : Error<
|
||||
"dealloc return type must be correctly specified as 'void' under ARC, "
|
||||
"instead of %0">;
|
||||
def warn_objc_missing_super_finalize : Warning<
|
||||
"method possibly missing a [super finalize] call">,
|
||||
InGroup<ObjCMissingSuperCalls>;
|
||||
def warn_undeclared_selector : Warning<
|
||||
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
|
||||
def warn_implicit_atomic_property : Warning<
|
||||
|
|
|
@ -91,13 +91,10 @@ public:
|
|||
/// \brief Whether this function contains any indirect gotos.
|
||||
bool HasIndirectGoto;
|
||||
|
||||
/// A flag that is set when parsing a -dealloc method and no [super dealloc]
|
||||
/// call was found yet.
|
||||
bool ObjCShouldCallSuperDealloc;
|
||||
|
||||
/// A flag that is set when parsing a -finalize method and no [super finalize]
|
||||
/// call was found yet.
|
||||
bool ObjCShouldCallSuperFinalize;
|
||||
/// A flag that is set when parsing a method that must call super's
|
||||
/// implementation, such as \c -dealloc, \c -finalize, or any method marked
|
||||
/// with \c __attribute__((objc_requires_super)).
|
||||
bool ObjCShouldCallSuper;
|
||||
|
||||
/// \brief Used to determine if errors occurred in this function or block.
|
||||
DiagnosticErrorTrap ErrorTrap;
|
||||
|
@ -299,8 +296,7 @@ public:
|
|||
HasBranchProtectedScope(false),
|
||||
HasBranchIntoScope(false),
|
||||
HasIndirectGoto(false),
|
||||
ObjCShouldCallSuperDealloc(false),
|
||||
ObjCShouldCallSuperFinalize(false),
|
||||
ObjCShouldCallSuper(false),
|
||||
ErrorTrap(Diag) { }
|
||||
|
||||
virtual ~FunctionScopeInfo();
|
||||
|
|
|
@ -7944,23 +7944,16 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
if (Body)
|
||||
computeNRVO(Body, getCurFunction());
|
||||
}
|
||||
if (getCurFunction()->ObjCShouldCallSuperDealloc) {
|
||||
if (getCurFunction()->ObjCShouldCallSuper) {
|
||||
Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call)
|
||||
<< MD->getSelector().getAsString();
|
||||
getCurFunction()->ObjCShouldCallSuperDealloc = false;
|
||||
}
|
||||
if (getCurFunction()->ObjCShouldCallSuperFinalize) {
|
||||
Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize);
|
||||
getCurFunction()->ObjCShouldCallSuperFinalize = false;
|
||||
getCurFunction()->ObjCShouldCallSuper = false;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(!getCurFunction()->ObjCShouldCallSuperDealloc &&
|
||||
"This should only be set for ObjC methods, which should have been "
|
||||
"handled in the block above.");
|
||||
assert(!getCurFunction()->ObjCShouldCallSuperFinalize &&
|
||||
assert(!getCurFunction()->ObjCShouldCallSuper &&
|
||||
"This should only be set for ObjC methods, which should have been "
|
||||
"handled in the block above.");
|
||||
|
||||
|
|
|
@ -383,19 +383,23 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
|
|||
// Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
|
||||
// Only do this if the current class actually has a superclass.
|
||||
if (IC->getSuperClass()) {
|
||||
getCurFunction()->ObjCShouldCallSuperDealloc =
|
||||
!(Context.getLangOpts().ObjCAutoRefCount ||
|
||||
Context.getLangOpts().getGC() == LangOptions::GCOnly) &&
|
||||
MDecl->getMethodFamily() == OMF_dealloc;
|
||||
if (!getCurFunction()->ObjCShouldCallSuperDealloc) {
|
||||
IMD = IC->getSuperClass()->lookupMethod(MDecl->getSelector(),
|
||||
MDecl->isInstanceMethod());
|
||||
getCurFunction()->ObjCShouldCallSuperDealloc =
|
||||
(IMD && IMD->hasAttr<ObjCRequiresSuperAttr>());
|
||||
ObjCMethodFamily Family = MDecl->getMethodFamily();
|
||||
if (Family == OMF_dealloc) {
|
||||
if (!(getLangOpts().ObjCAutoRefCount ||
|
||||
getLangOpts().getGC() == LangOptions::GCOnly))
|
||||
getCurFunction()->ObjCShouldCallSuper = true;
|
||||
|
||||
} else if (Family == OMF_finalize) {
|
||||
if (Context.getLangOpts().getGC() != LangOptions::NonGC)
|
||||
getCurFunction()->ObjCShouldCallSuper = true;
|
||||
|
||||
} else {
|
||||
const ObjCMethodDecl *SuperMethod =
|
||||
IC->getSuperClass()->lookupMethod(MDecl->getSelector(),
|
||||
MDecl->isInstanceMethod());
|
||||
getCurFunction()->ObjCShouldCallSuper =
|
||||
(SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
|
||||
}
|
||||
getCurFunction()->ObjCShouldCallSuperFinalize =
|
||||
Context.getLangOpts().getGC() != LangOptions::NonGC &&
|
||||
MDecl->getMethodFamily() == OMF_finalize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1772,20 +1772,10 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
|
|||
|
||||
// We are in a method whose class has a superclass, so 'super'
|
||||
// is acting as a keyword.
|
||||
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;
|
||||
if (Method->getSelector() == Sel)
|
||||
getCurFunction()->ObjCShouldCallSuper = false;
|
||||
|
||||
if (Method->isInstanceMethod()) {
|
||||
// Since we are in an instance method, this is an instance
|
||||
// message to the superclass instance.
|
||||
QualType SuperTy = Context.getObjCInterfaceType(Super);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
- (void) MyDeallocMeth; // Method in root is not annotated.
|
||||
- (void) AnnotMyDeallocMeth __attribute((objc_requires_super));
|
||||
- (void) AnnotMyDeallocMethCAT NS_REQUIRES_SUPER;
|
||||
|
||||
+ (void)registerClass:(id)name __attribute((objc_requires_super));
|
||||
@end
|
||||
|
||||
@interface Baz : Root<NSObject>
|
||||
|
@ -41,6 +43,8 @@
|
|||
- (void) MyDeallocMeth {} // No warning here.
|
||||
- (void) AnnotMyDeallocMeth{} // expected-warning {{method possibly missing a [super AnnotMyDeallocMeth] call}}
|
||||
- (void) AnnotMeth{}; // No warning here. Annotation is in its class.
|
||||
|
||||
+ (void)registerClass:(id)name {} // expected-warning {{method possibly missing a [super registerClass:] call}}
|
||||
@end
|
||||
|
||||
@interface Bar : Baz
|
||||
|
@ -64,3 +68,20 @@
|
|||
- (void) AnnotMyDeallocMethCAT{}; // expected-warning {{method possibly missing a [super AnnotMyDeallocMethCAT] call}}
|
||||
- (void) AnnotMethCAT {};
|
||||
@end
|
||||
|
||||
|
||||
@interface Valid : Baz
|
||||
@end
|
||||
|
||||
@implementation Valid
|
||||
|
||||
- (void)MyDeallocMeth {
|
||||
[super MyDeallocMeth]; // no-warning
|
||||
}
|
||||
|
||||
|
||||
+ (void)registerClass:(id)name {
|
||||
[super registerClass:name]; // no-warning
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue