Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 221579)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -3818,6 +3818,9 @@
     InGroup<DeprecatedDeclarations>;
 def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
     InGroup<DeprecatedDeclarations>;
+def warn_deprecated_anonymous_namespace : Warning<
+  "'deprecated' attribute on anonymous namespace ignored">,
+  InGroup<IgnoredAttributes>;
 def warn_deprecated_fwdclass_message : Warning<
     "%0 may be deprecated because the receiver type is unknown">,
     InGroup<DeprecatedDeclarations>;
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp	(revision 221579)
+++ lib/Sema/SemaDeclAttr.cpp	(working copy)
@@ -4139,6 +4139,19 @@
   D->addAttr(RCA);
 }
 
+static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
+    if (NSD->isAnonymousNamespace()) {
+      S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace);
+      // Do not want to attach the attribute to the namespace because that will
+      // cause confusing diagnostic reports for uses of declarations within the
+      // namespace.
+      return;
+    }
+  }
+  handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
+}
+
 /// Handles semantic checking for features that are common to all attributes,
 /// such as checking whether a parameter was properly specified, or the correct
 /// number of arguments were passed, etc.
@@ -4283,7 +4296,7 @@
     handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
     break;
   case AttributeList::AT_Deprecated:
-    handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
+    handleDeprecatedAttr(S, D, Attr);
     break;
   case AttributeList::AT_Destructor:
     handleDestructorAttr(S, D, Attr);
@@ -4928,18 +4941,22 @@
   diag.Triggered = true;
 }
 
-
-static bool isDeclDeprecated(Decl *D) {
+static const Decl *getDeclDeprecated(const Decl *D) {
   do {
     if (D->isDeprecated())
-      return true;
+      return D;
     // A category implicitly has the availability of the interface.
-    if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
-      return CatD->getClassInterface()->isDeprecated();
+    if (const auto *CatD = dyn_cast<ObjCCategoryDecl>(D))
+      if (CatD->getClassInterface()->isDeprecated())
+        return CatD->getClassInterface();
   } while ((D = cast_or_null<Decl>(D->getDeclContext())));
-  return false;
+  return nullptr;
 }
 
+static bool isDeclDeprecated(const Decl *D) {
+  return getDeclDeprecated(D) != nullptr;
+}
+
 static bool isDeclUnavailable(Decl *D) {
   do {
     if (D->isUnavailable())
@@ -4966,6 +4983,14 @@
   // Matches diag::note_availability_specified_here.
   unsigned available_here_select_kind;
 
+  // A declaration can be deprecated by virtue of its declaration context,
+  // (not lexical declaration though) being deprecated. For instance, a static
+  // data member of a deprecated class, or a declaration within a deprecated
+  // namespace. In these instances, we want to report on the declaration as
+  // being deprecated, but we want the note to point to the context which
+  // caused the deprecation.
+  NamedDecl *NoteDecl = const_cast<NamedDecl *>(D);
+
   // Don't warn if our current context is deprecated or unavailable.
   switch (K) {
   case DelayedDiagnostic::Deprecation:
@@ -4977,6 +5002,13 @@
     diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
     property_note_select = /* deprecated */ 0;
     available_here_select_kind = /* deprecated */ 2;
+
+    // Check whether the deprecation is due to the declaration context, and if
+    // it is, pick a new note declaration.
+    if (const auto *Why = dyn_cast<NamedDecl>(getDeclDeprecated(D))) {
+      if (Why != D)
+        NoteDecl = const_cast<NamedDecl *>(Why);
+    }
     break;
 
   case DelayedDiagnostic::Unavailable:
@@ -4994,24 +5026,25 @@
     llvm_unreachable("Neither a deprecation or unavailable kind");
   }
 
-  DeclarationName Name = D->getDeclName();
   if (!Message.empty()) {
-    S.Diag(Loc, diag_message) << Name << Message;
+    S.Diag(Loc, diag_message) << D << Message;
     if (ObjCProperty)
       S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
           << ObjCProperty->getDeclName() << property_note_select;
   } else if (!UnknownObjCClass) {
-    S.Diag(Loc, diag) << Name;
+    S.Diag(Loc, diag) << D;
     if (ObjCProperty)
       S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
           << ObjCProperty->getDeclName() << property_note_select;
   } else {
-    S.Diag(Loc, diag_fwdclass_message) << Name;
+    S.Diag(Loc, diag_fwdclass_message) << D;
     S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
   }
 
-  S.Diag(D->getLocation(), diag::note_availability_specified_here)
-      << D << available_here_select_kind;
+  // FIXME: This uses the declaration location for the diagnostic instead of
+  // the attribute location.
+  S.Diag(NoteDecl->getLocation(), diag::note_availability_specified_here)
+      << NoteDecl << available_here_select_kind;
 }
 
 static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 221579)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -95,12 +95,13 @@
       D = IDecl->getDefinition();
   }
   AvailabilityResult Result = D->getAvailability(&Message);
-  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
+  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
     if (Result == AR_Available) {
       const DeclContext *DC = ECD->getDeclContext();
       if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC))
         Result = TheEnumDecl->getAvailability(&Message);
     }
+  }
 
   const ObjCPropertyDecl *ObjCPDecl = nullptr;
   if (Result == AR_Deprecated || Result == AR_Unavailable) {
@@ -113,6 +114,22 @@
     }
   }
   
