diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 3e4c2cb..c3d9ff1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -273,6 +273,45 @@ getLVForTemplateParameterList(const TemplateParameterList *params) {
 static LinkageInfo getLVForDecl(const NamedDecl *D,
                                 LVComputationKind computation);
 
+static const FunctionDecl *getOutermostFunctionContext(const Decl *D) {
+  const FunctionDecl *Ret = NULL;
+  const DeclContext *DC = D->getDeclContext();
+  while (DC->getDeclKind() != Decl::TranslationUnit) {
+    const FunctionDecl *F = dyn_cast<FunctionDecl>(DC);
+    if (F)
+      Ret = F;
+    DC = DC->getParent();
+  }
+  return Ret;
+}
+
+/// Get the linkage and visibility to be used when this type is a template
+/// argument. This is normally just the linkage and visibility of the type,
+/// but for function local types we need to check the linkage and visibility
+/// of the function.
+static LinkageInfo getLIForTemplateTypeArgument(QualType T) {
+  LinkageInfo LI = T->getLinkageAndVisibility();
+  if (LI.getLinkage() != NoLinkage)
+    return LI;
+
+  const TagType *TT = dyn_cast<TagType>(T);
+  if (!TT)
+    return LI;
+
+  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TT->getDecl());
+  if (!RD)
+    return LI;
+
+  const FunctionDecl *FD = getOutermostFunctionContext(RD);
+  if (!FD)
+    return LI;
+
+  if (!FD->isInlined())
+    return LI;
+
+  return FD->getLinkageAndVisibility();
+}
+
 /// \brief Get the most restrictive linkage for the types and
 /// declarations in the given template argument list.
 ///
@@ -291,7 +330,7 @@ getLVForTemplateArgumentList(ArrayRef<TemplateArgument> args) {
       continue;
 
     case TemplateArgument::Type:
-      LV.merge(arg.getAsType()->getLinkageAndVisibility());
+      LV.merge(getLIForTemplateTypeArgument(arg.getAsType()));
       continue;
 
     case TemplateArgument::Declaration:
diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp
new file mode 100644
index 0000000..a940e89
--- /dev/null
+++ b/test/CodeGenCXX/linkage.cpp
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-optzns %s -o - | FileCheck %s
+
+// CHECK: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_(
+// CHECK: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_(
+// CHECK: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1S_1EEvT_(
+// CHECK: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1T_4EEvv(
+// CHECK: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hE_2vE1T_3EEvv(
+// CHECK: define internal void @_ZN5test21fIZNS_L1gEvE1S_0EEvT_(
+// CHECK: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_(
+
+namespace test1 {
+  template <typename T> void f(T) {}
+  inline void *g() {
+    struct S {
+    } s;
+    return reinterpret_cast<void *>(f<S>);
+  }
+  void *h() { return g(); }
+}
+
+namespace test2 {
+  template <typename T> void f(T) {}
+  static inline void *g() {
+    struct S {
+    } s;
+    return reinterpret_cast<void *>(f<S>);
+  }
+  void *h() { return g(); }
+}
+
+namespace test3 {
+  template <typename T> void f(T) {}
+  void *g() {
+    struct S {
+    } s;
+    return reinterpret_cast<void *>(f<S>);
+  }
+  void *h() { return g(); }
+}
+
+namespace test4 {
+  template <typename T> void f(T) {}
+  template <int N> inline void *g() {
+    struct S {
+    } s;
+    return reinterpret_cast<void *>(f<S>);
+  }
+  extern template void *g<1>();
+  template void *g<1>();
+}
+
+namespace test5 {
+  template <typename T> void f(T) {}
+  template <int N> inline void *g() {
+    struct S {
+    } s;
+    return reinterpret_cast<void *>(f<S>);
+  }
+  extern template void *g<1>();
+  void *h() { return g<1>(); }
+}
+
+namespace test6 {
+  template <typename T> void f() {}
+
+  inline void *g() {
+    struct S {
+      void *h() {
+        struct T {
+        };
+        return (void *)f<T>;
+      }
+    } s;
+    return s.h();
+  }
+
+  void *h() { return g(); }
+}
+
+namespace test7 {
+  template <typename T> void f() {}
+
+  void *g() {
+    struct S {
+      void *h() {
+        struct T {
+        };
+        return (void *)f<T>;
+      }
+    } s;
+    return s.h();
+  }
+
+  void *h() { return g(); }
+}
