mizvekov updated this revision to Diff 472415.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134113/new/

https://reviews.llvm.org/D134113

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/include/clang/AST/Type.h
  clang/include/clang/AST/TypeProperties.td
  clang/include/clang/Serialization/ASTRecordReader.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ASTDiagnostic.cpp
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/ASTStructuralEquivalence.cpp
  clang/lib/AST/DeclTemplate.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/QualTypeNames.cpp
  clang/lib/AST/Type.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/Index/USRGeneration.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
  clang/test/SemaTemplate/deduction.cpp
  clang/test/SemaTemplate/make_integer_seq.cpp
  clang/test/SemaTemplate/type_pack_element.cpp

Index: clang/test/SemaTemplate/type_pack_element.cpp
===================================================================
--- clang/test/SemaTemplate/type_pack_element.cpp
+++ clang/test/SemaTemplate/type_pack_element.cpp
@@ -15,61 +15,40 @@
 
 template<int N, class ...Ts> struct A {
   using test2 = __type_pack_element<N, Ts...>;
-//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:17:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, type-parameter-0-1...>'
+//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:17:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, Ts...>'
 // CHECK-NEXT:   `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent
-// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias __type_pack_element
+// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' dependent __type_pack_element
 // CHECK-NEXT:       |-TemplateArgument expr
 // CHECK-NEXT:       | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
 // CHECK-NEXT:       |   `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT:       |-TemplateArgument type 'Ts...'
-// CHECK-NEXT:       | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
-// CHECK-NEXT:       |   `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
-// CHECK-NEXT:       |     `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
-// CHECK-NEXT:       `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, type-parameter-0-1...>' dependent __type_pack_element
-// CHECK-NEXT:         |-TemplateArgument expr
-// CHECK-NEXT:         | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
-// CHECK-NEXT:         |   `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT:         `-TemplateArgument pack
-// CHECK-NEXT:           `-TemplateArgument type 'type-parameter-0-1...'
-// CHECK-NEXT:             `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent
-// CHECK-NEXT:               `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT:       `-TemplateArgument type 'Ts...'
+// CHECK-NEXT:         `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
+// CHECK-NEXT:           `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT:             `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
 
   using test3 = __type_pack_element<0, Ts...>;
-//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:37:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, type-parameter-0-1...>'
+//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:29:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, Ts...>'
 // CHECK-NEXT:   `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent
-// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias __type_pack_element
+// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' dependent __type_pack_element
 // CHECK-NEXT:       |-TemplateArgument expr
 // CHECK-NEXT:       | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long'
 // CHECK-NEXT:       |   |-value: Int 0
 // CHECK-NEXT:       |   `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
 // CHECK-NEXT:       |     `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:37> 'int' 0
-// CHECK-NEXT:       |-TemplateArgument type 'Ts...'
-// CHECK-NEXT:       | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
-// CHECK-NEXT:       |   `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
-// CHECK-NEXT:       |     `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
-// CHECK-NEXT:       `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, type-parameter-0-1...>' dependent __type_pack_element
-// CHECK-NEXT:         |-TemplateArgument integral 0
-// CHECK-NEXT:         `-TemplateArgument pack
-// CHECK-NEXT:           `-TemplateArgument type 'type-parameter-0-1...'
-// CHECK-NEXT:             `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent
-// CHECK-NEXT:               `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT:       `-TemplateArgument type 'Ts...'
+// CHECK-NEXT:         `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
+// CHECK-NEXT:           `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT:             `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
 
   using test4 = __type_pack_element<N, int>;
-//      CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:57:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>'
+//      CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:43:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>'
 // CHECK-NEXT:   `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent
-// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias __type_pack_element
+// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent __type_pack_element
 // CHECK-NEXT:       |-TemplateArgument expr
 // CHECK-NEXT:       | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
 // CHECK-NEXT:       |   `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT:       |-TemplateArgument type 'int'
-// CHECK-NEXT:       | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT:       `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent __type_pack_element
-// CHECK-NEXT:         |-TemplateArgument expr
-// CHECK-NEXT:         | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
-// CHECK-NEXT:         |   `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT:         `-TemplateArgument pack
-// CHECK-NEXT:           `-TemplateArgument type 'int'
-// CHECK-NEXT:             `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT:       `-TemplateArgument type 'int'
+// CHECK-NEXT:         `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
 };
 
 // expected-no-diagnostics
Index: clang/test/SemaTemplate/make_integer_seq.cpp
===================================================================
--- clang/test/SemaTemplate/make_integer_seq.cpp
+++ clang/test/SemaTemplate/make_integer_seq.cpp
@@ -40,75 +40,53 @@
 // CHECK-NEXT:           |-TemplateArgument type 'int'
 // CHECK-NEXT:           | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
 // CHECK-NEXT:           |-TemplateArgument expr
-// CHECK-NEXT:           | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:26:64> 'int'
+// CHECK-NEXT:           | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:5:42> 'int'
 // CHECK-NEXT:           |   |-value: Int 1
-// CHECK-NEXT:           |   `-SubstNonTypeTemplateParmExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int'
-// CHECK-NEXT:           |     |-NonTypeTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <col:21, col:24> col:24 referenced 'B1' depth 0 index 1 B2
-// CHECK-NEXT:           |     `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 1
+// CHECK-NEXT:           |   `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
 // CHECK-NEXT:           `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A
 // CHECK-NEXT:             |-TemplateArgument type 'int'
 // CHECK-NEXT:             | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
 // CHECK-NEXT:             |-TemplateArgument expr
-// CHECK-NEXT:             | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int'
+// CHECK-NEXT:             | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int'
 // CHECK-NEXT:             |   |-value: Int 0
-// CHECK-NEXT:             |   `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 0
+// CHECK-NEXT:             |   `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 0
 // CHECK-NEXT:             `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>'
 // CHECK-NEXT:               `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A'
 
 template <template <class T, T...> class S, class T, int N> struct C {
   using test3 = __make_integer_seq<S, T, N>;
-//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:59:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<type-parameter-0-1, N>'
+//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:57:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<S, T, N>'
 // CHECK-NEXT:   `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent
-// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias __make_integer_seq
+// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' dependent __make_integer_seq
 // CHECK-NEXT:       |-TemplateArgument template S
 // CHECK-NEXT:       |-TemplateArgument type 'T'
 // CHECK-NEXT:       | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1
 // CHECK-NEXT:       |   `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T'
-// CHECK-NEXT:       |-TemplateArgument expr
-// CHECK-NEXT:       | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
-// CHECK-NEXT:       |   `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT:       `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<type-parameter-0-1, N>' dependent __make_integer_seq
-// CHECK-NEXT:         |-TemplateArgument template
-// CHECK-NEXT:         |-TemplateArgument type 'type-parameter-0-1'
-// CHECK-NEXT:         | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1
-// CHECK-NEXT:         `-TemplateArgument expr
-// CHECK-NEXT:           `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
-// CHECK-NEXT:             `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT:       `-TemplateArgument expr
+// CHECK-NEXT:         `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
+// CHECK-NEXT:           `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
 
   using test4 = __make_integer_seq<A, T, 1>;
-//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:78:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, type-parameter-0-1, 1>'
+//      CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:69:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, T, 1>'
 // CHECK-NEXT:   `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent
-// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias __make_integer_seq
+// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' dependent __make_integer_seq
 // CHECK-NEXT:       |-TemplateArgument template A
 // CHECK-NEXT:       |-TemplateArgument type 'T'
 // CHECK-NEXT:       | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1
 // CHECK-NEXT:       |   `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T'
-// CHECK-NEXT:       |-TemplateArgument expr
-// CHECK-NEXT:       | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
-// CHECK-NEXT:       |   `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
-// CHECK-NEXT:       `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, type-parameter-0-1, 1>' dependent __make_integer_seq
-// CHECK-NEXT:         |-TemplateArgument template A
-// CHECK-NEXT:         |-TemplateArgument type 'type-parameter-0-1'
-// CHECK-NEXT:         | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1
-// CHECK-NEXT:         `-TemplateArgument expr
-// CHECK-NEXT:           `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
-// CHECK-NEXT:             `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
+// CHECK-NEXT:       `-TemplateArgument expr
+// CHECK-NEXT:         `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
+// CHECK-NEXT:           `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
 
   using test5 = __make_integer_seq<A, int, N>;
-//      CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:97:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>'
+//      CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:81:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>'
 // CHECK-NEXT:   `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent
-// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias __make_integer_seq
+// CHECK-NEXT:     `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent __make_integer_seq
 // CHECK-NEXT:       |-TemplateArgument template A
 // CHECK-NEXT:       |-TemplateArgument type 'int'
 // CHECK-NEXT:       | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT:       |-TemplateArgument expr
-// CHECK-NEXT:       | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT:       `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent __make_integer_seq
-// CHECK-NEXT:         |-TemplateArgument template A
-// CHECK-NEXT:         |-TemplateArgument type 'int'
-// CHECK-NEXT:         | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT:         `-TemplateArgument expr
-// CHECK-NEXT:           `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT:       `-TemplateArgument expr
+// CHECK-NEXT:         `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
 };
 
 // expected-no-diagnostics
