Index: include/clang/AST/PrettyPrinter.h
===================================================================
--- include/clang/AST/PrettyPrinter.h
+++ include/clang/AST/PrettyPrinter.h
@@ -52,7 +52,7 @@
       Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
       IncludeNewlines(true), MSVCFormatting(false),
       ConstantsAsWritten(false), SuppressImplicitBase(false),
-      FullyQualifiedName(false) { }
+      FullyQualifiedName(false), SuppressTemplateArgs(false) { }
 
   /// Adjust this printing policy for cases where it's known that we're
   /// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -225,6 +225,9 @@
   /// When true, print the fully qualified name of function declarations.
   /// This is the opposite of SuppressScope and thus overrules it.
   bool FullyQualifiedName : 1;
+
+  /// When true, suppresses printing template arguments
+  bool SuppressTemplateArgs : 1;
 };
 
 } // end namespace clang
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1538,6 +1538,9 @@
 template<typename TA>
 static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
                     const PrintingPolicy &Policy, bool SkipBrackets) {
+  if (Policy.SuppressTemplateArgs)
+    return;
+
   const char *Comma = Policy.MSVCFormatting ? "," : ", ";
   if (!SkipBrackets)
     OS << '<';
Index: unittests/AST/NamedDeclPrinterTest.cpp
===================================================================
--- unittests/AST/NamedDeclPrinterTest.cpp
+++ unittests/AST/NamedDeclPrinterTest.cpp
@@ -28,14 +28,19 @@
 
 namespace {
 
+using PrintingPolicyModifier = void (*)(PrintingPolicy &policy);
+
 class PrintMatch : public MatchFinder::MatchCallback {
   SmallString<1024> Printed;
   unsigned NumFoundDecls;
   bool SuppressUnwrittenScope;
+  PrintingPolicyModifier PolicyModifier;
 
 public:
-  explicit PrintMatch(bool suppressUnwrittenScope)
-    : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope) {}
+  explicit PrintMatch(bool suppressUnwrittenScope,
+                      PrintingPolicyModifier PolicyModifier)
+      : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope),
+        PolicyModifier(PolicyModifier) {}
 
   void run(const MatchFinder::MatchResult &Result) override {
     const NamedDecl *ND = Result.Nodes.getNodeAs<NamedDecl>("id");
@@ -48,6 +53,8 @@
     llvm::raw_svector_ostream Out(Printed);
     PrintingPolicy Policy = Result.Context->getPrintingPolicy();
     Policy.SuppressUnwrittenScope = SuppressUnwrittenScope;
+    if (PolicyModifier)
+      PolicyModifier(Policy);
     ND->printQualifiedName(Out, Policy);
   }
 
@@ -64,8 +71,9 @@
 PrintedNamedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
                         bool SuppressUnwrittenScope,
                         const DeclarationMatcher &NodeMatch,
-                        StringRef ExpectedPrinted, StringRef FileName) {
-  PrintMatch Printer(SuppressUnwrittenScope);
+                        StringRef ExpectedPrinted, StringRef FileName,
+                        PrintingPolicyModifier PolicyModifier) {
+  PrintMatch Printer(SuppressUnwrittenScope, PolicyModifier);
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
   std::unique_ptr<FrontendActionFactory> Factory =
@@ -94,26 +102,30 @@
 
 ::testing::AssertionResult
 PrintedNamedDeclCXX98Matches(StringRef Code, StringRef DeclName,
-                             StringRef ExpectedPrinted) {
+                             StringRef ExpectedPrinted,
+                             PrintingPolicyModifier PolicyModifier = nullptr) {
   std::vector<std::string> Args(1, "-std=c++98");
   return PrintedNamedDeclMatches(Code,
                                  Args,
                                  /*SuppressUnwrittenScope*/ false,
                                  namedDecl(hasName(DeclName)).bind("id"),
                                  ExpectedPrinted,
-                                 "input.cc");
+                                 "input.cc",
+                                 PolicyModifier);
 }
 
 ::testing::AssertionResult
-PrintedWrittenNamedDeclCXX11Matches(StringRef Code, StringRef DeclName,
-                                    StringRef ExpectedPrinted) {
+PrintedWrittenNamedDeclCXX11Matches(
+    StringRef Code, StringRef DeclName, StringRef ExpectedPrinted,
+    PrintingPolicyModifier PolicyModifier = nullptr) {
   std::vector<std::string> Args(1, "-std=c++11");
   return PrintedNamedDeclMatches(Code,
                                  Args,
                                  /*SuppressUnwrittenScope*/ true,
                                  namedDecl(hasName(DeclName)).bind("id"),
                                  ExpectedPrinted,
-                                 "input.cc");
+                                 "input.cc",
+                                 PolicyModifier);
 }
 
 } // unnamed namespace
@@ -180,3 +192,20 @@
     "A",
     "X::A"));
 }
+
+TEST(NamedDeclPrinter, TestClassTemplateMemberFunction) {
+  ASSERT_TRUE(PrintedNamedDeclCXX98Matches(
+    "template <typename T> struct X { void A(); };"
+    "void Y() { X<int> x; x.A(); }",
+    "::X<int>::A",
+    "X<int>::A"));
+}
+
+TEST(NamedDeclPrinter, TestClassTemplateMemberFunction_SuppressTemplateArgs) {
+  ASSERT_TRUE(PrintedNamedDeclCXX98Matches(
+    "template <typename T> struct X { void A(); };"
+    "void Y() { X<int> x; x.A(); }",
+    "::X<int>::A",
+    "X::A",
+    [](PrintingPolicy &Policy){ Policy.SuppressTemplateArgs = true; }));
+}