refactoring + objective-C specific test for my last patch.
// rdar://12233989

llvm-svn: 163338
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5fdb09c..919bd68 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7244,6 +7244,14 @@
   }
 
   AvailabilityResult getCurContextAvailability() const;
+  
+  const DeclContext *getCurObjCLexicalContext() const {
+    const DeclContext *DC = getCurLexicalContext();
+    // A category implicitly has the attribute of the interface.
+    if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))
+      DC = CatD->getClassInterface();
+    return DC;
+  }
 };
 
 /// \brief RAII object that enters a new expression evaluation context.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 711ea4c..b3db840 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -11101,10 +11101,6 @@
 }
 
 AvailabilityResult Sema::getCurContextAvailability() const {
-  const Decl *D = cast<Decl>(getCurLexicalContext());
-  // A category implicitly has the availability of the interface.
-  if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
-    D = CatD->getClassInterface();
-  
+  const Decl *D = cast<Decl>(getCurObjCLexicalContext());
   return D->getAvailability();
 }
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a67d5c6..cfa9ccb 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -69,10 +69,7 @@
 static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
   // Warn if this is used but marked unused.
   if (D->hasAttr<UnusedAttr>()) {
-    const Decl *DC = cast<Decl>(S.getCurLexicalContext());
-    // A category implicitly has the availability of the interface.
-    if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))
-      DC = CatD->getClassInterface();
+    const Decl *DC = cast<Decl>(S.getCurObjCLexicalContext());
     if (!DC->hasAttr<UnusedAttr>())
       S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
   }
diff --git a/clang/test/SemaObjC/unused.m b/clang/test/SemaObjC/unused.m
index 5c7542b..efaf9c8 100644
--- a/clang/test/SemaObjC/unused.m
+++ b/clang/test/SemaObjC/unused.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -Wunused -Wunused-parameter -fsyntax-only -Wno-objc-root-class %s
+// RUN: %clang_cc1 -verify -Wused-but-marked-unused -Wno-objc-protocol-method-implementation -Wunused -Wunused-parameter -fsyntax-only -Wno-objc-root-class %s
 
 int printf(const char *, ...);
 
@@ -53,3 +53,17 @@
 
 // rdar://10777111
 static NSString *x = @"hi"; // expected-warning {{unused variable 'x'}}
+
+// rdar://12233989
+@interface TestTransitiveUnused
+- (void) a __attribute__((unused));
+- (void) b __attribute__((unused));
+@end
+
+@interface TestTransitiveUnused(CAT)
+@end
+
+@implementation TestTransitiveUnused(CAT)
+- (void) b {}
+- (void) a { [self b]; }
+@end