Index: clang/test/SemaTemplate/deduction.cpp
===================================================================
--- clang/test/SemaTemplate/deduction.cpp
+++ clang/test/SemaTemplate/deduction.cpp
@@ -504,7 +504,7 @@
 namespace b29946541 {
   template<typename> class A {};
   template<typename T, typename U, template<typename, typename> class C>
-  void f(C<T, U>); // expected-note {{failed template argument deduction}}
+  void f(C<T, U>); // expected-note {{couldn't infer template argument 'U'}}
   void g(A<int> a) { f(a); } // expected-error {{no match}}
 }
 
Index: clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
===================================================================
--- clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
+++ clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
@@ -38,7 +38,7 @@
 template<typename T, typename U>
 struct Outer {
   template<typename X, typename Y> struct Inner;
-  template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous declaration of class template partial specialization 'Inner<int, type-parameter-0-0>' is here}}
+  template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous declaration of class template partial specialization 'Inner<int, Y>' is here}}
   template<typename Y> struct Inner<U, Y> {}; // expected-error{{cannot be redeclared}}
 };
 
@@ -80,7 +80,7 @@
 template <class T, class U> struct Foo {
   template <unsigned long, class X, class Y> struct Bar;
   template <class Y> struct Bar<0, T, Y> {};
-  // expected-note-re@-1 {{previous declaration {{.*}} 'Bar<0, int, type-parameter-0-0>' is here}}
+  // expected-note-re@-1 {{previous declaration {{.*}} 'Bar<0, int, Y>' is here}}
   template <class Y> struct Bar<0, U, Y> {};
   // expected-error@-1 {{partial specialization 'Bar<0, int, Y>' cannot be redeclared}}
 };
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -6746,12 +6746,24 @@
   TemplateArgumentListInfo NewTemplateArgs;
   NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
   NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
-  typedef TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>
-    ArgIterator;
-  if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
-                                              ArgIterator(TL, TL.getNumArgs()),
-                                              NewTemplateArgs))
-    return QualType();
+
+  const auto *T = cast<TemplateSpecializationType>(TL.getType());
+  if (T->isCanonicalUnqualified()) {
+    ArrayRef<TemplateArgument> ConvertedArgs = T->getConvertedArguments();
+    using ArgIterator =
+        TemplateArgumentLocInventIterator<Derived, const TemplateArgument *>;
+    if (getDerived().TransformTemplateArguments(
+            ArgIterator(*this, ConvertedArgs.begin()),
+            ArgIterator(*this, ConvertedArgs.end()), NewTemplateArgs))
+      return QualType();
+  } else {
+    using ArgIterator =
+        TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>;
+    if (getDerived().TransformTemplateArguments(
+            ArgIterator(TL, 0), ArgIterator(TL, TL.getNumArgs()),
+            NewTemplateArgs))
+      return QualType();
+  }
 
   // FIXME: maybe don't rebuild if all the template arguments are the same.
 
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3815,12 +3815,6 @@
   if (SubstQualifier(D, InstD))
     return nullptr;
 
-  // Build the canonical type that describes the converted template
-  // arguments of the class template explicit specialization.
-  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
-      TemplateName(InstClassTemplate), CanonicalConverted,
-      SemaRef.Context.getRecordType(InstD));
-
   // Build the fully-sugared type for this class template
   // specialization as the user wrote in the specialization
   // itself. This means that we'll pretty-print the type retrieved
@@ -3830,7 +3824,8 @@
   // template arguments in the specialization.
   TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
       TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs,
-      CanonType);
+      SugaredConverted, CanonicalConverted,
+      SemaRef.Context.getRecordType(InstD));
 
   InstD->setAccess(D->getAccess());
   InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
@@ -4165,11 +4160,6 @@
       ClassTemplate->findPartialSpecialization(CanonicalConverted, InstParams,
                                                InsertPos);
 
-  // Build the canonical type that describes the converted template
-  // arguments of the class template partial specialization.
-  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
-      TemplateName(ClassTemplate), CanonicalConverted);
-
   // Build the fully-sugared type for this class template
   // specialization as the user wrote in the specialization
   // itself. This means that we'll pretty-print the type retrieved
@@ -4177,12 +4167,9 @@
   // actually wrote the specialization, rather than formatting the
   // name based on the "canonical" representation used to store the
   // template arguments in the specialization.
-  TypeSourceInfo *WrittenTy
-    = SemaRef.Context.getTemplateSpecializationTypeInfo(
-                                                    TemplateName(ClassTemplate),
-                                                    PartialSpec->getLocation(),
-                                                    InstTemplateArgs,
-                                                    CanonType);
+  TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
+      TemplateName(ClassTemplate), PartialSpec->getLocation(), InstTemplateArgs,
+      SugaredConverted, CanonicalConverted);
 
   if (PrevDecl) {
     // We've already seen a partial specialization with the same template
@@ -4213,8 +4200,8 @@
       ClassTemplatePartialSpecializationDecl::Create(
           SemaRef.Context, PartialSpec->getTagKind(), Owner,
           PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
-          ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType,
-          nullptr);
+          ClassTemplate, CanonicalConverted, InstTemplateArgs,
+          WrittenTy->getType(), nullptr);
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(PartialSpec, InstPartialSpec))
     return nullptr;
@@ -4290,11 +4277,6 @@
       VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams,
                                              InsertPos);
 
-  // Build the canonical type that describes the converted template
-  // arguments of the variable template partial specialization.
-  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
-      TemplateName(VarTemplate), CanonicalConverted);
-
   // Build the fully-sugared type for this variable template
   // specialization as the user wrote in the specialization
   // itself. This means that we'll pretty-print the type retrieved
@@ -4304,7 +4286,7 @@
   // template arguments in the specialization.
   TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
       TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs,
-      CanonType);
+      SugaredConverted, CanonicalConverted);
 
   if (PrevDecl) {
     // We've already seen a partial specialization with the same template
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -219,7 +219,7 @@
                               ->getInjectedSpecializationType();
       const auto *InjectedType = cast<TemplateSpecializationType>(Injected);
       Result.addOuterTemplateArguments(const_cast<CXXRecordDecl *>(Rec),
-                                       InjectedType->template_arguments(),
+                                       InjectedType->getConvertedArguments(),
                                        /*Final=*/false);
     }
   }
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -560,16 +560,16 @@
   QualType UP = P;
   if (const auto *IP = P->getAs<InjectedClassNameType>())
     UP = IP->getInjectedSpecializationType();
-  // FIXME: Try to preserve type sugar here, which is hard
-  // because of the unresolved template arguments.
-  const auto *TP = UP.getCanonicalType()->castAs<TemplateSpecializationType>();
+  assert(isa<TemplateSpecializationType>(UP.getCanonicalType()));
+  const TemplateSpecializationType *TP =
+      UP->castAsNonAliasTemplateSpecializationType();
   TemplateName TNP = TP->getTemplateName();
 
   // If the parameter is an alias template, there is nothing to deduce.
   if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias())
     return Sema::TDK_Success;
 
-  ArrayRef<TemplateArgument> PResolved = TP->template_arguments();
+  ArrayRef<TemplateArgument> PResolved = TP->getConvertedArguments();
 
   QualType UA = A;
   // Treat an injected-class-name as its underlying template-id.
@@ -577,9 +577,7 @@
     UA = Injected->getInjectedSpecializationType();
 
   // Check whether the template argument is a dependent template-id.
