diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index b01070edb4e0811637b29e9dc1c70b987fafc08e..06ca46b2f6b18b85390d0a6f7c7c954af4fc4a5c 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1927,8 +1927,9 @@ public:
                                 unsigned &Idx);
 
   /// \brief Read a template argument.
-  TemplateArgument ReadTemplateArgument(ModuleFile &F,
-                                        const RecordData &Record,unsigned &Idx);
+  TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record,
+                                        unsigned &Idx,
+                                        bool Canonicalize = false);
 
   /// \brief Read a template parameter list.
   TemplateParameterList *ReadTemplateParameterList(ModuleFile &F,
@@ -1936,10 +1937,9 @@ public:
                                                    unsigned &Idx);
 
   /// \brief Read a template argument array.
-  void
-  ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
-                           ModuleFile &F, const RecordData &Record,
-                           unsigned &Idx);
+  void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
+                                ModuleFile &F, const RecordData &Record,
+                                unsigned &Idx, bool Canonicalize = false);
 
   /// \brief Read a UnresolvedSet structure.
   void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 2412d04666f1390a2de5334e9de276362f353c1a..ff771fd00a3b09ef2d9271f2d4ea3e884e5975f5 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -7568,9 +7568,19 @@ ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
   llvm_unreachable("Unhandled template name kind!");
 }
 
-TemplateArgument
-ASTReader::ReadTemplateArgument(ModuleFile &F,
-                                const RecordData &Record, unsigned &Idx) {
+TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F,
+                                                 const RecordData &Record,
+                                                 unsigned &Idx,
+                                                 bool Canonicalize) {
+  if (Canonicalize) {
+    // The caller wants a canonical template argument. Sometimes the AST only
+    // wants template arguments in canonical form (particularly as the template
+    // argument lists of template specializations) so ensure we preserve that
+    // canonical form across serialization.
+    TemplateArgument Arg = ReadTemplateArgument(F, Record, Idx, false);
+    return Context.getCanonicalTemplateArgument(Arg);
+  }
+
   TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
   switch (Kind) {
   case TemplateArgument::Null:
@@ -7634,11 +7644,11 @@ void
 ASTReader::
 ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
                          ModuleFile &F, const RecordData &Record,
-                         unsigned &Idx) {
+                         unsigned &Idx, bool Canonicalize) {
   unsigned NumTemplateArgs = Record[Idx++];
   TemplArgs.reserve(NumTemplateArgs);
   while (NumTemplateArgs--)
-    TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
+    TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx, Canonicalize));
 }
 
 /// \brief Read a UnresolvedSet structure.
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index b59b94f9bf98dec36aa75ab8601daeb40d5d569d..972e2b829d17d04d1e5e3f35cea0e7923af617ed 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -779,8 +779,9 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
     
     // Template arguments.
     SmallVector<TemplateArgument, 8> TemplArgs;
-    Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
-    
+    Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
+                                    /*Canonicalize*/ true);
+
     // Template args as written.
     SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
     SourceLocation LAngleLoc, RAngleLoc;
@@ -1937,7 +1938,8 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
   }
 
   SmallVector<TemplateArgument, 8> TemplArgs;
-  Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+  Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
+                                  /*Canonicalize*/ true);
   D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), 
                                                      TemplArgs.size());
   D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
@@ -2064,7 +2066,8 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
   }
 
   SmallVector<TemplateArgument, 8> TemplArgs;
-  Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+  Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
+                                  /*Canonicalize*/ true);
   D->TemplateArgs =
       TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
   D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
diff --git a/test/Modules/Inputs/stress1/merge00.h b/test/Modules/Inputs/stress1/merge00.h
index 46d5e4138279d76a33fc0717db6c7cdfdea65437..0aeb6ce0087fa3fa13dc11fad85c364612ac59a3 100644
--- a/test/Modules/Inputs/stress1/merge00.h
+++ b/test/Modules/Inputs/stress1/merge00.h
@@ -9,6 +9,10 @@
 //#pragma weak pragma_weak01 // expected-warning {{weak identifier 'pragma_weak01' never declared}}
 //#pragma weak pragma_weak04 // expected-warning {{weak identifier 'pragma_waek04' never declared}}
 
+#ifdef MERGE_NO_REEXPORT
+#include "merge_no_reexport.h"
+#endif
+
 #include "common.h"
 #include "m00.h"
 #include "m01.h"
diff --git a/test/Modules/Inputs/stress1/module.modulemap b/test/Modules/Inputs/stress1/module.modulemap
index 2b687b015215704e611823318d2998fd4c43459b..33eb23e2a6e0280cfcf31f9e952218cd57d5b94f 100644
--- a/test/Modules/Inputs/stress1/module.modulemap
+++ b/test/Modules/Inputs/stress1/module.modulemap
@@ -3,4 +3,5 @@ module m01 { header "Inputs/stress1/m01.h" export * }
 module m02 { header "Inputs/stress1/m02.h" export * }
 module m03 { header "Inputs/stress1/m03.h" export * }
 
+module merge_no_reexport { header "Inputs/stress1/merge_no_reexport.h" }
 module merge00 { header "Inputs/stress1/merge00.h" export * }
diff --git a/test/Modules/Inputs/submodules-merge-defs/defs.h b/test/Modules/Inputs/submodules-merge-defs/defs.h
index 670c400ae3b266b63abc9ac3ca9f2663fe903056..ba6956fb98dc38deac6b7cab7268c690c769f2ce 100644
--- a/test/Modules/Inputs/submodules-merge-defs/defs.h
+++ b/test/Modules/Inputs/submodules-merge-defs/defs.h
@@ -111,3 +111,16 @@ namespace Anon {
     };
   };
 }
+
+namespace ClassTemplatePartialSpec {
+  template<typename T> struct F;
+  template<template<int> class A, int B> struct F<A<B>> {
+    template<typename C> F();
+  };
+  template<template<int> class A, int B> template<typename C> F<A<B>>::F() {}
+
+  template<typename A, int B> struct F<A[B]> {
+    template<typename C> F();
+  };
+  template<typename A, int B> template<typename C> F<A[B]>::F() {}
+}
diff --git a/test/Modules/stress1.cpp b/test/Modules/stress1.cpp
index 0cefed27df8c9091e8b6b86defd3f8725e5584ef..4da1edd092e3fc7440682d791d09545911543dd3 100644
--- a/test/Modules/stress1.cpp
+++ b/test/Modules/stress1.cpp
@@ -107,6 +107,18 @@
 //
 // RUN: diff -u %t/stress1.ll %t/stress1_check.ll
 //
+// RUN: %clang_cc1 -fmodules -x c++ -std=c++11 \
+// RUN:   -I Inputs/stress1 \
+// RUN:   -fmodules-cache-path=%t \
+// RUN:   -fmodule-map-file-home-is-cwd \
+// RUN:   -fmodule-file=%t/m00.pcm \
+// RUN:   -fmodule-file=%t/m01.pcm \
+// RUN:   -fmodule-file=%t/m02.pcm \
+// RUN:   -fmodule-file=%t/m03.pcm \
+// RUN:   -emit-module -fmodule-name=merge00 -o /dev/null \
+// RUN:   -DMERGE_NO_REEXPORT \
+// RUN:   Inputs/stress1/module.modulemap
+//
 // expected-no-diagnostics
 
 #include "m00.h"