diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-10-22 01:21:15 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-10-22 01:21:15 +0000 |
commit | 7fda400103a5ae21fdc5f31b07c69cf60737cb29 (patch) | |
tree | 5505f3c8489cc275006469ee3da021a1d103e417 | |
parent | c7d0ab174c3f5150ba5667a96e621da9e057a3c3 (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.cpp | 37 | ||||
-rw-r--r-- | test/SemaObjC/attr-deprecated.m | 2 | ||||
-rw-r--r-- | test/SemaObjC/method-attributes.m | 5 |
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 |