-  // FIXME: Should not lose sugar here.
-  if (const auto *SA =
-          dyn_cast<TemplateSpecializationType>(UA.getCanonicalType())) {
+  if (const auto *SA = UA->getAsNonAliasTemplateSpecializationType()) {
     TemplateName TNA = SA->getTemplateName();
 
     // If the argument is an alias template, there is nothing to deduce.
@@ -594,7 +592,7 @@
     // argument. Ignore any missing/extra arguments, since they could be
     // filled in by default arguments.
     return DeduceTemplateArguments(S, TemplateParams, PResolved,
-                                   SA->template_arguments(), Info, Deduced,
+                                   SA->getConvertedArguments(), Info, Deduced,
                                    /*NumberOfArgumentsMustMatch=*/false);
   }
 
@@ -5255,11 +5253,11 @@
       auto *TST2 = dyn_cast<TemplateSpecializationType>(T2);
       if (!TST1 || !TST2)
         continue;
-      const TemplateArgument &TA1 = TST1->template_arguments().back();
+      const TemplateArgument &TA1 = TST1->getConvertedArguments().back();
       if (TA1.getKind() == TemplateArgument::Pack) {
-        assert(TST1->template_arguments().size() ==
-               TST2->template_arguments().size());
-        const TemplateArgument &TA2 = TST2->template_arguments().back();
+        assert(TST1->getConvertedArguments().size() ==
+               TST2->getConvertedArguments().size());
+        const TemplateArgument &TA2 = TST2->getConvertedArguments().back();
         assert(TA2.getKind() == TemplateArgument::Pack);
         unsigned PackSize1 = TA1.pack_size();
         unsigned PackSize2 = TA2.pack_size();
@@ -5501,7 +5499,7 @@
     AtLeastAsSpecialized = !FinishTemplateArgumentDeduction(
         S, P2, /*IsPartialOrdering=*/true,
         TemplateArgumentList(TemplateArgumentList::OnStack,
-                             TST1->template_arguments()),
+                             TST1->getConvertedArguments()),
         Deduced, Info);
   });
   return AtLeastAsSpecialized;
@@ -5623,11 +5621,11 @@
   if (!ClangABICompat15) {
     auto *TST1 = cast<TemplateSpecializationType>(T1);
     auto *TST2 = cast<TemplateSpecializationType>(T2);
-    const TemplateArgument &TA1 = TST1->template_arguments().back();
+    const TemplateArgument &TA1 = TST1->getConvertedArguments().back();
     if (TA1.getKind() == TemplateArgument::Pack) {
-      assert(TST1->template_arguments().size() ==
-             TST2->template_arguments().size());
-      const TemplateArgument &TA2 = TST2->template_arguments().back();
+      assert(TST1->getConvertedArguments().size() ==
+             TST2->getConvertedArguments().size());
+      const TemplateArgument &TA2 = TST2->getConvertedArguments().back();
       assert(TA2.getKind() == TemplateArgument::Pack);
       unsigned PackSize1 = TA1.pack_size();
       unsigned PackSize2 = TA2.pack_size();
@@ -5732,9 +5730,11 @@
   TemplateName Name(PS1->getSpecializedTemplate());
   TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
   QualType PT1 = Context.getTemplateSpecializationType(
-      CanonTemplate, PS1->getTemplateArgs().asArray());
+      CanonTemplate, ArrayRef<TemplateArgument>(), None,
+      PS1->getTemplateArgs().asArray());
   QualType PT2 = Context.getTemplateSpecializationType(
-      CanonTemplate, PS2->getTemplateArgs().asArray());
+      CanonTemplate, ArrayRef<TemplateArgument>(), None,
+      PS2->getTemplateArgs().asArray());
 
   TemplateDeductionInfo Info(Loc);
   return getMoreSpecialized(*this, PT1, PT2, PS1, PS2, Info);
@@ -5745,10 +5745,14 @@
   VarTemplateDecl *Primary = Spec->getSpecializedTemplate();
   TemplateName CanonTemplate =
       Context.getCanonicalTemplateName(TemplateName(Primary));
-  QualType PrimaryT = Context.getTemplateSpecializationType(
-      CanonTemplate, Primary->getInjectedTemplateArgs());
+  QualType PrimaryT = Context
+                          .getTemplateSpecializationType(
+                              CanonTemplate, ArrayRef<TemplateArgument>(),
+                              Primary->getInjectedTemplateArgs(), None)
+                          .getCanonicalType();
   QualType PartialT = Context.getTemplateSpecializationType(
-      CanonTemplate, Spec->getTemplateArgs().asArray());
+      CanonTemplate, ArrayRef<TemplateArgument>(), None,
+      Spec->getTemplateArgs().asArray());
 
   VarTemplatePartialSpecializationDecl *MaybeSpec =
       getMoreSpecialized(*this, PartialT, PrimaryT, Spec, Primary, Info);
@@ -5778,6 +5782,7 @@
   //      template parameters from the respective function template
   SmallVector<TemplateArgument, 8> AArgs;
   Context.getInjectedTemplateArgs(A, AArgs);
+  Context.canonicalizeTemplateArguments(AArgs);
 
   // Check P's arguments against A's parameter list. This will fill in default
   // template arguments as needed. AArgs are already correct by construction.
@@ -5788,6 +5793,7 @@
     SFINAETrap Trap(*this);
 
     Context.getInjectedTemplateArgs(P, PArgs);
+    Context.canonicalizeTemplateArguments(PArgs);
     TemplateArgumentListInfo PArgList(P->getLAngleLoc(),
                                       P->getRAngleLoc());
     for (unsigned I = 0, N = P->size(); I != N; ++I) {
@@ -5813,8 +5819,10 @@
       return false;
   }
 
-  QualType AType = Context.getCanonicalTemplateSpecializationType(X, AArgs);
-  QualType PType = Context.getCanonicalTemplateSpecializationType(X, PArgs);
+  QualType AType = Context.getTemplateSpecializationType(
+      X, ArrayRef<TemplateArgument>(), None, AArgs);
+  QualType PType = Context.getTemplateSpecializationType(
+      X, ArrayRef<TemplateArgument>(), None, PArgs);
 
   //   ... the function template corresponding to P is at least as specialized
   //   as the function template corresponding to A according to the partial
@@ -6107,11 +6115,10 @@
     //   If the template argument list of P contains a pack expansion that is
     //   not the last template argument, the entire template argument list is a
     //   non-deduced context.
-    if (OnlyDeduced &&
-        hasPackExpansionBeforeEnd(Spec->template_arguments()))
+    if (OnlyDeduced && hasPackExpansionBeforeEnd(Spec->getConvertedArguments()))
       break;
 
-    for (const auto &Arg : Spec->template_arguments())
+    for (const TemplateArgument &Arg : Spec->getConvertedArguments())
       MarkUsedTemplateParameters(Ctx, Arg, OnlyDeduced, Depth, Used);
     break;
   }
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -3578,11 +3578,11 @@
   }
 }
 
-static QualType
-checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
-                           ArrayRef<TemplateArgument> Converted,
-                           SourceLocation TemplateLoc,
-                           TemplateArgumentListInfo &TemplateArgs) {
+static QualType checkBuiltinTemplateIdType(
+    Sema &SemaRef, TemplateName Name, BuiltinTemplateDecl *BTD,
+    ArrayRef<TemplateArgument> SugaredConverted,
+    ArrayRef<TemplateArgument> CanonicalConverted, SourceLocation TemplateLoc,
+    TemplateArgumentListInfo &TemplateArgs) {
   ASTContext &Context = SemaRef.getASTContext();
 
   switch (BTD->getBuiltinTemplateKind()) {
@@ -3590,7 +3590,7 @@
     // Specializations of __make_integer_seq<S, T, N> are treated like
     // S<T, 0, ..., N-1>.
 
-    QualType OrigType = Converted[1].getAsType();
+    QualType OrigType = SugaredConverted[1].getAsType();
     // C++14 [inteseq.intseq]p1:
     //   T shall be an integer type.
     if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) {
@@ -3599,10 +3599,11 @@
       return QualType();
     }
 
-    TemplateArgument NumArgsArg = Converted[2];
+    TemplateArgument NumArgsArg = SugaredConverted[2];
     if (NumArgsArg.isDependent())
-      return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
-                                                            Converted);
+      return SemaRef.Context.getTemplateSpecializationType(
+          TemplateName(BTD), TemplateArgs.arguments(), SugaredConverted,
+          CanonicalConverted);
 
     TemplateArgumentListInfo SyntheticTemplateArgs;
     // The type argument, wrapped in substitution sugar, gets reused as the
@@ -3630,21 +3631,26 @@
 
     // The first template argument will be reused as the template decl that
     // our synthetic template arguments will be applied to.
-    return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
-                                       TemplateLoc, SyntheticTemplateArgs);
+    QualType Result =
+        SemaRef.CheckTemplateIdType(SugaredConverted[0].getAsTemplate(),
+                                    TemplateLoc, SyntheticTemplateArgs);
+    return SemaRef.Context.getTemplateSpecializationType(
+        Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
+        Result);
   }
 
   case BTK__type_pack_element:
     // Specializations of
     //    __type_pack_element<Index, T_1, ..., T_N>
     // are treated like T_Index.