+  // A declaration can be deprecated by virtue of its declaration context being
+  // deprecated. (Static data member of a deprecated class, declaration within
+  // a deprecated namespace, etc. So if the declaration is available, check the
+  // declaration context chain.
+  // FIXME: The following code only handles namespace members, and is not as
+  // fully-generalized as it could be. It should also handle static members of
+  // a deprecated class, types declared within a deprecated class, and
+  // enumerators within a deprecated enumeration.
+  NamedDecl *TD = D;
+  while (TD && Result == AR_Available) {
+    if (TD = dyn_cast<NamespaceDecl>(TD->getDeclContext())) {
+        Result = TD->getAvailability(&Message);
+      } else
+        break;
+  }
+
   switch (Result) {
     case AR_Available:
     case AR_NotYetIntroduced:
Index: test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp
===================================================================
--- test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp	(revision 221579)
+++ test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp	(working copy)
@@ -21,8 +21,7 @@
 template <typename T> class X {};
 template <> class [[deprecated]] X<int> {}; // expected-note {{'X<int>' has been explicitly marked deprecated here}}
 X<char> x1;
-// FIXME: The diagnostic here could be much better by mentioning X<int>.
-X<int> x2; // expected-warning {{'X' is deprecated}}
+X<int> x2; // expected-warning {{'X<int>' is deprecated}}
 
 template <typename T> class [[deprecated]] X2 {};
 template <> class X2<int> {};
Index: test/Sema/attr-deprecated.c
===================================================================
--- test/Sema/attr-deprecated.c	(revision 221579)
+++ test/Sema/attr-deprecated.c	(working copy)
@@ -102,9 +102,9 @@
         test19;
 
 // rdar://problem/8518751
-enum __attribute__((deprecated)) Test20 { // expected-note {{'Test20' has been explicitly marked deprecated here}}
+enum __attribute__((deprecated)) Test20 { // expected-note {{'Test20' has been explicitly marked deprecated here}} expected-note {{'Test20' has been explicitly marked deprecated here}}
   test20_a __attribute__((deprecated)), // expected-note {{'test20_a' has been explicitly marked deprecated here}}
-  test20_b // expected-note {{'test20_b' has been explicitly marked deprecated here}}
+  test20_b
 };
 void test20() {
   enum Test20 f; // expected-warning {{'Test20' is deprecated}}
Index: test/Sema/attr-unavailable-message.c
===================================================================
--- test/Sema/attr-unavailable-message.c	(revision 221579)
+++ test/Sema/attr-unavailable-message.c	(working copy)
@@ -33,8 +33,8 @@
 }
 
 // rdar://10201690
-enum foo {
-    a = 1, // expected-note {{'a' has been explicitly marked deprecated here}}
+enum foo { // expected-note {{'foo' has been explicitly marked deprecated here}}
+    a = 1,
     b __attribute__((deprecated())) = 2, // expected-note {{'b' has been explicitly marked deprecated here}}
     c = 3
 }__attribute__((deprecated()));
Index: test/SemaCXX/attr-deprecated.cpp
===================================================================
--- test/SemaCXX/attr-deprecated.cpp	(revision 221579)
+++ test/SemaCXX/attr-deprecated.cpp	(working copy)
@@ -193,8 +193,8 @@
 
 // rdar://problem/8518751
 namespace test6 {
-  enum __attribute__((deprecated)) A { // expected-note {{'A' has been explicitly marked deprecated here}}
-    a0 // expected-note {{'a0' has been explicitly marked deprecated here}}
+  enum __attribute__((deprecated)) A { // expected-note {{'A' has been explicitly marked deprecated here}} expected-note {{'A' has been explicitly marked deprecated here}}
+    a0
   };
   void testA() {
     A x; // expected-warning {{'A' is deprecated}}
@@ -212,8 +212,8 @@
   }
 
   template <class T> struct C {
-    enum __attribute__((deprecated)) Enum { // expected-note {{'Enum' has been explicitly marked deprecated here}}
-      c0 // expected-note {{'c0' has been explicitly marked deprecated here}}
+    enum __attribute__((deprecated)) Enum { // expected-note {{'Enum' has been explicitly marked deprecated here}} expected-note {{'Enum' has been explicitly marked deprecated here}}
+      c0
     };
   };
   void testC() {
Index: test/SemaCXX/cxx-deprecated.cpp
===================================================================
--- test/SemaCXX/cxx-deprecated.cpp	(revision 0)
+++ test/SemaCXX/cxx-deprecated.cpp	(working copy)
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
+
+namespace [[deprecated]] foo { // expected-note {{'foo' has been explicitly marked deprecated here}}
+int x;
+}
+
+namespace [[deprecated]] {  // expected-warning {{'deprecated' attribute on anonymous namespace ignored}}
+int y;
+}
+
+namespace [[deprecated]] outer { // expected-note {{'outer' has been explicitly marked deprecated here}}
+namespace inner {
+int z;
+}
+}
+
+struct [[deprecated]] S { // note-FIXME {{'S' has been explicitly marked deprecated here}}
+  static const int i = 12;
+};
+
+struct [[deprecated]] OuterCls { // note-FIXME {{'OuterCls' has been explicitly marked deprecated here}}
+  struct InnerCls {};
+};
+
+void f() {
+  foo::x = 12; // expected-warning {{'x' is deprecated}}
+  y = 12; // Ok; anonymous namespaces cannot be deprecated.
+
+  enum test {
+    bing [[deprecated]] // expected-note {{'bing' has been explicitly marked deprecated here}}
+  } t;
+
+  t = bing; // expected-warning {{'bing' is deprecated}}
+
+  int i = S::i; // warning-FIXME {{'i' is deprecated}}
+
+  using namespace outer::inner;
+  int j = z; // expected-warning {{'z' is deprecated}}
+
+  OuterCls::InnerCls I; // warning-FIXME {{'OuterCls::InnerCls' is deprecated}}
+}
