diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 6996207..af513fe 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -102,6 +102,21 @@ inline Linkage minLinkage(Linkage L1, Linkage L2) {
   return L1 < L2 ? L1 : L2;
 }
 
+inline Linkage getWithLinkageVisibility(Linkage Linkage, bool Visible) {
+  switch (Linkage) {
+  case NoLinkage:
+  case VisibleNoLinkage:
+    return Visible ? VisibleNoLinkage : NoLinkage;
+
+  case InternalLinkage:
+    assert(!Visible);
+    return InternalLinkage;
+
+  case UniqueExternalLinkage:
+  case ExternalLinkage:
+    return Visible ? ExternalLinkage : UniqueExternalLinkage;
+  }
+}
 } // end namespace clang
 
 #endif // LLVM_CLANG_BASIC_LINKAGE_H
diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h
index 604f05b..57fe3c7 100644
--- a/include/clang/Basic/Visibility.h
+++ b/include/clang/Basic/Visibility.h
@@ -89,6 +89,15 @@ public:
     mergeLinkage(other.getLinkage());
   }
 
+  void mergeLinkageVisibility(Linkage L) {
+    Linkage ThisL = getLinkage();
+    bool Visible = isExternallyVisible(L) && isExternallyVisible(ThisL);
+    setLinkage(getWithLinkageVisibility(ThisL, Visible));
+  }
+  void mergeLinkageVisibility(LinkageInfo Other) {
+    mergeLinkageVisibility(Other.getLinkage());
+  }
+
   /// Merge in the visibility 'newVis'.
   void mergeVisibility(Visibility newVis, bool newExplicit) {
     Visibility oldVis = getVisibility();
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 41b6da3..a64ae1d 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -471,7 +471,9 @@ static void mergeTemplateLV(LinkageInfo &LV,
   // instantiation with a visibility attribute.
   const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
   LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
-  LV.mergeMaybeWithVisibility(argsLV, considerVisibility);
+  if (considerVisibility)
+    LV.mergeVisibility(argsLV);
+  LV.mergeLinkageVisibility(argsLV);
 }
 
 static bool useInlineVisibilityHidden(const NamedDecl *D) {
@@ -863,8 +865,9 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
     // Modify the variable's linkage by its type, but ignore the
     // type's visibility unless it's a definition.
     LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
-    LV.mergeMaybeWithVisibility(typeLV,
-                 !LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit());
+    if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
+      LV.mergeVisibility(typeLV);
+    LV.mergeLinkageVisibility(typeLV);
 
     if (isExplicitMemberSpecialization(VD)) {
       explicitSpecSuppressor = VD;
diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp
index ed6e967..a811575 100644
--- a/test/SemaCXX/linkage2.cpp
+++ b/test/SemaCXX/linkage2.cpp
@@ -186,3 +186,18 @@ namespace test17 {
     g();
   }
 }
+
+namespace test18 {
+  template <typename T> struct foo {
+    template <T *P> static void f() {}
+    static void *g() { return (void *)f<&x>; }
+    static T x;
+  };
+  template <typename T> T foo<T>::x;
+  inline void *f() {
+    struct S {
+    };
+    return foo<S>::g();
+  }
+  void *h() { return f(); }
+}