-    assert(Converted.size() == 2 &&
-      "__type_pack_element should be given an index and a parameter pack");
+    assert(SugaredConverted.size() == 2 &&
+           "__type_pack_element should be given an index and a parameter pack");
 
-    TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
+    TemplateArgument IndexArg = SugaredConverted[0], Ts = SugaredConverted[1];
     if (IndexArg.isDependent() || Ts.isDependent())
-      return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
-                                                            Converted);
+      return SemaRef.Context.getTemplateSpecializationType(
+          TemplateName(BTD), TemplateArgs.arguments(), SugaredConverted,
+          CanonicalConverted);
 
     llvm::APSInt Index = IndexArg.getAsIntegral();
     assert(Index >= 0 && "the index used with __type_pack_element should be of "
@@ -3658,7 +3664,9 @@
 
     // We simply return the type at index `Index`.
     int64_t N = Index.getExtValue();
-    return Ts.getPackAsArray()[N].getAsType();
+    return SemaRef.Context.getTemplateSpecializationType(
+        Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
+        Ts.getPackAsArray()[N].getAsType());
   }
   llvm_unreachable("unexpected BuiltinTemplateDecl!");
 }
@@ -3819,19 +3827,18 @@
       resolveAssumedTemplateNameAsType(/*Scope*/nullptr, Name, TemplateLoc))
     return QualType();
 
-  TemplateDecl *Template = Name.getAsTemplateDecl();
-  if (!Template || isa<FunctionTemplateDecl>(Template) ||
-      isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
-    // We might have a substituted template template parameter pack. If so,
-    // build a template specialization type for it.
-    if (Name.getAsSubstTemplateTemplateParmPack())
-      return Context.getTemplateSpecializationType(Name,
-                                                   TemplateArgs.arguments());
-
-    Diag(TemplateLoc, diag::err_template_id_not_a_type)
-      << Name;
-    NoteAllFoundTemplates(Name);
-    return QualType();
+  TemplateDecl *Template;
+  if (const SubstTemplateTemplateParmPackStorage *S =
+          Name.getAsSubstTemplateTemplateParmPack()) {
+    Template = S->getParameterPack();
+  } else {
+    Template = Name.getAsTemplateDecl();
+    if (!Template || isa<FunctionTemplateDecl>(Template) ||
+        isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
+      Diag(TemplateLoc, diag::err_template_id_not_a_type) << Name;
+      NoteAllFoundTemplates(Name);
+      return QualType();
+    }
   }
 
   // Check that the template argument list is well-formed for this
@@ -3844,8 +3851,11 @@
 
   QualType CanonType;
 
-  if (TypeAliasTemplateDecl *AliasTemplate =
-          dyn_cast<TypeAliasTemplateDecl>(Template)) {
+  if (isa<TemplateTemplateParmDecl>(Template)) {
+    // We might have a substituted template template parameter pack. If so,
+    // build a template specialization type for it.
+  } else if (TypeAliasTemplateDecl *AliasTemplate =
+                 dyn_cast<TypeAliasTemplateDecl>(Template)) {
 
     // Find the canonical type for this type alias template specialization.
     TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
@@ -3903,8 +3913,9 @@
       return QualType();
     }
   } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
-    CanonType = checkBuiltinTemplateIdType(*this, BTD, SugaredConverted,
-                                           TemplateLoc, TemplateArgs);
+    return checkBuiltinTemplateIdType(*this, Name, BTD, SugaredConverted,
+                                      CanonicalConverted, TemplateLoc,
+                                      TemplateArgs);
   } else if (Name.isDependent() ||
              TemplateSpecializationType::anyDependentTemplateArguments(
                  TemplateArgs, CanonicalConverted)) {
@@ -3915,8 +3926,9 @@
     // A<T, T> have identical types when A is declared as:
     //
     //   template<typename T, typename U = T> struct A;
-    CanonType = Context.getCanonicalTemplateSpecializationType(
-        Name, CanonicalConverted);
+    CanonType = Context.getTemplateSpecializationType(
+        Context.getCanonicalTemplateName(Name), ArrayRef<TemplateArgument>(),
+        None, CanonicalConverted);
 
     // This might work out to be a current instantiation, in which
     // case the canonical type needs to be the InjectedClassNameType.
@@ -4003,7 +4015,8 @@
   // specialization, which refers back to the class template
   // specialization we created or found.
   return Context.getTemplateSpecializationType(Name, TemplateArgs.arguments(),
-                                               CanonType);
+                                               SugaredConverted,
+                                               CanonicalConverted, CanonType);
 }
 
 void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,
@@ -8694,9 +8707,9 @@
   if (isPartialSpecialization) {
     // Build the canonical type that describes the converted template
     // arguments of the class template partial specialization.
-    TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
-    CanonType = Context.getTemplateSpecializationType(CanonTemplate,
-                                                      CanonicalConverted);
+    CanonType = Context.getTemplateSpecializationType(
+        Context.getCanonicalTemplateName(Name), ArrayRef<TemplateArgument>(),
+        None, CanonicalConverted);
 
     if (Context.hasSameType(CanonType,
                         ClassTemplate->getInjectedClassNameSpecialization()) &&
@@ -8763,9 +8776,9 @@
       ClassTemplate->AddSpecialization(Specialization, InsertPos);
 
     if (CurContext->isDependentContext()) {
-      TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
-      CanonType = Context.getTemplateSpecializationType(CanonTemplate,
-                                                        CanonicalConverted);
+      CanonType = Context.getTemplateSpecializationType(
+          Context.getCanonicalTemplateName(Name), ArrayRef<TemplateArgument>(),
+          None, CanonicalConverted);
     } else {
       CanonType = Context.getTypeDeclType(Specialization);
     }
@@ -8842,9 +8855,9 @@
   // actually wrote the specialization, rather than formatting the
   // name based on the "canonical" representation used to store the
   // template arguments in the specialization.
-  TypeSourceInfo *WrittenTy
-    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
-                                                TemplateArgs, CanonType);
+  TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
+      Name, TemplateNameLoc, TemplateArgs, SugaredConverted, CanonicalConverted,
+      CanonType);
   if (TUK != TUK_Friend) {
     Specialization->setTypeAsWritten(WrittenTy);
     Specialization->setTemplateKeywordLoc(TemplateKWLoc);
@@ -10016,10 +10029,9 @@
   // the explicit instantiation, rather than formatting the name based
   // on the "canonical" representation used to store the template
   // arguments in the specialization.
-  TypeSourceInfo *WrittenTy
-    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
-                                                TemplateArgs,
-                                  Context.getTypeDeclType(Specialization));
+  TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
+      Name, TemplateNameLoc, TemplateArgs, SugaredConverted, CanonicalConverted,
+      Context.getTypeDeclType(Specialization));
   Specialization->setTypeAsWritten(WrittenTy);
 
   // Set source locations for keywords.
Index: clang/lib/Index/USRGeneration.cpp
===================================================================
--- clang/lib/Index/USRGeneration.cpp
+++ clang/lib/Index/USRGeneration.cpp
@@ -856,8 +856,8 @@
                                     = T->getAs<TemplateSpecializationType>()) {
       Out << '>';
       VisitTemplateName(Spec->getTemplateName());
-      Out << Spec->template_arguments().size();
-      for (const auto &Arg : Spec->template_arguments())
+      Out << Spec->getConvertedArguments().size();
+      for (const TemplateArgument &Arg : Spec->getConvertedArguments())
         VisitTemplateArgument(Arg);
       return;
     }
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1504,7 +1504,10 @@
 
   DefaultTemplateArgsPolicyRAII TemplateArgs(Policy);
   const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr;
-  printTemplateArgumentList(OS, T->template_arguments(), Policy, TPL);
+  ArrayRef<TemplateArgument> Args = T->isCanonicalUnqualified()
+                                        ? T->getConvertedArguments()
+                                        : T->template_arguments();
+  printTemplateArgumentList(OS, Args, Policy, TPL);
   spaceBeforePlaceHolder(OS);
 }
 
@@ -1988,6 +1991,7 @@
     ArrayRef<TemplateArgument> TemplateArgs;
     if (auto *TTST = T->getAs<TemplateSpecializationType>()) {
       Template = TTST->getTemplateName();
+      assert(!TTST->isCanonicalUnqualified());
       TemplateArgs = TTST->template_arguments();
     } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
                    T->getAsCXXRecordDecl())) {
@@ -2000,11 +2004,12 @@
     if (!isSubstitutedTemplateArgument(Ctx, Template, PTST->getTemplateName(),
                                        Args, Depth))
       return false;
-    if (TemplateArgs.size() != PTST->template_arguments().size())
+    ArrayRef<TemplateArgument> PArgs = PTST->getConvertedArguments();
+    if (TemplateArgs.size() != PArgs.size())
       return false;
     for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
-      if (!isSubstitutedTemplateArgument(
-              Ctx, TemplateArgs[I], PTST->template_arguments()[I], Args, Depth))
+      if (!isSubstitutedTemplateArgument(Ctx, TemplateArgs[I], PArgs[I], Args,
+                                         Depth))
         return false;
     return true;
   }
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -1774,6 +1774,17 @@
   return nullptr;
 }
 
