diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index f0147c42e27bfc1866685d35e56c6c8cc1c88910..614351f76b38fbbeeb3f9e9b9d8c0f116034675c 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -4350,6 +4350,9 @@ public:
   const TemplateSpecializationType *getInjectedTST() const {
     return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
   }
+  TemplateName getTemplateName() const {
+    return getInjectedTST()->getTemplateName();
+  }
 
   CXXRecordDecl *getDecl() const;
 
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 144ef0ba9d7b10ee21736c9f2db3d0edb4465c9c..e20619bb37d3d5fe419d83125729f042c507e144 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -6114,12 +6114,17 @@ public:
   /// \param Converted Will receive the converted, canonicalized template
   /// arguments.
   ///
+  /// \param UpdateArgsWithConversions If \c true, update \p TemplateArgs to
+  /// contain the converted forms of the template arguments as written.
+  /// Otherwise, \p TemplateArgs will not be modified.
+  ///
   /// \returns true if an error occurred, false otherwise.
   bool CheckTemplateArgumentList(TemplateDecl *Template,
                                  SourceLocation TemplateLoc,
                                  TemplateArgumentListInfo &TemplateArgs,
                                  bool PartialTemplateArgs,
-                           SmallVectorImpl<TemplateArgument> &Converted);
+                                 SmallVectorImpl<TemplateArgument> &Converted,
+                                 bool UpdateArgsWithConversions = true);
 
   bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
                                  TemplateArgumentLoc &Arg,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2920ede3b5eea3de477e0ab2e6a8e2fa993edfac..90de88ac3327a33a8e23678e34010eb1b67237db 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3657,6 +3657,39 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
                 TempTempParm->getDefaultArgument().getTemplateNameLoc());
 }
 
+/// Convert a template-argument that we parsed as a type into a template, if
+/// possible. C++ permits injected-class-names to perform dual service as
+/// template template arguments and as template type arguments.
+static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
+  // Extract and step over any surrounding nested-name-specifier.
+  NestedNameSpecifierLoc QualLoc;
+  if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) {
+    if (ETLoc.getTypePtr()->getKeyword() != ETK_None)
+      return TemplateArgumentLoc();
+
+    QualLoc = ETLoc.getQualifierLoc();
+    TLoc = ETLoc.getNamedTypeLoc();
+  }
+
+  // If this type was written as an injected-class-name, it can be used as a
+  // template template argument.
+  if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>())
+    return TemplateArgumentLoc(InjLoc.getTypePtr()->getTemplateName(),
+                               QualLoc, InjLoc.getNameLoc());
+
+  // If this type was written as an injected-class-name, it may have been
+  // converted to a RecordType during instantiation. If the RecordType is
+  // *not* wrapped in a TemplateSpecializationType and denotes a class
+  // template specialization, it must have come from an injected-class-name.
+  if (auto RecLoc = TLoc.getAs<RecordTypeLoc>())
+    if (auto *CTSD =
+            dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl()))
+      return TemplateArgumentLoc(TemplateName(CTSD->getSpecializedTemplate()),
+                                 QualLoc, RecLoc.getNameLoc());
+
+  return TemplateArgumentLoc();
+}
+
 /// \brief Check that the given template argument corresponds to the given
 /// template parameter.
 ///
@@ -3863,6 +3896,17 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
       return true;
   }
 
