diff --git lib/AST/MicrosoftMangle.cpp lib/AST/MicrosoftMangle.cpp
index 6250f61..cbe501c 100644
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -117,6 +117,26 @@ static bool isInCLinkageSpecification(const Decl *D) {
   return false;
 }
 
+static const TemplateDecl *
+isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
+  // Check if we have a function template.
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
+    if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
+      TemplateArgs = FD->getTemplateSpecializationArgs();
+      return TD;
+    }
+  }
+
+  // Check if we have a class template.
+  if (const ClassTemplateSpecializationDecl *Spec =
+        dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+    TemplateArgs = &Spec->getTemplateArgs();
+    return Spec->getSpecializedTemplate();
+  }
+
+  return 0;
+}
+
 bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
   // In C, functions with no attributes never need to be mangled. Fastpath them.
   if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
@@ -280,10 +300,10 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
     char Encoding[16];
     char *EndPtr = Encoding+sizeof(Encoding);
     char *CurPtr = EndPtr;
-    while (Number) {
+    do {
       *--CurPtr = 'A' + (Number % 16);
       Number /= 16;
-    }
+    } while (Number);
     Out.write(CurPtr, EndPtr-CurPtr);
     Out << '@';
   }
@@ -295,6 +315,34 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
   //  <unqualified-name> ::= <operator-name>
   //                     ::= <ctor-dtor-name>
   //                     ::= <source-name>
+
+  // Check if we have a template.
+  const TemplateArgumentList *TemplateArgs = 0;
+  if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+    // <template-name> ::= ?$ <name><template-argument-list> @
+    Out << "?$";
+    mangleUnqualifiedName(TD->getTemplatedDecl(), Name);
+
+    const TemplateArgumentList &Args = *TemplateArgs;
+    for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+      const TemplateArgument& Arg = Args[i];
+
+      switch (Arg.getKind()) {
+      case TemplateArgument::Type:
+        mangleType(Arg.getAsType());
+        break;
+      case TemplateArgument::Integral:
+        Out << "$0";
+        mangleNumber(Arg.getAsIntegral()->getLimitedValue());
+        break;
+      default:
+        llvm_unreachable("This template argument type is not yet supported!");
+      }
+    }
+    Out << "@";
+    return;
+  }
+
   switch (Name.getNameKind()) {
     case DeclarationName::Identifier: {
       if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
diff --git test/CodeGenCXX/mangle-ms-templates.cpp test/CodeGenCXX/mangle-ms-templates.cpp
new file mode 100644
index 0000000..357cc3b
--- /dev/null
+++ test/CodeGenCXX/mangle-ms-templates.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+template<typename T>
+class Class {
+ public:
+  void method() {}
+};
+
+class Typename { };
+
+template<typename T>
+class Nested { };
+
+template<bool flag>
+class BoolTemplate {
+ public:
+  BoolTemplate() {}
+};
+
+void template_mangling() {
+  Class<Typename> c1;
+  c1.method();
+// CHECK: call {{.*}} @"\01?method@?$Class@VTypename@@@@QAEXXZ"
+
+  Class<Nested<Typename> > c2;
+  c2.method();
+// CHECK: call {{.*}} @"\01?method@?$Class@V?$Nested@VTypename@@@@@@QAEXXZ"
+
+  BoolTemplate<false> _false;
+// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
+
+  BoolTemplate<true> _true;
+// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
+}
+
+namespace space {
+  template<class T> const T& foo(const T& l) { return l; }
+}
+// CHECK: "\01??$foo@H@space@@YAABHABH@Z"
+
+void use() {
+  space::foo(42);
+}