+const TemplateSpecializationType *
+Type::getAsNonAliasTemplateSpecializationType() const {
+  for (auto T = this; /**/; /**/) {
+    const TemplateSpecializationType *TST =
+        T->getAs<TemplateSpecializationType>();
+    if (!TST || !TST->isTypeAlias())
+      return TST;
+    T = TST->desugar().getTypePtr();
+  }
+}
+
 bool Type::hasAttr(attr::Kind AK) const {
   const Type *Cur = this;
   while (const auto *AT = Cur->getAs<AttributedType>()) {
@@ -3738,17 +3749,20 @@
 }
 
 TemplateSpecializationType::TemplateSpecializationType(
-    TemplateName T, ArrayRef<TemplateArgument> Args, QualType Canon,
-    QualType AliasedType)
-    : Type(TemplateSpecialization, Canon.isNull() ? QualType(this, 0) : Canon,
-           (Canon.isNull()
+    TemplateName T, bool IsAlias, ArrayRef<TemplateArgument> SpecifiedArgs,
+    ArrayRef<TemplateArgument> ConvertedArgs, QualType Underlying)
+    : Type(TemplateSpecialization,
+           Underlying.isNull() ? QualType(this, 0)
+                               : Underlying.getCanonicalType(),
+           (Underlying.isNull()
                 ? TypeDependence::DependentInstantiation
-                : toSemanticDependence(Canon->getDependence())) |
+                : toSemanticDependence(Underlying->getDependence())) |
                (toTypeDependence(T.getDependence()) &
                 TypeDependence::UnexpandedPack)),
       Template(T) {
-  TemplateSpecializationTypeBits.NumArgs = Args.size();
-  TemplateSpecializationTypeBits.TypeAlias = !AliasedType.isNull();
+  TemplateSpecializationTypeBits.NumSpecifiedArgs = SpecifiedArgs.size();
+  TemplateSpecializationTypeBits.NumConvertedArgs = ConvertedArgs.size();
+  TemplateSpecializationTypeBits.TypeAlias = IsAlias;
 
   assert(!T.getAsDependentTemplateName() &&
          "Use DependentTemplateSpecializationType for dependent template-name");
@@ -3758,51 +3772,69 @@
           T.getKind() == TemplateName::UsingTemplate) &&
          "Unexpected template name for TemplateSpecializationType");
 
-  auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);
-  for (const TemplateArgument &Arg : Args) {
-    // Update instantiation-dependent, variably-modified, and error bits.
-    // If the canonical type exists and is non-dependent, the template
-    // specialization type can be non-dependent even if one of the type
-    // arguments is. Given:
-    //   template<typename T> using U = int;
-    // U<T> is always non-dependent, irrespective of the type T.
-    // However, U<Ts> contains an unexpanded parameter pack, even though
-    // its expansion (and thus its desugared type) doesn't.
-    addDependence(toTypeDependence(Arg.getDependence()) &
-                  ~TypeDependence::Dependent);
-    if (Arg.getKind() == TemplateArgument::Type)
-      addDependence(Arg.getAsType()->getDependence() &
-                    TypeDependence::VariablyModified);
-    new (TemplateArgs++) TemplateArgument(Arg);
-  }
+  auto initArgs = [this](ArrayRef<TemplateArgument> Out,
+                         ArrayRef<TemplateArgument> In) {
+    auto *Args = const_cast<TemplateArgument *>(Out.data());
+    for (const TemplateArgument &Arg : In) {
+      // Update instantiation-dependent, variably-modified, and error bits.
+      // If the canonical type exists and is non-dependent, the template
+      // specialization type can be non-dependent even if one of the type
+      // arguments is. Given:
+      //   template<typename T> using U = int;
+      // U<T> is always non-dependent, irrespective of the type T.
+      // However, U<Ts> contains an unexpanded parameter pack, even though
+      // its expansion (and thus its desugared type) doesn't.
+      addDependence(toTypeDependence(Arg.getDependence()) &
+                    ~TypeDependence::Dependent);
+      if (Arg.getKind() == TemplateArgument::Type)
+        addDependence(Arg.getAsType()->getDependence() &
+                      TypeDependence::VariablyModified);
+      new (Args++) TemplateArgument(Arg);
+    }
+  };
+
+  initArgs(template_arguments(), SpecifiedArgs);
+  initArgs(getConvertedArguments(), ConvertedArgs);
 
   // Store the aliased type if this is a type alias template specialization.
-  if (isTypeAlias()) {
-    auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
-    *reinterpret_cast<QualType *>(Begin + Args.size()) = AliasedType;
-  }
+  if (IsAlias)
+    *reinterpret_cast<QualType *>(const_cast<TemplateArgument *>(
+        getConvertedArguments().end())) = Underlying;
 }
 
 QualType TemplateSpecializationType::getAliasedType() const {
   assert(isTypeAlias() && "not a type alias template specialization");
-  return *reinterpret_cast<const QualType *>(template_arguments().end());
+  return *reinterpret_cast<const QualType *>(getConvertedArguments().end());
+}
+
+ArrayRef<TemplateArgument>
+TemplateSpecializationType::getConvertedArguments() const {
+  return {template_arguments().end(),
+          TemplateSpecializationTypeBits.NumConvertedArgs};
 }
 
 void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
                                          const ASTContext &Ctx) {
-  Profile(ID, Template, template_arguments(), Ctx);
-  if (isTypeAlias())
-    getAliasedType().Profile(ID);
+  Profile(ID, Template, template_arguments(), getConvertedArguments(),
+          isSugared() ? desugar() : QualType(), Ctx);
 }
 
-void
-TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
-                                    TemplateName T,
-                                    ArrayRef<TemplateArgument> Args,
-                                    const ASTContext &Context) {
+void TemplateSpecializationType::Profile(
+    llvm::FoldingSetNodeID &ID, TemplateName T,
+    ArrayRef<TemplateArgument> SpecifiedArgs,
+    ArrayRef<TemplateArgument> ConvertedArgs, QualType Underlying,
+    const ASTContext &Context) {
   T.Profile(ID);
-  for (const TemplateArgument &Arg : Args)
+
+  ID.AddInteger(SpecifiedArgs.size());
+  for (const TemplateArgument &Arg : SpecifiedArgs)
+    Arg.Profile(ID, Context);
+
+  ID.AddInteger(ConvertedArgs.size());
+  for (const TemplateArgument &Arg : ConvertedArgs)
     Arg.Profile(ID, Context);
+
+  Underlying.Profile(ID);
 }
 
 QualType
Index: clang/lib/AST/QualTypeNames.cpp
===================================================================
--- clang/lib/AST/QualTypeNames.cpp
+++ clang/lib/AST/QualTypeNames.cpp
@@ -141,8 +141,8 @@
     // allocate new type in the AST.
     if (MightHaveChanged) {
       QualType QT = Ctx.getTemplateSpecializationType(
-          TST->getTemplateName(), FQArgs,
-          TST->getCanonicalTypeInternal());
+          TST->getTemplateName(), FQArgs, TST->getConvertedArguments(),
+          /*CanonicalConvertedArgs=*/None, TST->getCanonicalTypeInternal());
       // getTemplateSpecializationType returns a fully qualified
       // version of the specialization itself, so no need to qualify
       // it.
@@ -173,7 +173,8 @@
       if (MightHaveChanged) {
         TemplateName TN(TSTDecl->getSpecializedTemplate());
         QualType QT = Ctx.getTemplateSpecializationType(
-            TN, FQArgs,
+            TN, FQArgs, FQArgs,
+            /*CanonicalConvertedArgs=*/None,
             TSTRecord->getCanonicalTypeInternal());
         // getTemplateSpecializationType returns a fully qualified
         // version of the specialization itself, so no need to qualify
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -1240,7 +1240,9 @@
       // FIXME: GCC does not appear to mangle the template arguments when
       // the template in question is a dependent template name. Should we
       // emulate that badness?
-      mangleTemplateArgs(TST->getTemplateName(), TST->template_arguments());
+      auto Args = TST->isCanonicalUnqualified() ? TST->getConvertedArguments()
+                                                : TST->template_arguments();
+      mangleTemplateArgs(TST->getTemplateName(), Args);
       addSubstitution(QualType(TST, 0));
     }
   } else if (const auto *DTST =
@@ -2406,13 +2408,14 @@
       break;
     }
     }