+  // C++1z [temp.local]p1: (DR1004)
+  //   When [the injected-class-name] is used [...] as a template-argument for
+  //   a template template-parameter [...] it refers to the class template
+  //   itself.
+  if (Arg.getArgument().getKind() == TemplateArgument::Type) {
+    TemplateArgumentLoc ConvertedArg = convertTypeTemplateArgumentToTemplate(
+        Arg.getTypeSourceInfo()->getTypeLoc());
+    if (!ConvertedArg.getArgument().isNull())
+      Arg = ConvertedArg;
+  }
+
   switch (Arg.getArgument().getKind()) {
   case TemplateArgument::Null:
     llvm_unreachable("Should never see a NULL template argument here");
@@ -3976,11 +4020,11 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
 
 /// \brief Check that the given template argument list is well-formed
 /// for specializing the given template.
-bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
-                                     SourceLocation TemplateLoc,
-                                     TemplateArgumentListInfo &TemplateArgs,
-                                     bool PartialTemplateArgs,
-                          SmallVectorImpl<TemplateArgument> &Converted) {
+bool Sema::CheckTemplateArgumentList(
+    TemplateDecl *Template, SourceLocation TemplateLoc,
+    TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
+    SmallVectorImpl<TemplateArgument> &Converted,
+    bool UpdateArgsWithConversions) {
   // Make a copy of the template arguments for processing.  Only make the
   // changes at the end when successful in matching the arguments to the
   // template.
@@ -4218,7 +4262,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
 
   // No problems found with the new argument list, propagate changes back
   // to caller.
-  TemplateArgs = std::move(NewArgs);
+  if (UpdateArgsWithConversions)
+    TemplateArgs = std::move(NewArgs);
 
   return false;
 }
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 93e796ee9668ecb6d2abdafbd30159d63a1ed68e..3197647d8d8beb3f1326e20a88df161eef5e143f 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2640,11 +2640,9 @@ Sema::SubstituteExplicitTemplateArguments(
   if (Inst.isInvalid())
     return TDK_InstantiationDepth;
 
-  if (CheckTemplateArgumentList(FunctionTemplate,
-                                SourceLocation(),
-                                ExplicitTemplateArgs,
-                                true,
-                                Builder) || Trap.hasErrorOccurred()) {
+  if (CheckTemplateArgumentList(FunctionTemplate, SourceLocation(),
+                                ExplicitTemplateArgs, true, Builder, false) ||
+      Trap.hasErrorOccurred()) {
     unsigned Index = Builder.size();
     if (Index >= TemplateParams->size())
       Index = TemplateParams->size() - 1;
diff --git a/test/CXX/drs/dr10xx.cpp b/test/CXX/drs/dr10xx.cpp
index e11e796165e22ab36e2ec3b0be0c51c90e2240ac..0ae55f5e07c073a1f0abbf8dded11d3bb17eb1a5 100644
--- a/test/CXX/drs/dr10xx.cpp
+++ b/test/CXX/drs/dr10xx.cpp
@@ -12,6 +12,29 @@ namespace std {
   };
 }
 
+namespace dr1004 { // dr1004: 5
+  template<typename> struct A {};
+  template<typename> struct B1 {};
+  template<template<typename> class> struct B2 {};
+  template<typename X> void f(); // expected-note {{[with X = dr1004::A<int>]}}
+  template<template<typename> class X> void f(); // expected-note {{[with X = A]}}
+  template<template<typename> class X> void g(); // expected-note {{[with X = A]}}
+  template<typename X> void g(); // expected-note {{[with X = dr1004::A<int>]}}
+  struct C : A<int> {
+    B1<A> b1a;
+    B2<A> b2a;
+    void h() {
+      f<A>(); // expected-error {{ambiguous}}
+      g<A>(); // expected-error {{ambiguous}}
+    }
+  };
+
+  // FIXME: Is this example (from the standard) really OK, or does name lookup
+  // of "T::template A" name the constructor?
+  template<class T, template<class> class U = T::template A> struct Third { };
+  Third<A<int> > t;
+}
+
 namespace dr1048 { // dr1048: 3.6
   struct A {};
   const A f();
diff --git a/test/CXX/temp/temp.res/temp.local/p1.cpp b/test/CXX/temp/temp.res/temp.local/p1.cpp
index f6ef636daa56b729c6e307d6bc033a7ab7d773ca..faa85cb5fce3000adbb8f0170a5d435e10ed2771 100644
--- a/test/CXX/temp/temp.res/temp.local/p1.cpp
+++ b/test/CXX/temp/temp.res/temp.local/p1.cpp
@@ -1,12 +1,55 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
 
-// C++0x [temp.local]p1:
+// C++1z [temp.local]p1:
 //   Like normal (non-template) classes, class templates have an
-//   injected-class-name (Clause 9). The injected-class-name can be used with
-//   or without a template-argument-list. When it is used without
-//   a template-argument-list, it is equivalent to the injected-class-name
-//   followed by the template-parameters of the class template enclosed in <>.
+//   injected-class-name (Clause 9). The injected-class-name can
+//   be used as a template-name or a type-name.
+
+template<typename> char id;
+
+template<typename> struct TempType {};
+template<template<typename> class> struct TempTemp {};
+
+template<typename> void use(int&); // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}}
+template<template<typename> class> void use(float&); // expected-note 2{{no known conversion}}
+template<int> void use(char&); // expected-note 2{{invalid explicitly-specified argument}}
+
+template<typename T> struct A {
+  template<typename> struct C {};
+  struct B : C<T> {
+    //   When it is used with a template-argument-list,
+    A<int> *aint;
+    typename B::template C<int> *cint;
+
+    //   as a template-argument for a template template-parameter,
+    TempTemp<A> a_as_temp;
+    TempTemp<B::template C> c_as_temp;
+
+    //   or as the final identifier in the elaborated-type-specifier of a friend
+    //   class template declaration,
+    template<typename U> friend struct A;
+    // it refers to the class template itself.
+
+    // Otherwise, it is equivalent to the template-name followed by the
+    // template-parameters of the class template enclosed in <>.
+    A *aT;
+    typename B::C *cT;
+    TempType<A> a_as_type;
+    TempType<typename B::C> c_as_type;
+    friend struct A;
+    friend struct B::C;
+
+    void f(T &t) {
+      use<A>(t); // expected-error {{no matching function}}
+      if constexpr (&id<T> != &id<int>)
+        use<B::template C>(t); // expected-error {{no matching function}}
+    }
+  };
+};
+
+template struct A<int>;
+template struct A<float>;
+template struct A<char>; // expected-note {{instantiation of}}
 
 template <typename T> struct X0 {
   X0();
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index ffc076512446088cdb96a21ab7af13b7925a2248..b4a4d7710f5e9118a543ae42680138ef47d99028 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -1937,7 +1937,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#316">316</a></td>
     <td>NAD</td>
     <td>Injected-class-name of template used as template template parameter</td>
-    <td class="none" align="center">Superseded by <a href="#1004">1004</a></td>
+    <td class="svn" align="center">Superseded by <a href="#1004">1004</a></td>
   </tr>
   <tr id="317">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#317">317</a></td>
@@ -5839,7 +5839,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1004">1004</a></td>
     <td>C++11</td>
     <td>Injected-class-names as arguments for template template parameters</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="1005">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1005">1005</a></td>