forked from OSchip/llvm-project
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:
parent
b8da426285
commit
512a4cc967
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue