diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 0e1c43c..bee3588 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1752,7 +1752,15 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
     return;
   }
 
-  VisibilityAttr *PrevAttr = D->getCanonicalDecl()->getAttr<VisibilityAttr>();
+  VisibilityAttr *PrevAttr = NULL;
+  for (Decl::redecl_iterator I = D->redecls_begin(), E = D->redecls_end();
+       I != E; ++I) {
+    Decl *PrevDecl = *I;
+    PrevAttr = PrevDecl->getAttr<VisibilityAttr>();
+    if (PrevAttr)
+      break;
+  }
+
   if (PrevAttr) {
     VisibilityAttr::VisibilityType PrevVisibility = PrevAttr->getVisibility();
     if (PrevVisibility != type) {
diff --git a/test/SemaCXX/attr-visibility.cpp b/test/SemaCXX/attr-visibility.cpp
new file mode 100644
index 0000000..99adaa6
--- /dev/null
+++ b/test/SemaCXX/attr-visibility.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <class Element>
+void foo() {
+}
+template <>
+ __attribute__((visibility("hidden")))  // expected-note {{previous attribute is here}}
+void foo<int>();
+
+template <>
+ __attribute__((visibility("default"))) // expected-error {{visibility does not match previous declaration}}
+void foo<int>() {
+}
