diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 5e8d130..9d44f7f 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -970,11 +970,32 @@ void NamedDecl::verifyLinkage() const {
 
 Optional<Visibility>
 NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
-  // Use the most recent declaration of a variable.
-  if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
-    if (Optional<Visibility> V = getVisibilityOf(Var, kind))
-      return V;
+  // Otherwise, just check the declaration itself first.
+  if (Optional<Visibility> V = getVisibilityOf(this, kind))
+    return V;
+
+  // If this is a member class of a specialization of a class template
+  // and the corresponding decl has explicit visibility, use that.
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
+    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+    if (InstantiatedFrom)
+      return getVisibilityOf(InstantiatedFrom, kind);
+  }
 
+  // If there wasn't explicit visibility there, and this is a
+  // specialization of a class template, check for visibility
+  // on the pattern.
+  if (const ClassTemplateSpecializationDecl *spec
+        = dyn_cast<ClassTemplateSpecializationDecl>(this))
+    return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
+                           kind);
+
+  // Use the most recent declaration.
+  const NamedDecl *MostRecent = cast<NamedDecl>(this->getMostRecentDecl());
+  if (MostRecent != this)
+    return MostRecent->getExplicitVisibility(kind);
+
+  if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
     if (Var->isStaticDataMember()) {
       VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
       if (InstantiatedFrom)
@@ -983,12 +1004,8 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
 
     return None;
   }
-  // Use the most recent declaration of a function, and also handle
-  // function template specializations.
+  // Also handle function template specializations.
   if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) {
-    if (Optional<Visibility> V = getVisibilityOf(fn, kind))
-      return V;
-
     // If the function is a specialization of a template with an
     // explicit visibility attribute, use that.
     if (FunctionTemplateSpecializationInfo *templateInfo
@@ -1005,30 +1022,10 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
     return None;
   }
 
-  // Otherwise, just check the declaration itself first.
-  if (Optional<Visibility> V = getVisibilityOf(this, kind))
-    return V;
-
   // The visibility of a template is stored in the templated decl.
   if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(this))
     return getVisibilityOf(TD->getTemplatedDecl(), kind);
 
-  // If there wasn't explicit visibility there, and this is a
-  // specialization of a class template, check for visibility
-  // on the pattern.
-  if (const ClassTemplateSpecializationDecl *spec
-        = dyn_cast<ClassTemplateSpecializationDecl>(this))
-    return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
-                           kind);
-
-  // If this is a member class of a specialization of a class template
-  // and the corresponding decl has explicit visibility, use that.
-  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
-    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
-    if (InstantiatedFrom)
-      return getVisibilityOf(InstantiatedFrom, kind);
-  }
-
   return None;
 }
 
diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp
index b9dec17..5511da7 100644
--- a/test/CodeGenCXX/visibility.cpp
+++ b/test/CodeGenCXX/visibility.cpp
@@ -1227,3 +1227,36 @@ namespace test65 {
 
   template class C<B<A>::InnerT>;
 }
+
+namespace test66 {
+  template <typename T>
+  struct __attribute__((visibility("default"))) barT {
+    static void zed() {}
+  };
+  class foo;
+  class __attribute__((visibility("default"))) foo;
+  template struct barT<foo>;
+  // CHECK: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+
+  template <int* I>
+  struct __attribute__((visibility("default"))) barI {
+    static void zed() {}
+  };
+  extern int I;
+  extern int I __attribute__((visibility("default")));
+  template struct barI<&I>;
+  // CHECK: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+
+  typedef void (*fType)(void);
+  template<fType F>
+  struct __attribute__((visibility("default"))) barF {
+    static void zed() {}
+  };
+  void F();
+  void F() __attribute__((visibility("default")));;
+  template struct barF<F>;
+  // CHECK: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+}
