]> granicus.if.org Git - clang/commitdiff
objc: private methods can have their attributes, no diagnostic is required.
authorFariborz Jahanian <fjahanian@apple.com>
Sat, 22 Oct 2011 01:21:15 +0000 (01:21 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Sat, 22 Oct 2011 01:21:15 +0000 (01:21 +0000)
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

lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/attr-deprecated.m
test/SemaObjC/method-attributes.m

index 669ea8f32a93cae604b979390c0bda8748e0a01e..69d9c1d9980dd80c39ef90d0d2d5e0972bf235fe 100644 (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);
index ca267599288e8c45f7b2b30047202ccf9c889816..e90bbf94eab2148cf4750342363af1db127e16b7 100644 (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.
 }
 
index 9157fcfefe114700de252380f7ff10bdf3424fa1..f7f647bd4603fbe59890ecb442fa3d4d511b7b1e 100644 (file)
 - (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