objc: private methods can have their attributes, no diagnostic is required.

None private methods if their implementation have attribute, they must exactly 
match those in their declarations. // rdar://10271563

llvm-svn: 142709
This commit is contained in:
Fariborz Jahanian 2011-10-22 01:21:15 +00:00
parent b8da426285
commit 512a4cc967
3 changed files with 35 additions and 9 deletions

View File

@ -2318,13 +2318,32 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
}
static inline
bool containsInvalidMethodImplAttribute(const AttrVec &A) {
// The 'ibaction' attribute is allowed on method definitions because of
// how the IBAction macro is used on both method declarations and definitions.
// If the method definitions contains any other attributes, return true.
for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
if ((*i)->getKind() != attr::IBAction)
bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD,
const AttrVec &A) {
// If method is only declared in implementation (private method),
// or method declared in interface has no attribute.
// No need to issue any diagnostics on method definition with attributes.
if (!IMD || !IMD->hasAttrs())
return false;
const AttrVec &D = IMD->getAttrs();
if (D.size() != A.size())
return true;
// attributes on method declaration and definition must match exactly.
// Note that we have at most a couple of attributes on methods, so this
// n*n search is good enough.
for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) {
bool match = false;
for (AttrVec::const_iterator i1 = D.begin(), e1 = D.end(); i1 != e1; ++i1) {
if ((*i)->getKind() == (*i1)->getKind()) {
match = true;
break;
}
}
if (!match)
return true;
}
return false;
}
@ -2656,8 +2675,12 @@ Decl *Sema::ActOnMethodDeclaration(
ImpDecl->addClassMethod(ObjCMethod);
}
ObjCMethodDecl *IMD = 0;
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())
IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
ObjCMethod->isInstanceMethod());
if (ObjCMethod->hasAttrs() &&
containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs()))
Diag(EndLoc, diag::warn_attribute_method_def);
} else {
cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);

View File

@ -9,7 +9,7 @@
@implementation A
+ (void)F __attribute__((deprecated))
{ // expected-warning {{method attribute can only be specified on method declarations}}
{
[self F]; // no warning, since the caller is also deprecated.
}

View File

@ -16,10 +16,11 @@
- (int) foo: (int)arg1;
- (int) foo2: (int)arg1 __attribute__((deprecated)) __attribute__((unavailable));
- (int) foo3: (int)arg1 __attribute__((deprecated)) __attribute__((unavailable)) __attribute__((ns_consumes_self));
@end
@implementation INTF
- (int) foo: (int)arg1 __attribute__((deprecated)){ // expected-warning {{method attribute can only be specified}}
- (int) foo: (int)arg1 __attribute__((deprecated)){
return 10;
}
- (int) foo1: (int)arg1 {
@ -28,5 +29,7 @@
- (int) foo2: (int)arg1 __attribute__((deprecated)) { // expected-warning {{method attribute can only be specified}}
return 10;
}
- (int) foo3: (int)arg1 __attribute__((deprecated)) __attribute__((unavailable)) __attribute__((ns_consumes_self)) {return 0; }
- (void) dep __attribute__((deprecated)) { } // OK private methodn
@end