-
+    auto Args = TST->isCanonicalUnqualified() ? TST->getConvertedArguments()
+                                              : TST->template_arguments();
     // Note: we don't pass in the template name here. We are mangling the
     // original source-level template arguments, so we shouldn't consider
     // conversions to the corresponding template parameter.
     // FIXME: Other compilers mangle partially-resolved template arguments in
     // unresolved-qualifier-levels.
-    mangleTemplateArgs(TemplateName(), TST->template_arguments());
+    mangleTemplateArgs(TemplateName(), Args);
     break;
   }
 
@@ -3869,8 +3872,10 @@
 }
 
 void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
+  auto Args = T->isCanonicalUnqualified() ? T->getConvertedArguments()
+                                          : T->template_arguments();
   if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
-    mangleTemplateName(TD, T->template_arguments());
+    mangleTemplateName(TD, Args);
   } else {
     if (mangleSubstitution(QualType(T, 0)))
       return;
@@ -3880,7 +3885,7 @@
     // FIXME: GCC does not appear to mangle the template arguments when
     // the template in question is a dependent template name. Should we
     // emulate that badness?
-    mangleTemplateArgs(T->getTemplateName(), T->template_arguments());
+    mangleTemplateArgs(T->getTemplateName(), Args);
     addSubstitution(QualType(T, 0));
   }
 }
Index: clang/lib/AST/DeclTemplate.cpp
===================================================================
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -627,9 +627,11 @@
   TemplateParameterList *Params = getTemplateParameters();
   SmallVector<TemplateArgument, 16> TemplateArgs;
   Context.getInjectedTemplateArgs(Params, TemplateArgs);
-  CommonPtr->InjectedClassNameType
-    = Context.getTemplateSpecializationType(TemplateName(this),
-                                            TemplateArgs);
+  CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(
+      TemplateName(this),
+      /*SpecifiedArgs=*/TemplateArgs,
+      /*SugaredConvertedArgs=*/TemplateArgs,
+      /*CanonicalConvertedArgs=*/None);
   return CommonPtr->InjectedClassNameType;
 }
 
Index: clang/lib/AST/ASTStructuralEquivalence.cpp
===================================================================
--- clang/lib/AST/ASTStructuralEquivalence.cpp
+++ clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1108,6 +1108,9 @@
     if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
                                   Spec2->template_arguments()))
       return false;
+    if (!IsStructurallyEquivalent(Context, Spec1->getConvertedArguments(),
+                                  Spec2->getConvertedArguments()))
+      return false;
     break;
   }
 
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1555,6 +1555,11 @@
           ImportTemplateArguments(T->template_arguments(), ToTemplateArgs))
     return std::move(Err);
 
+  SmallVector<TemplateArgument, 2> ToConvertedArgs;
+  if (Error Err =
+          ImportTemplateArguments(T->getConvertedArguments(), ToConvertedArgs))
+    return std::move(Err);
+
   QualType ToCanonType;
   if (!T->isCanonicalUnqualified()) {
     QualType FromCanonType
@@ -1564,9 +1569,9 @@
     else
       return TyOrErr.takeError();
   }
-  return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr,
-                                                               ToTemplateArgs,
-                                                               ToCanonType);
+  return Importer.getToContext().getTemplateSpecializationType(
+      *ToTemplateOrErr, ToTemplateArgs, ToConvertedArgs,
+      /*CanonicalConvertedArgs=*/None, ToCanonType);
 }
 
 ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
Index: clang/lib/AST/ASTDiagnostic.cpp
===================================================================
--- clang/lib/AST/ASTDiagnostic.cpp
+++ clang/lib/AST/ASTDiagnostic.cpp
@@ -129,7 +129,8 @@
         if (DesugarArgument) {
           ShouldAKA = true;
           QT = Context.getTemplateSpecializationType(
-              TST->getTemplateName(), Args, QT);
+              TST->getTemplateName(), Args, TST->getConvertedArguments(),
+              /*CanonicalConvertedArguments=*/None, QT);
         }
         break;
       }
@@ -1134,9 +1135,11 @@
       return nullptr;
 
     Ty = Context.getTemplateSpecializationType(
-             TemplateName(CTSD->getSpecializedTemplate()),
-             CTSD->getTemplateArgs().asArray(),
-             Ty.getLocalUnqualifiedType().getCanonicalType());
+        TemplateName(CTSD->getSpecializedTemplate()),
+        /*SpecifiedArgs=*/CTSD->getTemplateArgs().asArray(),
+        /*SugaredConvertedArgs=*/CTSD->getTemplateArgs().asArray(),
+        /*CanonicalConvertedArgs=*/None,
+        Ty.getLocalUnqualifiedType().getCanonicalType());
 
     return Ty->getAs<TemplateSpecializationType>();
   }
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -3049,12 +3049,19 @@
                                           ArrayRef<TemplateArgument> Args,
                                           bool &AnyNonCanonArgs) {
   SmallVector<TemplateArgument, 16> CanonArgs(Args);
-  for (auto &Arg : CanonArgs) {
+  AnyNonCanonArgs |= C.canonicalizeTemplateArguments(CanonArgs);
+  return CanonArgs;
+}
+
+bool ASTContext::canonicalizeTemplateArguments(
+    MutableArrayRef<TemplateArgument> Args) const {
+  bool AnyNonCanonArgs = false;
+  for (auto &Arg : Args) {
     TemplateArgument OrigArg = Arg;
-    Arg = C.getCanonicalTemplateArgument(Arg);
+    Arg = getCanonicalTemplateArgument(Arg);
     AnyNonCanonArgs |= !Arg.structurallyEquals(OrigArg);
   }
-  return CanonArgs;
+  return AnyNonCanonArgs;
 }
 
 //===----------------------------------------------------------------------===//
@@ -4934,41 +4941,41 @@
   return QualType(TypeParm, 0);
 }
 
