aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-10-22 01:21:15 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-10-22 01:21:15 +0000
commit7fda400103a5ae21fdc5f31b07c69cf60737cb29 (patch)
tree5505f3c8489cc275006469ee3da021a1d103e417
parentc7d0ab174c3f5150ba5667a96e621da9e057a3c3 (diff)
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142709 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclObjC.cpp37
-rw-r--r--test/SemaObjC/attr-deprecated.m2
-rw-r--r--test/SemaObjC/method-attributes.m5
3 files changed, 35 insertions, 9 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 669ea8f32a..69d9c1d998 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -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);
diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m
index ca26759928..e90bbf94ea 100644
--- a/test/SemaObjC/attr-deprecated.m
+++ b/test/SemaObjC/attr-deprecated.m
@@ -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.
}
diff --git a/test/SemaObjC/method-attributes.m b/test/SemaObjC/method-attributes.m
index 9157fcfefe..f7f647bd46 100644
--- a/test/SemaObjC/method-attributes.m
+++ b/test/SemaObjC/method-attributes.m
@@ -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