-TypeSourceInfo *
-ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
-                                              SourceLocation NameLoc,
-                                        const TemplateArgumentListInfo &Args,
-                                              QualType Underlying) const {
-  assert(!Name.getAsDependentTemplateName() &&
-         "No dependent template names here!");
-  QualType TST =
-      getTemplateSpecializationType(Name, Args.arguments(), Underlying);
+TypeSourceInfo *ASTContext::getTemplateSpecializationTypeInfo(
+    TemplateName Name, SourceLocation NameLoc,
+    const TemplateArgumentListInfo &SpecifiedArgs,
+    ArrayRef<TemplateArgument> SugaredConvertedArgs,
+    ArrayRef<TemplateArgument> CanonicalConvertedArgs,
+    QualType Underlying) const {
+  QualType TST = getTemplateSpecializationType(
+      Name, SpecifiedArgs.arguments(), SugaredConvertedArgs,
+      CanonicalConvertedArgs, Underlying);
 
   TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
   TemplateSpecializationTypeLoc TL =
       DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>();
   TL.setTemplateKeywordLoc(SourceLocation());
   TL.setTemplateNameLoc(NameLoc);
-  TL.setLAngleLoc(Args.getLAngleLoc());
-  TL.setRAngleLoc(Args.getRAngleLoc());
+  TL.setLAngleLoc(SpecifiedArgs.getLAngleLoc());
+  TL.setRAngleLoc(SpecifiedArgs.getRAngleLoc());
   for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
-    TL.setArgLocInfo(i, Args[i].getLocInfo());
+    TL.setArgLocInfo(i, SpecifiedArgs[i].getLocInfo());
   return DI;
 }
 
-QualType
-ASTContext::getTemplateSpecializationType(TemplateName Template,
-                                          ArrayRef<TemplateArgumentLoc> Args,
-                                          QualType Underlying) const {
-  assert(!Template.getAsDependentTemplateName() &&
-         "No dependent template names here!");
-
-  SmallVector<TemplateArgument, 4> ArgVec;
-  ArgVec.reserve(Args.size());
-  for (const TemplateArgumentLoc &Arg : Args)
-    ArgVec.push_back(Arg.getArgument());
+QualType ASTContext::getTemplateSpecializationType(
+    TemplateName Template, ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
+    ArrayRef<TemplateArgument> SugaredConvertedArgs,
+    ArrayRef<TemplateArgument> CanonicalConvertedArgs,
+    QualType Underlying) const {
+  SmallVector<TemplateArgument, 4> SpecifiedArgVec;
+  SpecifiedArgVec.reserve(SpecifiedArgs.size());
+  for (const TemplateArgumentLoc &Arg : SpecifiedArgs)
+    SpecifiedArgVec.push_back(Arg.getArgument());
 
-  return getTemplateSpecializationType(Template, ArgVec, Underlying);
+  return getTemplateSpecializationType(Template, SpecifiedArgVec,
+                                       SugaredConvertedArgs,
+                                       CanonicalConvertedArgs, Underlying);
 }
 
 #ifndef NDEBUG
@@ -4981,84 +4988,88 @@
 }
 #endif
 
-QualType
-ASTContext::getTemplateSpecializationType(TemplateName Template,
-                                          ArrayRef<TemplateArgument> Args,
-                                          QualType Underlying) const {
+QualType ASTContext::getTemplateSpecializationType(
+    TemplateName Template, ArrayRef<TemplateArgument> SpecifiedArgs,
+    ArrayRef<TemplateArgument> SugaredConvertedArgs,
+    ArrayRef<TemplateArgument> CanonicalConvertedArgs,
+    QualType Underlying) const {
   assert(!Template.getAsDependentTemplateName() &&
          "No dependent template names here!");
-  // Look through qualified template names.
-  if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
-    Template = QTN->getUnderlyingTemplate();
 
-  const auto *TD = Template.getAsTemplateDecl();
-  bool IsTypeAlias = TD && TD->isTypeAlias();
-  QualType CanonType;
-  if (!Underlying.isNull())
-    CanonType = getCanonicalType(Underlying);
-  else {
-    // We can get here with an alias template when the specialization contains
-    // a pack expansion that does not match up with a parameter pack.
-    assert((!IsTypeAlias || hasAnyPackExpansions(Args)) &&
-           "Caller must compute aliased type");
-    IsTypeAlias = false;
-    CanonType = getCanonicalTemplateSpecializationType(Template, Args);
+  bool AnyNonCanonArgs = false;
+  if (CanonicalConvertedArgs.size() != 0) {
+#ifndef NDEBUG
+    for (const TemplateArgument &A : CanonicalConvertedArgs)
+      assert(A.structurallyEquals(getCanonicalTemplateArgument(A)));
+#endif
+    if (SugaredConvertedArgs.empty()) {
+      SugaredConvertedArgs = CanonicalConvertedArgs;
+    } else {
+      assert(SugaredConvertedArgs.size() == CanonicalConvertedArgs.size());
+      for (unsigned I = 0; I < SugaredConvertedArgs.size(); ++I) {
+        if (!CanonicalConvertedArgs[I].structurallyEquals(
+                SugaredConvertedArgs[I])) {
+          AnyNonCanonArgs = true;
+          break;
+        }
+      }
+    }
   }
 
-  // Allocate the (non-canonical) template specialization type, but don't
-  // try to unique it: these types typically have location information that
-  // we don't unique and don't want to lose.
-  void *Mem = Allocate(sizeof(TemplateSpecializationType) +
-                       sizeof(TemplateArgument) * Args.size() +
-                       (IsTypeAlias? sizeof(QualType) : 0),
-                       TypeAlignment);
-  auto *Spec
-    = new (Mem) TemplateSpecializationType(Template, Args, CanonType,
-                                         IsTypeAlias ? Underlying : QualType());
-
-  Types.push_back(Spec);
-  return QualType(Spec, 0);
-}
-
-QualType ASTContext::getCanonicalTemplateSpecializationType(
-    TemplateName Template, ArrayRef<TemplateArgument> Args) const {
-  assert(!Template.getAsDependentTemplateName() &&
-         "No dependent template names here!");
-
   // Look through qualified template names.
   if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
-    Template = TemplateName(QTN->getUnderlyingTemplate());
-
-  // Build the canonical template specialization type.
-  TemplateName CanonTemplate = getCanonicalTemplateName(Template);
-  bool AnyNonCanonArgs = false;
-  auto CanonArgs =
-      ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
+    Template = QTN->getUnderlyingTemplate();
 
-  // Determine whether this canonical template specialization type already
-  // exists.
   llvm::FoldingSetNodeID ID;
-  TemplateSpecializationType::Profile(ID, CanonTemplate,
-                                      CanonArgs, *this);
+  TemplateSpecializationType::Profile(ID, Template, SpecifiedArgs,
+                                      SugaredConvertedArgs, Underlying, *this);
 
   void *InsertPos = nullptr;
-  TemplateSpecializationType *Spec
-    = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+  if (auto *T = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(T, 0);
 
-  if (!Spec) {
-    // Allocate a new canonical template specialization type.
-    void *Mem = Allocate((sizeof(TemplateSpecializationType) +
-                          sizeof(TemplateArgument) * CanonArgs.size()),
-                         TypeAlignment);
-    Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
-                                                CanonArgs,
-                                                QualType(), QualType());
-    Types.push_back(Spec);
-    TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+  const auto *TD = Template.getAsTemplateDecl();
+  bool IsTypeAlias = TD && TD->isTypeAlias();
+  if (Underlying.isNull()) {
+    // We can get here with an alias template when the specialization
+    // contains a pack expansion that does not match up with a parameter
+    // pack.
+    assert((!IsTypeAlias || hasAnyPackExpansions(CanonicalConvertedArgs)) &&
+           "Caller must compute aliased type");
+    IsTypeAlias = false;
+    TemplateName CanonTemplate = getCanonicalTemplateName(Template);
+
+    SmallVector<TemplateArgument, 4> CanonArgsVec;
+    if (CanonicalConvertedArgs.size() == 0) {
+      CanonArgsVec = ::getCanonicalTemplateArguments(
+          *this, SugaredConvertedArgs, AnyNonCanonArgs);
+      CanonicalConvertedArgs = CanonArgsVec;
+    }
+
+    if (AnyNonCanonArgs || !SpecifiedArgs.empty() ||
+        Template.getAsVoidPointer() != CanonTemplate.getAsVoidPointer()) {
+      Underlying = getTemplateSpecializationType(
+          CanonTemplate, ArrayRef<TemplateArgument>(), None,
+          CanonicalConvertedArgs, QualType());
+      assert(Underlying->isDependentType() &&
+             "Non-dependent template-id type must have a canonical type");
+      [[maybe_unused]] const auto *Found =
+          TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+      assert(!Found);
+    }
   }
 
-  assert(Spec->isDependentType() &&
-         "Non-dependent template-id type must have a canonical type");
+  void *Mem =
+      Allocate(sizeof(TemplateSpecializationType) +
+                   sizeof(TemplateArgument) *
+                       (SpecifiedArgs.size() + SugaredConvertedArgs.size()) +
+                   (IsTypeAlias ? sizeof(QualType) : 0),
+               TypeAlignment);
+  auto *Spec = new (Mem) TemplateSpecializationType(
+      Template, IsTypeAlias, SpecifiedArgs, SugaredConvertedArgs, Underlying);
+
+  Types.push_back(Spec);
+  TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
   return QualType(Spec, 0);
 }
 
@@ -7387,8 +7398,7 @@
 void ASTContext::setCFConstantStringType(QualType T) {
   const auto *TD = T->castAs<TypedefType>();
   CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl());
-  const auto *TagType =
-      CFConstantStringTypeDecl->getUnderlyingType()->castAs<RecordType>();
+  const auto *TagType = TD->castAs<RecordType>();
   CFConstantStringTagDecl = TagType->getDecl();
 }
 
@@ -12783,12 +12793,15 @@
   case Type::TemplateSpecialization: {
     const auto *TX = cast<TemplateSpecializationType>(X),
                *TY = cast<TemplateSpecializationType>(Y);
-    auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(),
-                                         TY->template_arguments());
+    auto SpecAs = getCommonTemplateArguments(Ctx, TX->template_arguments(),
+                                             TY->template_arguments());
+    auto ConvAs = getCommonTemplateArguments(Ctx, TX->getConvertedArguments(),
+                                             TY->getConvertedArguments());
     return Ctx.getTemplateSpecializationType(
         ::getCommonTemplateNameChecked(Ctx, TX->getTemplateName(),
                                        TY->getTemplateName()),
-        As, X->getCanonicalTypeInternal());
+        SpecAs, ConvAs, /*CanonicalConvertedArgs=*/{},
+        X->getCanonicalTypeInternal());
   }
   case Type::DependentName: {
     const auto *NX = cast<DependentNameType>(X),
@@ -12998,11 +13011,14 @@
                                                TY->getTemplateName());
     if (!CTN.getAsVoidPointer())
       return QualType();
-    SmallVector<TemplateArgument, 8> Args;
-    if (getCommonTemplateArguments(Ctx, Args, TX->template_arguments(),
+    SmallVector<TemplateArgument, 8> SpecAs;
+    if (getCommonTemplateArguments(Ctx, SpecAs, TX->template_arguments(),
                                    TY->template_arguments()))
       return QualType();
-    return Ctx.getTemplateSpecializationType(CTN, Args,
+    auto ConvAs = getCommonTemplateArguments(Ctx, TX->getConvertedArguments(),
+                                             TY->getConvertedArguments());
+    return Ctx.getTemplateSpecializationType(CTN, SpecAs, ConvAs,
+                                             /*CanonicalConvertedArgs=*/{},
                                              Ctx.getQualifiedType(Underlying));
   }
   case Type::Typedef: {
Index: clang/include/clang/Serialization/ASTRecordReader.h
===================================================================
--- clang/include/clang/Serialization/ASTRecordReader.h
+++ clang/include/clang/Serialization/ASTRecordReader.h
@@ -249,6 +249,10 @@
   void readTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
                                 bool Canonicalize = false);
 
+  /// Read a template argument list.
+  const TemplateArgumentList *
+  readTemplateArgumentList(bool Canonicalize = false);
+
   /// Read a UnresolvedSet structure, advancing Idx.
   void readUnresolvedSet(LazyASTUnresolvedSet &Set);
 
Index: clang/include/clang/AST/TypeProperties.td
===================================================================
--- clang/include/clang/AST/TypeProperties.td
+++ clang/include/clang/AST/TypeProperties.td
@@ -660,29 +660,27 @@
   def : Property<"templateName", TemplateName> {
     let Read = [{ node->getTemplateName() }];
   }
-  def : Property<"templateArguments", Array<TemplateArgument>> {
+  def : Property<"specifiedArguments", Array<TemplateArgument>> {
     let Read = [{ node->template_arguments() }];
   }
-  def : Property<"underlyingType", Optional<QualType>> {
+  def : Property<"convertedArguments", Array<TemplateArgument>> {
+    let Read = [{ node->getConvertedArguments() }];
+  }
+  def : Property<"underlyingType", QualType> {
     let Read = [{
       node->isTypeAlias()
-        ? llvm::Optional<QualType>(node->getAliasedType())
+        ? node->getAliasedType()
         : node->isCanonicalUnqualified()
-            ? llvm::None
-            : llvm::Optional<QualType>(node->getCanonicalTypeInternal())
+            ? QualType() : node->getCanonicalTypeInternal()
     }];
   }
 
   def : Creator<[{
-    QualType result;
-    if (!underlyingType) {
-      result = ctx.getCanonicalTemplateSpecializationType(templateName,
-                                                          templateArguments);
-    } else {
-      result = ctx.getTemplateSpecializationType(templateName,
-                                                 templateArguments,
-                                                 *underlyingType);
-    }
+    QualType result = ctx.getTemplateSpecializationType(templateName,
+                                                        specifiedArguments,
+                                                        convertedArguments,
+                                                        /*CanonicalConvertedArguments=*/{},
+                                                        underlyingType);
     if (dependent)
       const_cast<Type *>(result.getTypePtr())
           ->addDependence(TypeDependence::DependentInstantiation);
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -1870,10 +1870,9 @@
     /// specialization, which is expected to be able to hold at least 1024
     /// according to [implimits]. However, as this limit is somewhat easy to
     /// hit with template metaprogramming we'd prefer to keep it as large
-    /// as possible. At the moment it has been left as a non-bitfield since
-    /// this type safely fits in 64 bits as an unsigned, so there is no reason
-    /// to introduce the performance impact of a bitfield.
-    unsigned NumArgs;
+    /// as possible.
+    unsigned NumSpecifiedArgs : 16;
+    unsigned NumConvertedArgs : 16;
   };
 
   class DependentTemplateSpecializationTypeBitfields {
@@ -2423,6 +2422,18 @@
   /// immediately following this class.
   template <typename T> const T *getAs() const;
 
+  /// Look through sugar for an instance of TemplateSpecializationType which
+  /// is not a type alias.
+  const TemplateSpecializationType *
+  getAsNonAliasTemplateSpecializationType() const;
+
+  const TemplateSpecializationType *
+  castAsNonAliasTemplateSpecializationType() const {
+    auto TST = getAsNonAliasTemplateSpecializationType();
+    assert(TST && "not a TemplateSpecializationType");
+    return TST;
+  }
+
   /// Member-template getAsAdjusted<specific type>. Look through specific kinds
   /// of sugar (parens, attributes, etc) for an instance of \<specific type>.
   /// This is used when you need to walk over sugar nodes that represent some
@@ -5365,10 +5376,10 @@
   /// replacement must, recursively, be one of these).
   TemplateName Template;
 
-  TemplateSpecializationType(TemplateName T,
-                             ArrayRef<TemplateArgument> Args,
-                             QualType Canon,
-                             QualType Aliased);
+  TemplateSpecializationType(TemplateName T, bool IsAlias,
+                             ArrayRef<TemplateArgument> SpecifiedArgs,
+                             ArrayRef<TemplateArgument> ConvertedArgs,
+                             QualType Underlying);
 
 public:
   /// Determine whether any of the given template arguments are dependent.
@@ -5423,9 +5434,11 @@
 
   ArrayRef<TemplateArgument> template_arguments() const {
     return {reinterpret_cast<const TemplateArgument *>(this + 1),
-            TemplateSpecializationTypeBits.NumArgs};
+            TemplateSpecializationTypeBits.NumSpecifiedArgs};
   }
 
+  ArrayRef<TemplateArgument> getConvertedArguments() const;
+
   bool isSugared() const {
     return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
   }
@@ -5436,8 +5449,9 @@
 
   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
   static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
-                      ArrayRef<TemplateArgument> Args,
-                      const ASTContext &Context);
+                      ArrayRef<TemplateArgument> SpecifiedArgs,
+                      ArrayRef<TemplateArgument> ConvertedArgs,
+                      QualType Underlying, const ASTContext &Context);
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == TemplateSpecialization;
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1099,7 +1099,10 @@
 
 DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
   TRY_TO(TraverseTemplateName(T->getTemplateName()));
-  TRY_TO(TraverseTemplateArguments(T->template_arguments()));
+  if (T->isCanonicalUnqualified())
+    TRY_TO(TraverseTemplateArguments(T->getConvertedArguments()));
+  else
+    TRY_TO(TraverseTemplateArguments(T->template_arguments()));
 })
 
 DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -1629,22 +1629,24 @@
                           bool ParameterPack,
                           TemplateTypeParmDecl *ParmDecl = nullptr) const;
 
-  QualType getTemplateSpecializationType(TemplateName T,
-                                         ArrayRef<TemplateArgument> Args,
-                                         QualType Canon = QualType()) const;
-
-  QualType
-  getCanonicalTemplateSpecializationType(TemplateName T,
-                                         ArrayRef<TemplateArgument> Args) const;
-
-  QualType getTemplateSpecializationType(TemplateName T,
-                                         ArrayRef<TemplateArgumentLoc> Args,
-                                         QualType Canon = QualType()) const;
-
-  TypeSourceInfo *
-  getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
-                                    const TemplateArgumentListInfo &Args,
-                                    QualType Canon = QualType()) const;
+  QualType getTemplateSpecializationType(
+      TemplateName T, ArrayRef<TemplateArgument> SpecifiedArgs,
+      ArrayRef<TemplateArgument> SugaredConvertedArgs,
+      ArrayRef<TemplateArgument> CanonicalConvertedArgs,
+      QualType Canon = QualType()) const;
+
+  QualType getTemplateSpecializationType(
+      TemplateName T, ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
+      ArrayRef<TemplateArgument> SugaredConvertedArgs,
+      ArrayRef<TemplateArgument> CanonicalConvertedArgs,
+      QualType Canon = QualType()) const;
+
+  TypeSourceInfo *getTemplateSpecializationTypeInfo(
+      TemplateName T, SourceLocation TLoc,
+      const TemplateArgumentListInfo &SpecifiedArgs,
+      ArrayRef<TemplateArgument> SugaredConvertedArgs,
+      ArrayRef<TemplateArgument> CanonicalConvertedArgs,
+      QualType Canon = QualType()) const;
 
   QualType getParenType(QualType NamedType) const;
 
@@ -2718,6 +2720,12 @@
   TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
     const;
 
+  /// Canonicalize the given template argument list.
+  ///
+  /// Returns true if any arguments were non-canonical, false otherwise.
+  bool
+  canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
+
   /// Type Query functions.  If the type is an instance of the specified class,
   /// return the Type pointer for the underlying maximally pretty type.  This
   /// is a member of ASTContext because this may need to do some amount of
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to