mizvekov updated this revision to Diff 374921.
mizvekov added a comment.

update print-type.cpp test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110216

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
  clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/ASTTests.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp
  clang-tools-extra/clangd/unittests/InlayHintTests.cpp
  clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
  clang-tools-extra/test/clang-tidy/checkers/cert-static-object-exception.cpp
  clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-owning-memory.cpp
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/Type.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Type.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaLambda.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaType.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
  clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
  clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
  clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
  clang/test/Index/print-type.cpp
  clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
  clang/test/SemaCXX/cxx1z-decomposition.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaCXX/friend.cpp
  clang/test/SemaCXX/recovery-expr-type.cpp
  clang/test/SemaCXX/sizeless-1.cpp
  clang/test/SemaCXX/sugared-auto.cpp
  clang/test/SemaTemplate/attributes.cpp
  clang/test/SemaTemplate/friend.cpp
  clang/test/SemaTemplate/operator-template.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -6176,26 +6176,9 @@
       FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
 
   FunctionDecl *To = Import(From, Lang_CXX14);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
-}
-
-TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
-  Decl *FromTU = getTuDecl(
-      R"(
-      auto foo() {
-        struct X {};
-        return X();
-      }
-      )",
-      Lang_CXX14, "input0.cc");
-  FunctionDecl *From =
-      FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
-
-  // This time import the type directly.
-  QualType ToT = ImportType(From->getType(), From, Lang_CXX14);
-  const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);
-  EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
@@ -6212,8 +6195,9 @@
       FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
 
   FunctionDecl *To = Import(From, Lang_CXX14);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
@@ -6229,8 +6213,9 @@
       FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
 
   FunctionDecl *To = Import(From, Lang_CXX14);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
@@ -6249,8 +6234,9 @@
       FromTU, functionDecl(hasName("f")));
 
   FunctionDecl *To = Import(From, Lang_CXX17);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
@@ -6268,8 +6254,9 @@
       FromTU, functionDecl(hasName("f")));
 
   FunctionDecl *To = Import(From, Lang_CXX17);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
@@ -6285,8 +6272,9 @@
       FromTU, functionDecl(hasName("f")));
 
   FunctionDecl *To = Import(From, Lang_CXX17);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
@@ -6304,8 +6292,9 @@
       FromTU, functionDecl(hasName("f")));
 
   FunctionDecl *To = Import(From, Lang_CXX17);
-  EXPECT_TRUE(To);
-  EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+  // FIXME: We do not support importing these.
+  // EXPECT: error: cannot import unsupported AST node CXXRecord
+  EXPECT_FALSE(To);
 }
 
 struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
Index: clang/test/SemaTemplate/operator-template.cpp
===================================================================
--- clang/test/SemaTemplate/operator-template.cpp
+++ clang/test/SemaTemplate/operator-template.cpp
@@ -2,7 +2,7 @@
 
 // Make sure we accept this
 template<class X>struct A{typedef X Y;};
-template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: could not match 'A<type-parameter-0-0>' against 'B<int> *'}}
+template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: could not match 'A<X>' against 'B<int> *'}}
 
 int a(A<int> x) { return operator==(x,1); }
 
Index: clang/test/SemaTemplate/friend.cpp
===================================================================
--- clang/test/SemaTemplate/friend.cpp
+++ clang/test/SemaTemplate/friend.cpp
@@ -50,7 +50,7 @@
 
 namespace qualified_friend {
   void f(int); // expected-note 2{{type mismatch at 1st parameter}}
-  template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
+  template<typename T> void f(T*); // expected-note 2{{could not match 'T *' against 'double'}}
   template<typename T> void nondep();
 
   template<typename> struct X1 {
@@ -66,7 +66,7 @@
 
   struct Y {
     void f(int); // expected-note 2{{type mismatch at 1st parameter}}
-    template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
+    template<typename T> void f(T*); // expected-note 2{{could not match 'T *' against 'double'}}
     template<typename T> void nondep();
   };
 
Index: clang/test/SemaTemplate/attributes.cpp
===================================================================
--- clang/test/SemaTemplate/attributes.cpp
+++ clang/test/SemaTemplate/attributes.cpp
@@ -125,7 +125,7 @@
              clang::preferred_name(const_iterator)]] Iter {};
   };
   auto it = MemberTemplate<int>::Iter<const int>();
-  int n = it; // expected-error {{no viable conversion from 'preferred_name::MemberTemplate<int>::const_iterator' to 'int'}}
+  int n = it; // expected-error {{no viable conversion from 'MemberTemplate<int>::Iter<const int>' to 'int'}}
 
   template<int A, int B, typename ...T> struct Foo;
   template<typename ...T> using Bar = Foo<1, 2, T...>;
Index: clang/test/SemaCXX/sugared-auto.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/sugared-auto.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
+
+enum class N {};
+
+using T1 = int;
+auto x1 = T1();
+N t1 = x1;
+// expected-error@-1 {{cannot initialize a variable of type 'N' with an lvalue of type 'T1' (aka 'int')}}
+
+using T2 = T1 *;
+auto x2 = T2();
+N t2 = x2;
+// expected-error@-1 {{cannot initialize a variable of type 'N' with an lvalue of type 'T2' (aka 'int *')}}
+
+auto *x3 = T2();
+N t3 = x3;
+// expected-error@-1 {{cannot initialize a variable of type 'N' with an lvalue of type 'T1 *' (aka 'int *')}}
+
+auto f1() { return T1(); }
+auto x4 = f1();
+N t4 = x4;
+// expected-error@-1 {{cannot initialize a variable of type 'N' with an lvalue of type 'T1' (aka 'int')}}
+
+decltype(auto) f2() { return T1(); }
+auto x5 = f2();
+N t5 = x5;
+// expected-error@-1 {{cannot initialize a variable of type 'N' with an lvalue of type 'T1' (aka 'int')}}
+
+auto x6 = [a = T1()] { return a; }();
+N t6 = x6;
+// expected-error@-1 {{cannot initialize a variable of type 'N' with an lvalue of type 'T1' (aka 'int')}}
Index: clang/test/SemaCXX/sizeless-1.cpp
===================================================================
--- clang/test/SemaCXX/sizeless-1.cpp
+++ clang/test/SemaCXX/sizeless-1.cpp
@@ -581,7 +581,7 @@
   auto auto_int8 = local_int8;
   auto auto_int16 = local_int16;
 #if __cplusplus >= 201703L
-  auto [auto_int8_a] = local_int8; // expected-error {{cannot decompose non-class, non-array type '__SVInt8_t'}}
+  auto [auto_int8_a] = local_int8; // expected-error {{cannot decompose non-class, non-array type 'svint8_t' (aka '__SVInt8_t')}}
 #endif
 #endif
 
@@ -600,7 +600,7 @@
   auto fn1 = [&local_int8](svint8_t x) { local_int8 = x; };
   auto fn2 = [&local_int8](svint8_t *ptr) { *ptr = local_int8; };
 #if __cplusplus >= 201703L
-  auto fn3 = [a(return_int8())] {}; // expected-error {{field has sizeless type '__SVInt8_t'}}
+  auto fn3 = [a(return_int8())] {}; // expected-error {{field has sizeless type 'svint8_t' (aka '__SVInt8_t')}}
 #endif
   auto fn4 = [local_int8](svint8_t *ptr) { *ptr = local_int8; }; // expected-error {{by-copy capture of variable 'local_int8' with sizeless type 'svint8_t'}}
 
Index: clang/test/SemaCXX/recovery-expr-type.cpp
===================================================================
--- clang/test/SemaCXX/recovery-expr-type.cpp
+++ clang/test/SemaCXX/recovery-expr-type.cpp
@@ -133,7 +133,7 @@
 template <typename T> S(T t) -> S<void *>;
 
 void baz() {
-  bar(S(123)); // expected-error {{no matching conversion for functional-style cast from 'int' to 'test11::S<>'}}
+  bar(S(123)); // expected-error {{no matching conversion for functional-style cast from 'int' to 'S<void *>'}}
 }
 } // namespace test11
 
Index: clang/test/SemaCXX/friend.cpp
===================================================================
--- clang/test/SemaCXX/friend.cpp
+++ clang/test/SemaCXX/friend.cpp
@@ -415,7 +415,7 @@
 
 namespace qualified_friend_no_match {
   void f(int); // expected-note {{type mismatch at 1st parameter}}
-  template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}}
+  template<typename T> void f(T*); // expected-note {{could not match 'T *' against 'double'}}
   struct X {
     friend void qualified_friend_no_match::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend_no_match'}}
     friend void qualified_friend_no_match::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend_no_match'}}
@@ -423,7 +423,7 @@
 
   struct Y {
     void f(int); // expected-note {{type mismatch at 1st parameter}}
-    template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}}
+    template<typename T> void f(T*); // expected-note {{could not match 'T *' against 'double'}}
   };
   struct Z {
     friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend_no_match::Y'}}
Index: clang/test/SemaCXX/deduced-return-type-cxx14.cpp
===================================================================
--- clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -300,7 +300,7 @@
   }
   struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
   // cxx20_2b-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
-  constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}}
+  constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}}
 }
 
 // It's not really clear whether these are valid, but this matches g++.
Index: clang/test/SemaCXX/cxx1z-decomposition.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-decomposition.cpp
+++ clang/test/SemaCXX/cxx1z-decomposition.cpp
@@ -9,7 +9,7 @@
   int a1[1], a2[2];
 
   auto [] = a0; // expected-warning {{does not allow a decomposition group to be empty}}
-  auto [v1] = a0; // expected-error {{type 'A0' decomposes into 0 elements, but 1 name was provided}}
+  auto [v1] = a0; // expected-error {{type 'struct A0' decomposes into 0 elements, but 1 name was provided}}
   auto [] = a1; // expected-error {{type 'int [1]' decomposes into 1 element, but no names were provided}} expected-warning {{empty}}
   auto [v2] = a1;
   auto [v3, v4] = a1; // expected-error {{type 'int [1]' decomposes into 1 element, but 2 names were provided}}
@@ -70,7 +70,7 @@
 void bitfield() {
   struct { int a : 3, : 4, b : 5; } a;
   auto &[x, y] = a;
-  auto &[p, q, r] = a; // expected-error-re {{type '(unnamed struct at {{.*}})' decomposes into 2 elements, but 3 names were provided}}
+  auto &[p, q, r] = a; // expected-error-re {{type 'struct (unnamed struct at {{.*}})' decomposes into 2 elements, but 3 names were provided}}
 }
 
 void for_range() {
Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -555,6 +555,31 @@
 void foo() {
   insert(Foo(2, 2, 2)); // expected-error{{no viable constructor or deduction guide}}
 }
+
+namespace function_prototypes {
+  template<class T> using fptr1 = void (*) (T);
+  template<class T> using fptr2 = fptr1<fptr1<T>>;
+
+  template<class T> void foo1(fptr1<const T *>) {}
+  void bar1(const char * __restrict);
+  void t1() { foo1(&bar1); }
+
+  template<class T> void foo2(fptr2<const T *>) {}
+  void bar2(fptr1<const char * __restrict>);
+  void t2() { foo2(&bar2); }
+
+  template<class T> void foo3(fptr1<const T *>) {}
+  void bar3(char * __restrict);
+  void t3() { foo3(&bar3); }
+  // expected-error@-1 {{no matching function for call to 'foo3'}}
+  // expected-note@-4  {{candidate template ignored: cannot deduce a type for 'T' that would make 'const T' equal 'char'}}
+
+  template<class T> void foo4(fptr2<const T *>) {}
+  void bar4(fptr1<char * __restrict>);
+  void t4() { foo4(&bar4); }
+  // expected-error@-1 {{no matching function for call to 'foo4'}}
+  // expected-note@-4  {{candidate template ignored: cannot deduce a type for 'T' that would make 'const T' equal 'char'}}
+}
 #else
 
 // expected-no-diagnostics
Index: clang/test/Index/print-type.cpp
===================================================================
--- clang/test/Index/print-type.cpp
+++ clang/test/Index/print-type.cpp
@@ -199,7 +199,7 @@
 // CHECK: UnexposedExpr=templRefParam:71:40 [type=const Specialization<Specialization<bool> &>] [typekind=Record] const [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
 // CHECK: DeclRefExpr=templRefParam:71:40 [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
 // CHECK: TypeAliasDecl=baz:76:7 (Definition) [type=baz] [typekind=Typedef] [templateargs/1= [type=A<void>] [typekind=Unexposed]] [canonicaltype=A<void>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=void] [typekind=Void]] [isPOD=0]
-// CHECK: VarDecl=autoTemplPointer:78:6 (Definition) [type=Specialization<Specialization<bool> &> *] [typekind=Auto] [canonicaltype=Specialization<Specialization<bool> &> *] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=Specialization<Specialization<bool> &>] [pointeekind=Record]
+// CHECK: VarDecl=autoTemplPointer:78:6 (Definition) [type=Specialization<Specialization<bool> &> *] [typekind=Auto] [canonicaltype=Specialization<Specialization<bool> &> *] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=Specialization<Specialization<bool> &>] [pointeekind=Auto]
 // CHECK: CallExpr=Bar:17:3 [type=outer::inner::Bar] [typekind=Elaborated] [canonicaltype=outer::inner::Bar] [canonicaltypekind=Record] [args= [outer::Foo<bool> *] [Pointer]] [isPOD=0] [nbFields=3]
 // CHECK: StructDecl=:84:3 (Definition) [type=X::(anonymous struct at {{.*}}print-type.cpp:84:3)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1]
 // CHECK: ClassDecl=:85:3 (Definition) [type=X::(anonymous class at {{.*}}print-type.cpp:85:3)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1]
Index: clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
===================================================================
--- clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
+++ clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp
@@ -53,9 +53,8 @@
 }
 
 
-// FIXME: Use the template parameter names in this diagnostic.
 template<typename ...Args1, typename ...Args2>
-typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<type-parameter-0-0, type-parameter-0-1>' against 'int'}}
+typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<Args1, Args2>' against 'int'}}
 
 template<typename ...Args1, typename ...Args2>
 typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...);
Index: clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
===================================================================
--- clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
+++ clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
@@ -284,7 +284,7 @@
     void g(U &&...u, T &&...t) {} // expected-note {{candidate}}
     template<typename...U>
     void h(tuple<T, U> &&...) {}
-    // expected-note@-1 {{candidate template ignored: could not match 'tuple<type-parameter-0-0, type-parameter-0-0>' against 'int'}}
+    // expected-note@-1 {{candidate template ignored: could not match 'tuple<T, U>' against 'int'}}
     // expected-note@-2 {{candidate template ignored: substitution failure: deduced incomplete pack <(no value)> for template parameter 'U'}}
 
     template<typename...U>
Index: clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
===================================================================
--- clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -321,14 +321,14 @@
 
   namespace NE {
     struct E {
-      void begin(); // expected-note {{member is not a candidate because range type 'p0962r1::NE::E' has no 'end' member}}
+      void begin(); // expected-note {{member is not a candidate because range type 'NE::E' has no 'end' member}}
     };
     int *end(E);
   }
 
   namespace NF {
     struct F {
-      void end(); // expected-note {{member is not a candidate because range type 'p0962r1::NF::F' has no 'begin' member}}
+      void end(); // expected-note {{member is not a candidate because range type 'NF::F' has no 'begin' member}}
     };
     int *begin(F);
   }
@@ -336,9 +336,9 @@
   void use(NA::A a, NB::B b, NC::C c, ND::D d, NE::E e, NF::F f) {
     for (auto x : a) {}
     for (auto x : b) {}
-    for (auto x : c) {} // expected-error {{invalid range expression of type 'p0962r1::NC::C'; no viable 'end' function available}}
-    for (auto x : d) {} // expected-error {{invalid range expression of type 'p0962r1::ND::D'; no viable 'begin' function available}}
-    for (auto x : e) {} // expected-error {{invalid range expression of type 'p0962r1::NE::E'; no viable 'begin' function available}}
-    for (auto x : f) {} // expected-error {{invalid range expression of type 'p0962r1::NF::F'; no viable 'end' function available}}
+    for (auto x : c) {} // expected-error {{invalid range expression of type 'NC::C'; no viable 'end' function available}}
+    for (auto x : d) {} // expected-error {{invalid range expression of type 'ND::D'; no viable 'begin' function available}}
+    for (auto x : e) {} // expected-error {{invalid range expression of type 'NE::E'; no viable 'begin' function available}}
+    for (auto x : f) {} // expected-error {{invalid range expression of type 'NF::F'; no viable 'end' function available}}
   }
 }
Index: clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
===================================================================
--- clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
+++ clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
@@ -36,7 +36,7 @@
 
 namespace p0702r1 {
   template<typename T> struct X { // expected-note {{candidate}}
-    X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'initializer_list<type-parameter-0-0>' against 'p0702r1::Z'}}
+    X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'initializer_list<T>' against 'p0702r1::Z'}}
   };
 
   X xi = {0};
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -6561,7 +6561,7 @@
       T->isDependentType() || T->isConstrained()) {
     // FIXME: Maybe don't rebuild if all template arguments are the same.
     llvm::SmallVector<TemplateArgument, 4> NewArgList;
-    NewArgList.reserve(NewArgList.size());
+    NewArgList.reserve(NewTemplateArgs.size());
     for (const auto &ArgLoc : NewTemplateArgs.arguments())
       NewArgList.push_back(ArgLoc.getArgument());
     Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword(), NewCD,
@@ -14446,10 +14446,10 @@
   return SemaRef.Context.getTypeDeclType(Ty);
 }
 
-template<typename Derived>
+template <typename Derived>
 QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E,
-                                                       SourceLocation Loc) {
-  return SemaRef.BuildTypeofExprType(E, Loc);
+                                                       SourceLocation) {
+  return SemaRef.BuildTypeofExprType(E);
 }
 
 template<typename Derived>
@@ -14457,10 +14457,9 @@
   return SemaRef.Context.getTypeOfType(Underlying);
 }
 
-template<typename Derived>
-QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
-                                                     SourceLocation Loc) {
-  return SemaRef.BuildDecltypeType(E, Loc);
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E, SourceLocation) {
+  return SemaRef.BuildDecltypeType(E);
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1622,7 +1622,7 @@
     Expr *E = DS.getRepAsExpr();
     assert(E && "Didn't get an expression for typeof?");
     // TypeQuals handled by caller.
-    Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
+    Result = S.BuildTypeofExprType(E);
     if (Result.isNull()) {
       Result = Context.IntTy;
       declarator.setInvalidType(true);
@@ -1633,7 +1633,7 @@
     Expr *E = DS.getRepAsExpr();
     assert(E && "Didn't get an expression for decltype?");
     // TypeQuals handled by caller.
-    Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
+    Result = S.BuildDecltypeType(E);
     if (Result.isNull()) {
       Result = Context.IntTy;
       declarator.setInvalidType(true);
@@ -8893,7 +8893,7 @@
   return Context.getElaboratedType(Keyword, NNS, T, OwnedTagDecl);
 }
 
-QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
+QualType Sema::BuildTypeofExprType(Expr *E) {
   assert(!E->hasPlaceholderType() && "unexpected placeholder");
 
   if (!getLangOpts().CPlusPlus && E->refersToBitField())
@@ -8910,9 +8910,9 @@
 /// getDecltypeForExpr - Given an expr, will return the decltype for
 /// that expression, according to the rules in C++11
 /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
-static QualType getDecltypeForExpr(Sema &S, Expr *E) {
+QualType Sema::getDecltypeForExpr(Expr *E) {
   if (E->isTypeDependent())
-    return S.Context.DependentTy;
+    return Context.DependentTy;
 
   Expr *IDExpr = E;
   if (auto *ImplCastExpr = dyn_cast<ImplicitCastExpr>(E))
@@ -8929,7 +8929,7 @@
   // parameter object. This rule makes no difference before C++20 so we apply
   // it unconditionally.
   if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(IDExpr))
-    return SNTTPE->getParameterType(S.Context);
+    return SNTTPE->getParameterType(Context);
 
   //     - if e is an unparenthesized id-expression or an unparenthesized class
   //       member access (5.2.5), decltype(e) is the type of the entity named
@@ -8937,22 +8937,20 @@
   //       functions, the program is ill-formed;
   //
   // We apply the same rules for Objective-C ivar and property references.
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
+  if (const auto *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
     const ValueDecl *VD = DRE->getDecl();
-    if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD))
-      return TPO->getType().getUnqualifiedType();
-    return VD->getType();
-  } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(IDExpr)) {
-    if (const ValueDecl *VD = ME->getMemberDecl())
+    QualType T = VD->getType();
+    return isa<TemplateParamObjectDecl>(VD) ? T.getUnqualifiedType() : T;
+  } else if (const auto *ME = dyn_cast<MemberExpr>(IDExpr)) {
+    if (const auto *VD = ME->getMemberDecl())
       if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
         return VD->getType();
-  } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
+  } else if (const auto *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
     return IR->getDecl()->getType();
-  } else if (const ObjCPropertyRefExpr *PR =
-                 dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
+  } else if (const auto *PR = dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
     if (PR->isExplicitProperty())
       return PR->getExplicitProperty()->getType();
-  } else if (auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
+  } else if (const auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
     return PE->getType();
   }
 
@@ -8963,24 +8961,20 @@
   //   access to a corresponding data member of the closure type that
   //   would have been declared if x were an odr-use of the denoted
   //   entity.
-  using namespace sema;
-  if (S.getCurLambda()) {
-    if (isa<ParenExpr>(IDExpr)) {
-      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
-        if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
-          QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
-          if (!T.isNull())
-            return S.Context.getLValueReferenceType(T);
-        }
+  if (getCurLambda() && isa<ParenExpr>(IDExpr)) {
+    if (auto *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
+      if (auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+        QualType T = getCapturedDeclRefType(Var, DRE->getLocation());
+        if (!T.isNull())
+          return Context.getLValueReferenceType(T);
       }
     }
   }
 
-  return S.Context.getReferenceQualifiedType(E);
+  return Context.getReferenceQualifiedType(E);
 }
 
-QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
-                                 bool AsUnevaluated) {
+QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
   assert(!E->hasPlaceholderType() && "unexpected placeholder");
 
   if (AsUnevaluated && CodeSynthesisContexts.empty() &&
@@ -8991,8 +8985,7 @@
     // used to build SFINAE gadgets.
     Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
   }
-
-  return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
+  return Context.getDecltypeType(E, getDecltypeForExpr(E));
 }
 
 QualType Sema::BuildUnaryTransformType(QualType BaseType,
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -139,17 +139,11 @@
                         TemplateDeductionInfo &Info,
                         SmallVectorImpl<DeducedTemplateArgument> &Deduced);
 
-static Sema::TemplateDeductionResult
-DeduceTemplateArgumentsByTypeMatch(Sema &S,
-                                   TemplateParameterList *TemplateParams,
-                                   QualType Param,
-                                   QualType Arg,
-                                   TemplateDeductionInfo &Info,
-                                   SmallVectorImpl<DeducedTemplateArgument> &
-                                                      Deduced,
-                                   unsigned TDF,
-                                   bool PartialOrdering = false,
-                                   bool DeducedFromArrayBound = false);
+static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
+    Sema &S, TemplateParameterList *TemplateParams, QualType Param,
+    QualType Arg, TemplateDeductionInfo &Info,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF,
+    bool PartialOrdering = false, bool DeducedFromArrayBound = false);
 
 static Sema::TemplateDeductionResult
 DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
@@ -565,15 +559,20 @@
                         QualType Arg,
                         TemplateDeductionInfo &Info,
                         SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
-  assert(Arg.isCanonical() && "Argument type must be canonical");
+  QualType ArgDesug;
+  auto updateArg = [&Arg, &ArgDesug, &S](QualType T) {
+    Arg = T;
+    ArgDesug = T.getDesugaredType(S.Context);
+  };
+  updateArg(Arg);
 
   // Treat an injected-class-name as its underlying template-id.
-  if (auto *Injected = dyn_cast<InjectedClassNameType>(Arg))
-    Arg = Injected->getInjectedSpecializationType();
+  if (auto *Injected = dyn_cast<InjectedClassNameType>(ArgDesug))
+    updateArg(Injected->getInjectedSpecializationType());
 
   // Check whether the template argument is a dependent template-id.
-  if (const TemplateSpecializationType *SpecArg
-        = dyn_cast<TemplateSpecializationType>(Arg)) {
+  if (const TemplateSpecializationType *SpecArg =
+          dyn_cast<TemplateSpecializationType>(ArgDesug)) {
     // Perform template argument deduction for the template name.
     if (Sema::TemplateDeductionResult Result
           = DeduceTemplateArguments(S, TemplateParams,
@@ -595,7 +594,7 @@
   // If the argument type is a class template specialization, we
   // perform template argument deduction using its template
   // arguments.
-  const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
+  const RecordType *RecordArg = dyn_cast<RecordType>(ArgDesug);
   if (!RecordArg) {
     Info.FirstArg = TemplateArgument(QualType(Param, 0));
     Info.SecondArg = TemplateArgument(Arg);
@@ -1047,11 +1046,12 @@
         return Sema::TDK_MiscellaneousDeductionFailure;
       }
 
-      if (Sema::TemplateDeductionResult Result
-            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                                                 Params[ParamIdx], Args[ArgIdx],
-                                                 Info, Deduced, TDF,
-                                                 PartialOrdering))
+      if (Sema::TemplateDeductionResult Result =
+              DeduceTemplateArgumentsByTypeMatch(
+                  S, TemplateParams, Params[ParamIdx].getUnqualifiedType(),
+                  Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF,
+                  PartialOrdering,
+                  /*DeducedFromArrayBound=*/false))
         return Result;
 
       ++ArgIdx;
@@ -1073,10 +1073,11 @@
     if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity()) {
       for (; ArgIdx < NumArgs && PackScope.hasNextElement(); ++ArgIdx) {
         // Deduce template arguments from the pattern.
-        if (Sema::TemplateDeductionResult Result
-              = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
-                                                   Args[ArgIdx], Info, Deduced,
-                                                   TDF, PartialOrdering))
+        if (Sema::TemplateDeductionResult Result =
+                DeduceTemplateArgumentsByTypeMatch(
+                    S, TemplateParams, Pattern.getUnqualifiedType(),
+                    Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF,
+                    PartialOrdering, /*DeducedFromArrayBound=*/false))
           return Result;
 
         PackScope.nextPackElement();
@@ -1341,25 +1342,24 @@
 /// \returns the result of template argument deduction so far. Note that a
 /// "success" result means that template argument deduction has not yet failed,
 /// but it may still fail, later, for other reasons.
-static Sema::TemplateDeductionResult
-DeduceTemplateArgumentsByTypeMatch(Sema &S,
-                                   TemplateParameterList *TemplateParams,
-                                   QualType ParamIn, QualType ArgIn,
-                                   TemplateDeductionInfo &Info,
-                            SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                                   unsigned TDF,
-                                   bool PartialOrdering,
-                                   bool DeducedFromArrayBound) {
-  // We only want to look at the canonical types, since typedefs and
-  // sugar are not part of template argument deduction.
-  QualType Param = S.Context.getCanonicalType(ParamIn);
-  QualType Arg = S.Context.getCanonicalType(ArgIn);
-
-  // If the argument type is a pack expansion, look at its pattern.
-  // This isn't explicitly called out
-  if (const PackExpansionType *ArgExpansion
-                                            = dyn_cast<PackExpansionType>(Arg))
-    Arg = ArgExpansion->getPattern();
+static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
+    Sema &S, TemplateParameterList *TemplateParams, QualType Param,
+    QualType Arg, TemplateDeductionInfo &Info,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF,
+    bool PartialOrdering, bool DeducedFromArrayBound) {
+  QualType ParDesug;
+  auto updatePar = [&Param, &ParDesug, &S](QualType T) {
+    Param = T;
+    ParDesug = T.getDesugaredType(S.Context);
+  };
+  updatePar(Param);
+
+  QualType ArgDesug;
+  auto updateArg = [&Arg, &ArgDesug, &S](QualType T) {
+    Arg = T;
+    ArgDesug = T.getDesugaredType(S.Context);
+  };
+  updateArg(Arg);
 
   if (PartialOrdering) {
     // C++11 [temp.deduct.partial]p5:
@@ -1368,12 +1368,12 @@
     //     - If P is a reference type, P is replaced by the type referred to.
     const ReferenceType *ParamRef = Param->getAs<ReferenceType>();
     if (ParamRef)
-      Param = ParamRef->getPointeeType();
+      updatePar(ParamRef->getPointeeType());
 
     //     - If A is a reference type, A is replaced by the type referred to.
-    const ReferenceType *ArgRef = Arg->getAs<ReferenceType>();
+    const ReferenceType *ArgRef = ArgDesug->getAs<ReferenceType>();
     if (ArgRef)
-      Arg = ArgRef->getPointeeType();
+      updateArg(ArgRef->getPointeeType());
 
     if (ParamRef && ArgRef && S.Context.hasSameUnqualifiedType(Param, Arg)) {
       // C++11 [temp.deduct.partial]p9:
@@ -1404,8 +1404,8 @@
            ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
            ParamQuals.withoutObjCLifetime() ==
                ArgQuals.withoutObjCLifetime())) {
-        Info.FirstArg = TemplateArgument(ParamIn);
-        Info.SecondArg = TemplateArgument(ArgIn);
+        Info.FirstArg = TemplateArgument(Param);
+        Info.SecondArg = TemplateArgument(Arg);
         return Sema::TDK_NonDeducedMismatch;
       }
     }
@@ -1414,10 +1414,10 @@
     //   Remove any top-level cv-qualifiers:
     //     - If P is a cv-qualified type, P is replaced by the cv-unqualified
     //       version of P.
-    Param = Param.getUnqualifiedType();
+    updatePar(Param.getUnqualifiedType());
     //     - If A is a cv-qualified type, A is replaced by the cv-unqualified
     //       version of A.
-    Arg = Arg.getUnqualifiedType();
+    updateArg(Arg.getUnqualifiedType());
   } else {
     // C++0x [temp.deduct.call]p4 bullet 1:
     //   - If the original P is a reference type, the deduced A (i.e., the type
@@ -1427,8 +1427,8 @@
       Qualifiers Quals;
       QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
       Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
-                             Arg.getCVRQualifiers());
-      Param = S.Context.getQualifiedType(UnqualParam, Quals);
+                             ArgDesug.getCVRQualifiers());
+      updatePar(S.Context.getQualifiedType(UnqualParam, Quals));
     }
 
     if ((TDF & TDF_TopLevelParameterTypeList) && !Param->isFunctionType()) {
@@ -1444,8 +1444,8 @@
       //   Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be
       //   deduced as X&. - end note ]
       TDF &= ~TDF_TopLevelParameterTypeList;
-      if (isForwardingReference(Param, 0) && Arg->isLValueReferenceType())
-        Param = Param->getPointeeType();
+      if (isForwardingReference(Param, 0) && ArgDesug->isLValueReferenceType())
+        updatePar(Param->getPointeeType());
     }
   }
 
@@ -1456,32 +1456,29 @@
   //
   //     T
   //     cv-list T
-  if (const TemplateTypeParmType *TemplateTypeParm
-        = Param->getAs<TemplateTypeParmType>()) {
+  if (const TemplateTypeParmType *TemplateTypeParm =
+          ParDesug->getAs<TemplateTypeParmType>()) {
     // Just skip any attempts to deduce from a placeholder type or a parameter
     // at a different depth.
-    if (Arg->isPlaceholderType() ||
+    if (ArgDesug->isPlaceholderType() ||
         Info.getDeducedDepth() != TemplateTypeParm->getDepth())
       return Sema::TDK_Success;
 
     unsigned Index = TemplateTypeParm->getIndex();
-    bool RecanonicalizeArg = false;
 
     // If the argument type is an array type, move the qualifiers up to the
     // top level, so they can be matched with the qualifiers on the parameter.
-    if (isa<ArrayType>(Arg)) {
+    if (isa<ArrayType>(ArgDesug)) {
       Qualifiers Quals;
-      Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
-      if (Quals) {
-        Arg = S.Context.getQualifiedType(Arg, Quals);
-        RecanonicalizeArg = true;
-      }
+      updateArg(S.Context.getUnqualifiedArrayType(ArgDesug, Quals));
+      if (Quals)
+        updateArg(S.Context.getQualifiedType(ArgDesug, Quals));
     }
 
     // The argument type can not be less qualified than the parameter
     // type.
     if (!(TDF & TDF_IgnoreQualifiers) &&
-        hasInconsistentOrSupersetQualifiersOf(Param, Arg)) {
+        hasInconsistentOrSupersetQualifiersOf(Param, ArgDesug)) {
       Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
       Info.FirstArg = TemplateArgument(Param);
       Info.SecondArg = TemplateArgument(Arg);
@@ -1496,7 +1493,8 @@
 
     assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
            "saw template type parameter with wrong depth");
-    assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
+    assert(ArgDesug != S.Context.OverloadTy &&
+           "Unresolved overloaded function");
     QualType DeducedType = Arg;
 
     // Remove any qualifiers on the parameter from the deduced type.
@@ -1530,11 +1528,8 @@
         !DeducedQs.hasObjCLifetime())
       DeducedQs.setObjCLifetime(Qualifiers::OCL_Strong);
 
-    DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(),
-                                             DeducedQs);
-
-    if (RecanonicalizeArg)
-      DeducedType = S.Context.getCanonicalType(DeducedType);
+    DeducedType =
+        S.Context.getQualifiedType(DeducedType.getUnqualifiedType(), DeducedQs);
 
     DeducedTemplateArgument NewDeduced(DeducedType, DeducedFromArrayBound);
     DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
@@ -1552,14 +1547,14 @@
   }
 
   // Set up the template argument deduction information for a failure.
-  Info.FirstArg = TemplateArgument(ParamIn);
-  Info.SecondArg = TemplateArgument(ArgIn);
+  Info.FirstArg = TemplateArgument(Param);
+  Info.SecondArg = TemplateArgument(Arg);
 
   // If the parameter is an already-substituted template parameter
   // pack, do nothing: we don't know which of its arguments to look
   // at, so we have to wait until all of the parameter packs in this
   // expansion have arguments.
-  if (isa<SubstTemplateTypeParmPackType>(Param))
+  if (isa<SubstTemplateTypeParmPackType>(ParDesug))
     return Sema::TDK_Success;
 
   // Check the cv-qualifiers on the parameter and argument types.
@@ -1573,16 +1568,16 @@
       // C++ [temp.deduct.conv]p4:
       //   If the original A is a reference type, A can be more cv-qualified
       //   than the deduced A
-      if (!Arg.getQualifiers().compatiblyIncludes(Param.getQualifiers()))
+      if (!ArgDesug.getQualifiers().compatiblyIncludes(Param.getQualifiers()))
         return Sema::TDK_NonDeducedMismatch;
 
       // Strip out all extra qualifiers from the argument to figure out the
       // type we're converting to, prior to the qualification conversion.
       Qualifiers Quals;
-      Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
-      Arg = S.Context.getQualifiedType(Arg, Param.getQualifiers());
+      updateArg(S.Context.getUnqualifiedArrayType(ArgDesug, Quals));
+      updateArg(S.Context.getQualifiedType(ArgDesug, Param.getQualifiers()));
     } else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
-      if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
+      if (ParDesug.getCVRQualifiers() != ArgDesug.getCVRQualifiers())
         return Sema::TDK_NonDeducedMismatch;
     }
 
@@ -1592,7 +1587,7 @@
         bool NonDeduced =
             (TDF & TDF_AllowCompatibleFunctionType)
                 ? !S.isSameOrCompatibleFunctionType(CanParam, CanArg)
-                : Param != Arg;
+                : CanParam != CanArg;
         if (NonDeduced) {
           return Sema::TDK_NonDeducedMismatch;
         }
@@ -1614,7 +1609,7 @@
     }
   }
 
-  switch (Param->getTypeClass()) {
+  switch (ParDesug->getTypeClass()) {
     // Non-canonical types cannot appear here.
 #define NON_CANONICAL_TYPE(Class, Base) \
   case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
@@ -1641,99 +1636,98 @@
         return Sema::TDK_Success;
 
       if (TDF & TDF_IgnoreQualifiers) {
-        Param = Param.getUnqualifiedType();
-        Arg = Arg.getUnqualifiedType();
+        ParDesug = ParDesug.getUnqualifiedType();
+        ArgDesug = ArgDesug.getUnqualifiedType();
       }
 
-      return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
+      return ParDesug == ArgDesug ? Sema::TDK_Success
+                                  : Sema::TDK_NonDeducedMismatch;
 
     //     _Complex T   [placeholder extension]
     case Type::Complex:
-      if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
-        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                                    cast<ComplexType>(Param)->getElementType(),
-                                    ComplexArg->getElementType(),
-                                    Info, Deduced, TDF);
+      if (const ComplexType *ComplexArg = ArgDesug->getAs<ComplexType>())
+        return DeduceTemplateArgumentsByTypeMatch(
+            S, TemplateParams, cast<ComplexType>(ParDesug)->getElementType(),
+            ComplexArg->getElementType(), Info, Deduced, TDF);
 
       return Sema::TDK_NonDeducedMismatch;
 
     //     _Atomic T   [extension]
     case Type::Atomic:
-      if (const AtomicType *AtomicArg = Arg->getAs<AtomicType>())
-        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                                       cast<AtomicType>(Param)->getValueType(),
-                                       AtomicArg->getValueType(),
-                                       Info, Deduced, TDF);
+      if (const AtomicType *AtomicArg = ArgDesug->getAs<AtomicType>())
+        return DeduceTemplateArgumentsByTypeMatch(
+            S, TemplateParams, cast<AtomicType>(ParDesug)->getValueType(),
+            AtomicArg->getValueType(), Info, Deduced, TDF);
 
       return Sema::TDK_NonDeducedMismatch;
 
     //     T *
     case Type::Pointer: {
       QualType PointeeType;
-      if (const PointerType *PointerArg = Arg->getAs<PointerType>()) {
+      if (const PointerType *PointerArg = ArgDesug->getAs<PointerType>()) {
         PointeeType = PointerArg->getPointeeType();
-      } else if (const ObjCObjectPointerType *PointerArg
-                   = Arg->getAs<ObjCObjectPointerType>()) {
+      } else if (const ObjCObjectPointerType *PointerArg =
+                     ArgDesug->getAs<ObjCObjectPointerType>()) {
         PointeeType = PointerArg->getPointeeType();
       } else {
         return Sema::TDK_NonDeducedMismatch;
       }
 
       unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
-      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                                     cast<PointerType>(Param)->getPointeeType(),
-                                     PointeeType,
-                                     Info, Deduced, SubTDF);
+      return DeduceTemplateArgumentsByTypeMatch(
+          S, TemplateParams, cast<PointerType>(ParDesug)->getPointeeType(),
+          PointeeType, Info, Deduced, SubTDF);
     }
 
     //     T &
     case Type::LValueReference: {
       const LValueReferenceType *ReferenceArg =
-          Arg->getAs<LValueReferenceType>();
+          ArgDesug->getAs<LValueReferenceType>();
       if (!ReferenceArg)
         return Sema::TDK_NonDeducedMismatch;
 
-      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                           cast<LValueReferenceType>(Param)->getPointeeType(),
-                           ReferenceArg->getPointeeType(), Info, Deduced, 0);
+      return DeduceTemplateArgumentsByTypeMatch(
+          S, TemplateParams,
+          cast<LValueReferenceType>(ParDesug)->getPointeeType(),
+          ReferenceArg->getPointeeType(), Info, Deduced, 0);
     }
 
     //     T && [C++0x]
     case Type::RValueReference: {
       const RValueReferenceType *ReferenceArg =
-          Arg->getAs<RValueReferenceType>();
+          ArgDesug->getAs<RValueReferenceType>();
       if (!ReferenceArg)
         return Sema::TDK_NonDeducedMismatch;
 
-      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                             cast<RValueReferenceType>(Param)->getPointeeType(),
-                             ReferenceArg->getPointeeType(),
-                             Info, Deduced, 0);
+      return DeduceTemplateArgumentsByTypeMatch(
+          S, TemplateParams,
+          cast<RValueReferenceType>(ParDesug)->getPointeeType(),
+          ReferenceArg->getPointeeType(), Info, Deduced, 0);
     }
 
     //     T [] (implied, but not stated explicitly)
     case Type::IncompleteArray: {
       const IncompleteArrayType *IncompleteArrayArg =
-        S.Context.getAsIncompleteArrayType(Arg);
+          S.Context.getAsIncompleteArrayType(ArgDesug);
       if (!IncompleteArrayArg)
         return Sema::TDK_NonDeducedMismatch;
 
       unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
-      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
-                    S.Context.getAsIncompleteArrayType(Param)->getElementType(),
-                    IncompleteArrayArg->getElementType(),
-                    Info, Deduced, SubTDF);
+      return DeduceTemplateArgumentsByTypeMatch(
+          S, TemplateParams,
+          S.Context.getAsIncompleteArrayType(ParDesug)->getElementType(),
+          IncompleteArrayArg->getElementType(), Info, Deduced, SubTDF);
     }
 
     //     T [integer-constant]
     case Type::ConstantArray: {
       const ConstantArrayType *ConstantArrayArg =
-        S.Context.getAsConstantArrayType(Arg);
+          S.Context.getAsConstantArrayType(ArgDesug);
       if (!ConstantArrayArg)
         return Sema::TDK_NonDeducedMismatch;
 
       const ConstantArrayType *ConstantArrayParm =
-        S.Context.getAsConstantArrayType(Param);
+          S.Context.getAsConstantArrayType(ParDesug);
       if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
         return Sema::TDK_NonDeducedMismatch;
 
@@ -1746,15 +1740,15 @@
 
     //     type [i]
     case Type::DependentSizedArray: {
-      const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
+      const ArrayType *ArrayArg = S.Context.getAsArrayType(ArgDesug);
       if (!ArrayArg)
         return Sema::TDK_NonDeducedMismatch;
 
       unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
 
       // Check the element type of the arrays
-      const DependentSizedArrayType *DependentArrayParm
-        = S.Context.getAsDependentSizedArrayType(Param);
+      const DependentSizedArrayType *DependentArrayParm =
+          S.Context.getAsDependentSizedArrayType(ParDesug);
       if (Sema::TemplateDeductionResult Result
             = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
                                           DependentArrayParm->getElementType(),
@@ -1797,12 +1791,12 @@
     case Type::FunctionProto: {
       unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList;
       const FunctionProtoType *FunctionProtoArg =
-        dyn_cast<FunctionProtoType>(Arg);
+          dyn_cast<FunctionProtoType>(ArgDesug);
       if (!FunctionProtoArg)
         return Sema::TDK_NonDeducedMismatch;
 
       const FunctionProtoType *FunctionProtoParam =
-        cast<FunctionProtoType>(Param);
+          cast<FunctionProtoType>(ParDesug);
 
       if (FunctionProtoParam->getMethodQuals()
             != FunctionProtoArg->getMethodQuals() ||
@@ -1813,8 +1807,12 @@
 
       // Check return types.
       if (auto Result = DeduceTemplateArgumentsByTypeMatch(
-              S, TemplateParams, FunctionProtoParam->getReturnType(),
-              FunctionProtoArg->getReturnType(), Info, Deduced, 0))
+              S, TemplateParams,
+              FunctionProtoParam->getReturnType().getUnqualifiedType(),
+              FunctionProtoArg->getReturnType().getUnqualifiedType(), Info,
+              Deduced, 0,
+              /*PartialOrdering=*/false,
+              /*DeducedFromArrayBound=*/false))
         return Result;
 
       // Check parameter types.
@@ -1870,9 +1868,9 @@
     case Type::InjectedClassName:
       // Treat a template's injected-class-name as if the template
       // specialization type had been used.
-      Param = cast<InjectedClassNameType>(Param)
-        ->getInjectedSpecializationType();
-      assert(isa<TemplateSpecializationType>(Param) &&
+      updatePar(cast<InjectedClassNameType>(ParDesug)
+                    ->getInjectedSpecializationType());
+      assert(isa<TemplateSpecializationType>(ParDesug) &&
              "injected class name is not a template specialization type");
       LLVM_FALLTHROUGH;
 
@@ -1883,11 +1881,11 @@
     //     TT<>
     case Type::TemplateSpecialization: {
       const TemplateSpecializationType *SpecParam =
-          cast<TemplateSpecializationType>(Param);
+          cast<TemplateSpecializationType>(ParDesug);
 
       // When Arg cannot be a derived class, we can just try to deduce template
       // arguments from the template-id.
-      const RecordType *RecordT = Arg->getAs<RecordType>();
+      const RecordType *RecordT = ArgDesug->getAs<RecordType>();
       if (!(TDF & TDF_DerivedClass) || !RecordT)
         return DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg, Info,
                                        Deduced);
@@ -1929,8 +1927,9 @@
     //     T (T::*)()
     //     T (T::*)(T)
     case Type::MemberPointer: {
-      const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
-      const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
+      const MemberPointerType *MemPtrParam = cast<MemberPointerType>(ParDesug);
+      const MemberPointerType *MemPtrArg =
+          dyn_cast<MemberPointerType>(ArgDesug);
       if (!MemPtrArg)
         return Sema::TDK_NonDeducedMismatch;
 
@@ -1964,8 +1963,9 @@
     //     T(^)()
     //     T(^)(T)
     case Type::BlockPointer: {
-      const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
-      const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
+      const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(ParDesug);
+      const BlockPointerType *BlockPtrArg =
+          dyn_cast<BlockPointerType>(ArgDesug);
 
       if (!BlockPtrArg)
         return Sema::TDK_NonDeducedMismatch;
@@ -1980,8 +1980,8 @@
     //
     //     T __attribute__(((ext_vector_type(<integral constant>))))
     case Type::ExtVector: {
-      const ExtVectorType *VectorParam = cast<ExtVectorType>(Param);
-      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+      const ExtVectorType *VectorParam = cast<ExtVectorType>(ParDesug);
+      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(ArgDesug)) {
         // Make sure that the vectors have the same number of elements.
         if (VectorParam->getNumElements() != VectorArg->getNumElements())
           return Sema::TDK_NonDeducedMismatch;
@@ -1993,8 +1993,8 @@
                                                   Info, Deduced, TDF);
       }
 
-      if (const DependentSizedExtVectorType *VectorArg
-                                = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+      if (const DependentSizedExtVectorType *VectorArg =
+              dyn_cast<DependentSizedExtVectorType>(ArgDesug)) {
         // We can't check the number of elements, since the argument has a
         // dependent number of elements. This can only occur during partial
         // ordering.
@@ -2010,9 +2010,9 @@
     }
 
     case Type::DependentVector: {
-      const auto *VectorParam = cast<DependentVectorType>(Param);
+      const auto *VectorParam = cast<DependentVectorType>(ParDesug);
 
-      if (const auto *VectorArg = dyn_cast<VectorType>(Arg)) {
+      if (const auto *VectorArg = dyn_cast<VectorType>(ArgDesug)) {
         // Perform deduction on the element types.
         if (Sema::TemplateDeductionResult Result =
                 DeduceTemplateArgumentsByTypeMatch(
@@ -2036,7 +2036,7 @@
                                              Info, Deduced);
       }
 
-      if (const auto *VectorArg = dyn_cast<DependentVectorType>(Arg)) {
+      if (const auto *VectorArg = dyn_cast<DependentVectorType>(ArgDesug)) {
         // Perform deduction on the element types.
         if (Sema::TemplateDeductionResult Result =
                 DeduceTemplateArgumentsByTypeMatch(
@@ -2061,10 +2061,10 @@
     //
     //     T __attribute__(((ext_vector_type(N))))
     case Type::DependentSizedExtVector: {
-      const DependentSizedExtVectorType *VectorParam
-        = cast<DependentSizedExtVectorType>(Param);
+      const DependentSizedExtVectorType *VectorParam =
+          cast<DependentSizedExtVectorType>(ParDesug);
 
-      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(ArgDesug)) {
         // Perform deduction on the element types.
         if (Sema::TemplateDeductionResult Result
               = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
@@ -2089,8 +2089,8 @@
                                              Deduced);
       }
 
-      if (const DependentSizedExtVectorType *VectorArg
-                                = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+      if (const DependentSizedExtVectorType *VectorArg =
+              dyn_cast<DependentSizedExtVectorType>(ArgDesug)) {
         // Perform deduction on the element types.
         if (Sema::TemplateDeductionResult Result
             = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
@@ -2118,11 +2118,13 @@
     //     T __attribute__((matrix_type(<integral constant>,
     //                                  <integral constant>)))
     case Type::ConstantMatrix: {
-      const ConstantMatrixType *MatrixArg = dyn_cast<ConstantMatrixType>(Arg);
+      const ConstantMatrixType *MatrixArg =
+          dyn_cast<ConstantMatrixType>(ArgDesug);
       if (!MatrixArg)
         return Sema::TDK_NonDeducedMismatch;
 
-      const ConstantMatrixType *MatrixParam = cast<ConstantMatrixType>(Param);
+      const ConstantMatrixType *MatrixParam =
+          cast<ConstantMatrixType>(ParDesug);
       // Check that the dimensions are the same
       if (MatrixParam->getNumRows() != MatrixArg->getNumRows() ||
           MatrixParam->getNumColumns() != MatrixArg->getNumColumns()) {
@@ -2135,13 +2137,13 @@
     }
 
     case Type::DependentSizedMatrix: {
-      const MatrixType *MatrixArg = dyn_cast<MatrixType>(Arg);
+      const MatrixType *MatrixArg = dyn_cast<MatrixType>(ArgDesug);
       if (!MatrixArg)
         return Sema::TDK_NonDeducedMismatch;
 
       // Check the element type of the matrixes.
       const DependentSizedMatrixType *MatrixParam =
-          cast<DependentSizedMatrixType>(Param);
+          cast<DependentSizedMatrixType>(ParDesug);
       if (Sema::TemplateDeductionResult Result =
               DeduceTemplateArgumentsByTypeMatch(
                   S, TemplateParams, MatrixParam->getElementType(),
@@ -2212,10 +2214,10 @@
     //     T __attribute__(((address_space(N))))
     case Type::DependentAddressSpace: {
       const DependentAddressSpaceType *AddressSpaceParam =
-          cast<DependentAddressSpaceType>(Param);
+          cast<DependentAddressSpaceType>(ParDesug);
 
       if (const DependentAddressSpaceType *AddressSpaceArg =
-              dyn_cast<DependentAddressSpaceType>(Arg)) {
+              dyn_cast<DependentAddressSpaceType>(ArgDesug)) {
         // Perform deduction on the pointer type.
         if (Sema::TemplateDeductionResult Result =
                 DeduceTemplateArgumentsByTypeMatch(
@@ -2234,16 +2236,17 @@
             Deduced);
       }
 
-      if (isTargetAddressSpace(Arg.getAddressSpace())) {
+      if (isTargetAddressSpace(ArgDesug.getAddressSpace())) {
         llvm::APSInt ArgAddressSpace(S.Context.getTypeSize(S.Context.IntTy),
                                      false);
-        ArgAddressSpace = toTargetAddressSpace(Arg.getAddressSpace());
+        ArgAddressSpace = toTargetAddressSpace(ArgDesug.getAddressSpace());
 
         // Perform deduction on the pointer types.
         if (Sema::TemplateDeductionResult Result =
                 DeduceTemplateArgumentsByTypeMatch(
                     S, TemplateParams, AddressSpaceParam->getPointeeType(),
-                    S.Context.removeAddrSpaceQualType(Arg), Info, Deduced, TDF))
+                    S.Context.removeAddrSpaceQualType(ArgDesug), Info, Deduced,
+                    TDF))
           return Result;
 
         // Perform deduction on the address space, if we can.
@@ -2260,9 +2263,9 @@
       return Sema::TDK_NonDeducedMismatch;
     }
     case Type::DependentExtInt: {
-      const auto *IntParam = cast<DependentExtIntType>(Param);
+      const auto *IntParam = cast<DependentExtIntType>(ParDesug);
 
-      if (const auto *IntArg = dyn_cast<ExtIntType>(Arg)){
+      if (const auto *IntArg = dyn_cast<ExtIntType>(ArgDesug)) {
         if (IntParam->isUnsigned() != IntArg->isUnsigned())
           return Sema::TDK_NonDeducedMismatch;
 
@@ -2279,7 +2282,7 @@
                                              Deduced);
       }
 
-      if (const auto *IntArg = dyn_cast<DependentExtIntType>(Arg)) {
+      if (const auto *IntArg = dyn_cast<DependentExtIntType>(ArgDesug)) {
         if (IntParam->isUnsigned() != IntArg->isUnsigned())
           return Sema::TDK_NonDeducedMismatch;
         return Sema::TDK_Success;
@@ -2300,7 +2303,7 @@
     case Type::Pipe:
       // No template argument deduction for these types
       return Sema::TDK_Success;
-  }
+    }
 
   llvm_unreachable("Invalid Type Class!");
 }
@@ -2366,43 +2369,40 @@
     if (Arg.getKind() == TemplateArgument::Integral) {
       if (hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
         return Sema::TDK_Success;
-
-      Info.FirstArg = Param;
-      Info.SecondArg = Arg;
-      return Sema::TDK_NonDeducedMismatch;
-    }
-
-    if (Arg.getKind() == TemplateArgument::Expression) {
-      Info.FirstArg = Param;
-      Info.SecondArg = Arg;
-      return Sema::TDK_NonDeducedMismatch;
     }
-
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
 
-  case TemplateArgument::Expression:
+  case TemplateArgument::Expression: {
+    auto *E = Param.getAsExpr();
+    if (!E->isValueDependent()) {
+      if (const auto Int = E->getIntegerConstantExpr(S.Context)) {
+        if (Arg.getKind() == TemplateArgument::Integral) {
+          if (hasSameExtendedValue(*Int, Arg.getAsIntegral()))
+            return Sema::TDK_Success;
+        }
+        Info.FirstArg = Param;
+        Info.SecondArg = Arg;
+        return Sema::TDK_NonDeducedMismatch;
+      }
+    }
     if (const NonTypeTemplateParmDecl *NTTP =
-            getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
+            getDeducedParameterFromExpr(Info, E)) {
       if (Arg.getKind() == TemplateArgument::Integral)
-        return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
-                                             Arg.getAsIntegral(),
-                                             Arg.getIntegralType(),
-                                             /*ArrayBound=*/false,
-                                             Info, Deduced);
+        return DeduceNonTypeTemplateArgument(
+            S, TemplateParams, NTTP, Arg.getAsIntegral(), Arg.getIntegralType(),
+            /*ArrayBound=*/false, Info, Deduced);
       if (Arg.getKind() == TemplateArgument::NullPtr)
-        return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
-                                             Arg.getNullPtrType(),
-                                             Info, Deduced);
+        return DeduceNullPtrTemplateArgument(
+            S, TemplateParams, NTTP, Arg.getNullPtrType(), Info, Deduced);
       if (Arg.getKind() == TemplateArgument::Expression)
         return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
                                              Arg.getAsExpr(), Info, Deduced);
       if (Arg.getKind() == TemplateArgument::Declaration)
-        return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
-                                             Arg.getAsDecl(),
-                                             Arg.getParamTypeForDecl(),
-                                             Info, Deduced);
+        return DeduceNonTypeTemplateArgument(
+            S, TemplateParams, NTTP, Arg.getAsDecl(), Arg.getParamTypeForDecl(),
+            Info, Deduced);
 
       Info.FirstArg = Param;
       Info.SecondArg = Arg;
@@ -2411,7 +2411,7 @@
 
     // Can't deduce anything, but that's okay.
     return Sema::TDK_Success;
-
+  }
   case TemplateArgument::Pack:
     llvm_unreachable("Argument packs should be expanded by the caller!");
   }
@@ -4358,7 +4358,7 @@
   bool HasDeducedReturnType = false;
   if (getLangOpts().CPlusPlus14 && IsAddressOfFunction &&
       Function->getReturnType()->getContainedAutoType()) {
-    FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
+    FunctionType = SubstAutoTypeDependent(FunctionType);
     HasDeducedReturnType = true;
   }
 
@@ -4792,12 +4792,8 @@
       ExprResult ER = CheckPlaceholderExpr(Init);
       if (ER.isInvalid())
         return DAR_FailedAlreadyDiagnosed;
-      Init = ER.get();
-      QualType Deduced = BuildDecltypeType(Init, Init->getBeginLoc(), false);
-      if (Deduced.isNull())
-        return DAR_FailedAlreadyDiagnosed;
-      // FIXME: Support a non-canonical deduced type for 'auto'.
-      Deduced = Context.getCanonicalType(Deduced);
+      QualType Deduced = getDecltypeForExpr(ER.get());
+      assert(!Deduced.isNull());
       if (AT->isConstrained() && !IgnoreConstraints) {
         auto ConstraintsResult =
             CheckDeducedPlaceholderConstraints(*this, *AT,
@@ -4832,7 +4828,7 @@
       Context, Loc, Loc, TemplParamPtr, Loc, nullptr);
 
   QualType FuncParam =
-      SubstituteDeducedTypeTransform(*this, TemplArg, /*UseTypeSugar*/false)
+      SubstituteDeducedTypeTransform(*this, TemplArg, /*UseTypeSugar*/ true)
           .Apply(Type);
   assert(!FuncParam.isNull() &&
          "substituting template parameter for 'auto' failed");
@@ -4946,27 +4942,29 @@
 
 QualType Sema::SubstAutoType(QualType TypeWithAuto,
                              QualType TypeToReplaceAuto) {
-  if (TypeToReplaceAuto->isDependentType())
-    return SubstituteDeducedTypeTransform(
-               *this, DependentAuto{
-                          TypeToReplaceAuto->containsUnexpandedParameterPack()})
-        .TransformType(TypeWithAuto);
+  assert(TypeToReplaceAuto != Context.DependentTy);
   return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto)
       .TransformType(TypeWithAuto);
 }
 
 TypeSourceInfo *Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
                                               QualType TypeToReplaceAuto) {
-  if (TypeToReplaceAuto->isDependentType())
-    return SubstituteDeducedTypeTransform(
-               *this,
-               DependentAuto{
-                   TypeToReplaceAuto->containsUnexpandedParameterPack()})
-        .TransformType(TypeWithAuto);
+  assert(TypeToReplaceAuto != Context.DependentTy);
   return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto)
       .TransformType(TypeWithAuto);
 }
 
+QualType Sema::SubstAutoTypeDependent(QualType TypeWithAuto) {
+  return SubstituteDeducedTypeTransform(*this, DependentAuto{false})
+      .TransformType(TypeWithAuto);
+}
+
+TypeSourceInfo *
+Sema::SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto) {
+  return SubstituteDeducedTypeTransform(*this, DependentAuto{false})
+      .TransformType(TypeWithAuto);
+}
+
 QualType Sema::ReplaceAutoType(QualType TypeWithAuto,
                                QualType TypeToReplaceAuto) {
   return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto,
@@ -5161,6 +5159,10 @@
       Args2.resize(NumComparedArguments);
     if (Reversed)
       std::reverse(Args2.begin(), Args2.end());
+
+    auto TF = [&S](QualType T) { return S.Context.getCanonicalType(T); };
+    llvm::transform(Args1, Args1.begin(), TF);
+    llvm::transform(Args2, Args2.begin(), TF);
     if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
                                 Args1.data(), Args1.size(), Info, Deduced,
                                 TDF_None, /*PartialOrdering=*/true))
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -1260,15 +1260,15 @@
       BuildDeclRefExpr(NTTP, NTTP->getType(), VK_PRValue, NTTP->getLocation());
   if (!Ref)
     return true;
-  ExprResult ImmediatelyDeclaredConstraint =
-      formImmediatelyDeclaredConstraint(
-          *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
-          TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(),
-          BuildDecltypeType(Ref, NTTP->getLocation()), NTTP->getLocation(),
-          [&] (TemplateArgumentListInfo &ConstraintArgs) {
-            for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
-              ConstraintArgs.addArgument(TL.getArgLoc(I));
-          }, EllipsisLoc);
+  ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
+      *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
+      TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(),
+      BuildDecltypeType(Ref), NTTP->getLocation(),
+      [&](TemplateArgumentListInfo &ConstraintArgs) {
+        for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
+          ConstraintArgs.addArgument(TL.getArgLoc(I));
+      },
+      EllipsisLoc);
   if (ImmediatelyDeclaredConstraint.isInvalid() ||
      !ImmediatelyDeclaredConstraint.isUsable())
     return true;
@@ -1290,7 +1290,7 @@
     //    - an identifier associated by name lookup with a non-type
     //      template-parameter declared with a type that contains a
     //      placeholder type (7.1.7.4),
-    TSI = SubstAutoTypeSourceInfo(TSI, Context.DependentTy);
+    TSI = SubstAutoTypeSourceInfoDependent(TSI);
   }
 
   return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
@@ -10888,7 +10888,7 @@
       //    - an identifier associated by name lookup with a non-type
       //      template-parameter declared with a type that contains a
       //      placeholder type (7.1.7.4),
-      NewTSI = SubstAutoTypeSourceInfo(NewTSI, Context.DependentTy);
+      NewTSI = SubstAutoTypeSourceInfoDependent(NewTSI);
     }
 
     if (NewTSI != NTTP->getTypeSourceInfo()) {
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -2729,7 +2729,7 @@
       if (auto *DD = dyn_cast<DecompositionDecl>(LoopVar))
         for (auto *Binding : DD->bindings())
           Binding->setType(Context.DependentTy);
-      LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy));
+      LoopVar->setType(SubstAutoTypeDependent(LoopVar->getType()));
     }
   } else if (!BeginDeclStmt.get()) {
     SourceLocation RangeLoc = RangeVar->getLocation();
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -373,7 +373,7 @@
     const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
     QualType Result = FPT->getReturnType();
     if (Result->isUndeducedType()) {
-      Result = SubstAutoType(Result, Context.DependentTy);
+      Result = SubstAutoTypeDependent(Result);
       MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
                                            FPT->getExtProtoInfo());
     }
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -9969,7 +9969,7 @@
 
   auto TemplateName = DeducedTST->getTemplateName();
   if (TemplateName.isDependent())
-    return SubstAutoType(TSInfo->getType(), Context.DependentTy);
+    return SubstAutoTypeDependent(TSInfo->getType());
 
   // We can only perform deduction for class templates.
   auto *Template =
@@ -9988,7 +9988,7 @@
     Diag(TSInfo->getTypeLoc().getBeginLoc(),
          diag::warn_cxx14_compat_class_template_argument_deduction)
         << TSInfo->getTypeLoc().getSourceRange() << 0;
-    return SubstAutoType(TSInfo->getType(), Context.DependentTy);
+    return SubstAutoTypeDependent(TSInfo->getType());
   }
 
   // FIXME: Perform "exact type" matching first, per CWG discussion?
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -468,7 +468,7 @@
 
   assert(DS.getTypeSpecType() == DeclSpec::TST_decltype &&
          "unexpected type in getDestructorType");
-  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+  QualType T = BuildDecltypeType(DS.getRepAsExpr());
 
   // If we know the type of the object, check that the correct destructor
   // type was named now; we can give better diagnostics this way.
@@ -7727,8 +7727,7 @@
     return true;
   }
 
-  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc(),
-                                 false);
+  QualType T = BuildDecltypeType(DS.getRepAsExpr(), /*AsUnevaluated=*/false);
 
   TypeLocBuilder TLB;
   DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -4215,7 +4215,7 @@
     if (BaseType.isNull())
       return true;
   } else if (DS.getTypeSpecType() == TST_decltype) {
-    BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+    BaseType = BuildDecltypeType(DS.getRepAsExpr());
   } else if (DS.getTypeSpecType() == TST_decltype_auto) {
     Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
     return true;
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -3608,14 +3608,14 @@
       // defined, copy the deduced value from the old declaration.
       AutoType *OldAT = Old->getReturnType()->getContainedAutoType();
       if (OldAT && OldAT->isDeduced()) {
-        New->setType(
-            SubstAutoType(New->getType(),
-                          OldAT->isDependentType() ? Context.DependentTy
-                                                   : OldAT->getDeducedType()));
-        NewQType = Context.getCanonicalType(
-            SubstAutoType(NewQType,
-                          OldAT->isDependentType() ? Context.DependentTy
-                                                   : OldAT->getDeducedType()));
+        QualType DT = OldAT->getDeducedType();
+        if (DT.isNull()) {
+          New->setType(SubstAutoTypeDependent(New->getType()));
+          NewQType = Context.getCanonicalType(SubstAutoTypeDependent(NewQType));
+        } else {
+          New->setType(SubstAutoType(New->getType(), DT));
+          NewQType = Context.getCanonicalType(SubstAutoType(NewQType, DT));
+        }
       }
     }
 
@@ -9252,8 +9252,7 @@
       // a friend yet, so 'isDependentContext' on the FD doesn't work.
       const FunctionProtoType *FPT =
           NewFD->getType()->castAs<FunctionProtoType>();
-      QualType Result =
-          SubstAutoType(FPT->getReturnType(), Context.DependentTy);
+      QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
       NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
                                              FPT->getExtProtoInfo()));
     }
@@ -12347,7 +12346,7 @@
                                    /*TreatUnavailableAsInvalid=*/false);
     ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
     if (Result.isInvalid()) {
-      // If the provied initializer fails to initialize the var decl,
+      // If the provided initializer fails to initialize the var decl,
       // we attach a recovery expr for better recovery.
       auto RecoveryExpr =
           CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), Args);
Index: clang/lib/Sema/SemaCXXScopeSpec.cpp
===================================================================
--- clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -865,7 +865,7 @@
 
   assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
 
-  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+  QualType T = BuildDecltypeType(DS.getRepAsExpr());
   if (T.isNull())
     return true;
 
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -4394,10 +4394,10 @@
 }
 
 AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
-                   TypeDependence ExtraDependence,
+                   TypeDependence ExtraDependence, QualType Canon,
                    ConceptDecl *TypeConstraintConcept,
                    ArrayRef<TemplateArgument> TypeConstraintArgs)
-    : DeducedType(Auto, DeducedAsType, ExtraDependence) {
+    : DeducedType(Auto, DeducedAsType, ExtraDependence, Canon) {
   AutoTypeBits.Keyword = (unsigned)Keyword;
   AutoTypeBits.NumArgs = TypeConstraintArgs.size();
   this->TypeConstraintConcept = TypeConstraintConcept;
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1644,36 +1644,48 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+static Error checkCycle(ASTImporter &Importer, const RecordDecl *RD,
+                        QualType QT) {
+  const Type *LeafT = QT.getCanonicalType().getTypePtr();
+  while (LeafT->isPointerType() || LeafT->isArrayType())
+    LeafT = LeafT->getPointeeOrArrayElementType();
+
+  const auto *RT = dyn_cast<RecordType>(LeafT);
+  if (!RT)
+    return Error::success();
+
+  for (const DeclContext *DC = RT->getDecl(); DC; DC = DC->getParent())
+    if (DC == RD) {
+      Importer.FromDiag(RD->getLocation(), diag::err_unsupported_ast_node)
+          << RD->Decl::getDeclKindName();
+      return make_error<ImportError>(ImportError::UnsupportedConstruct);
+    }
+  return Error::success();
+}
+
 //----------------------------------------------------------------------------
 // Import Declarations
 //----------------------------------------------------------------------------
 Error ASTNodeImporter::ImportDeclParts(
     NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
     DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) {
-  // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop.
-  // example: int struct_in_proto(struct data_t{int a;int b;} *d);
+  // Check if FunctionDecl return / parameters are in the RecordDecl context,
+  // in order to avoid an infinite loop.
+  // Example: int struct_in_proto(struct data_t{int a;int b;} *d);
+  // Example: auto struct_in_body() { struct X {}; return X(); }
   // FIXME: We could support these constructs by importing a different type of
-  // this parameter and by importing the original type of the parameter only
+  // this return / parameter and then importing that original type only
   // after the FunctionDecl is created. See
   // VisitFunctionDecl::UsedDifferentProtoType.
-  DeclContext *OrigDC = D->getDeclContext();
-  FunctionDecl *FunDecl;
-  if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) &&
-      FunDecl->hasBody()) {
-    auto getLeafPointeeType = [](const Type *T) {
-      while (T->isPointerType() || T->isArrayType()) {
-        T = T->getPointeeOrArrayElementType();
-      }
-      return T;
-    };
-    for (const ParmVarDecl *P : FunDecl->parameters()) {
-      const Type *LeafT =
-          getLeafPointeeType(P->getType().getCanonicalType().getTypePtr());
-      auto *RT = dyn_cast<RecordType>(LeafT);
-      if (RT && RT->getDecl() == D) {
-        Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
-            << D->getDeclKindName();
-        return make_error<ImportError>(ImportError::UnsupportedConstruct);
+  {
+    const auto *FD = dyn_cast<FunctionDecl>(D->getDeclContext());
+    const auto *RD = dyn_cast<RecordDecl>(D);
+    if (RD && FD && FD->hasBody()) {
+      if (Error Err = checkCycle(Importer, RD, FD->getReturnType()))
+        return Err;
+      for (const ParmVarDecl *P : FD->parameters()) {
+        if (Error Err = checkCycle(Importer, RD, P->getType()))
+          return Err;
       }
     }
   }
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -4817,6 +4817,23 @@
   return QualType(Spec, 0);
 }
 
+static bool
+getCanonicalTemplateArguments(const ASTContext &C,
+                              ArrayRef<TemplateArgument> OrigArgs,
+                              SmallVectorImpl<TemplateArgument> &CanonArgs) {
+  bool AnyNonCanonArgs = false;
+  unsigned NumArgs = OrigArgs.size();
+  CanonArgs.resize(NumArgs);
+  for (unsigned I = 0; I != NumArgs; ++I) {
+    const TemplateArgument &OrigArg = OrigArgs[I];
+    TemplateArgument &CanonArg = CanonArgs[I];
+    CanonArg = C.getCanonicalTemplateArgument(OrigArg);
+    if (!CanonArg.structurallyEquals(OrigArg))
+      AnyNonCanonArgs = true;
+  }
+  return AnyNonCanonArgs;
+}
+
 QualType ASTContext::getCanonicalTemplateSpecializationType(
     TemplateName Template, ArrayRef<TemplateArgument> Args) const {
   assert(!Template.getAsDependentTemplateName() &&
@@ -4829,10 +4846,7 @@
   // Build the canonical template specialization type.
   TemplateName CanonTemplate = getCanonicalTemplateName(Template);
   SmallVector<TemplateArgument, 4> CanonArgs;
-  unsigned NumArgs = Args.size();
-  CanonArgs.reserve(NumArgs);
-  for (const TemplateArgument &Arg : Args)
-    CanonArgs.push_back(getCanonicalTemplateArgument(Arg));
+  ::getCanonicalTemplateArguments(*this, Args, CanonArgs);
 
   // Determine whether this canonical template specialization type already
   // exists.
@@ -4847,7 +4861,7 @@
   if (!Spec) {
     // Allocate a new canonical template specialization type.
     void *Mem = Allocate((sizeof(TemplateSpecializationType) +
-                          sizeof(TemplateArgument) * NumArgs),
+                          sizeof(TemplateArgument) * CanonArgs.size()),
                          TypeAlignment);
     Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
                                                 CanonArgs,
@@ -4989,14 +5003,9 @@
   ElaboratedTypeKeyword CanonKeyword = Keyword;
   if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
 
-  bool AnyNonCanonArgs = false;
-  unsigned NumArgs = Args.size();
-  SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
-  for (unsigned I = 0; I != NumArgs; ++I) {
-    CanonArgs[I] = getCanonicalTemplateArgument(Args[I]);
-    if (!CanonArgs[I].structurallyEquals(Args[I]))
-      AnyNonCanonArgs = true;
-  }
+  SmallVector<TemplateArgument, 16> CanonArgs;
+  bool AnyNonCanonArgs =
+      ::getCanonicalTemplateArguments(*this, Args, CanonArgs);
 
   QualType Canon;
   if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
@@ -5009,7 +5018,7 @@
   }
 
   void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
-                        sizeof(TemplateArgument) * NumArgs),
+                        sizeof(TemplateArgument) * Args.size()),
                        TypeAlignment);
   T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS,
                                                     Name, Args, Canon);
@@ -5594,15 +5603,10 @@
   return QualType(ut, 0);
 }
 
-/// getAutoType - Return the uniqued reference to the 'auto' type which has been
-/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
-/// canonical deduced-but-dependent 'auto' type.
-QualType
-ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
-                        bool IsDependent, bool IsPack,
-                        ConceptDecl *TypeConstraintConcept,
-                        ArrayRef<TemplateArgument> TypeConstraintArgs) const {
-  assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack");
+QualType ASTContext::getAutoTypeInternal(
+    QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent,
+    bool IsPack, ConceptDecl *TypeConstraintConcept,
+    ArrayRef<TemplateArgument> TypeConstraintArgs, bool IsCanon) const {
   if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto &&
       !TypeConstraintConcept && !IsDependent)
     return getAutoDeductType();
@@ -5615,21 +5619,52 @@
   if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(AT, 0);
 
+  QualType Canon;
+  if (!IsCanon) {
+    if (DeducedType.isNull()) {
+      SmallVector<TemplateArgument, 4> CanonArgs;
+      bool AnyNonCanonArgs =
+          ::getCanonicalTemplateArguments(*this, TypeConstraintArgs, CanonArgs);
+      if (AnyNonCanonArgs) {
+        Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
+                                    TypeConstraintConcept, CanonArgs, true);
+        // Find the insert position again.
+        AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
+      }
+    } else {
+      Canon = DeducedType.getCanonicalType();
+    }
+  }
+
   void *Mem = Allocate(sizeof(AutoType) +
-                       sizeof(TemplateArgument) * TypeConstraintArgs.size(),
+                           sizeof(TemplateArgument) * TypeConstraintArgs.size(),
                        TypeAlignment);
   auto *AT = new (Mem) AutoType(
       DeducedType, Keyword,
       (IsDependent ? TypeDependence::DependentInstantiation
                    : TypeDependence::None) |
           (IsPack ? TypeDependence::UnexpandedPack : TypeDependence::None),
-      TypeConstraintConcept, TypeConstraintArgs);
+      Canon, TypeConstraintConcept, TypeConstraintArgs);
   Types.push_back(AT);
-  if (InsertPos)
-    AutoTypes.InsertNode(AT, InsertPos);
+  AutoTypes.InsertNode(AT, InsertPos);
   return QualType(AT, 0);
 }
 
+/// getAutoType - Return the uniqued reference to the 'auto' type which has been
+/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
+/// canonical deduced-but-dependent 'auto' type.
+QualType
+ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
+                        bool IsDependent, bool IsPack,
+                        ConceptDecl *TypeConstraintConcept,
+                        ArrayRef<TemplateArgument> TypeConstraintArgs) const {
+  assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack");
+  assert((!IsDependent || DeducedType.isNull()) &&
+         "A dependent auto should be undeduced");
+  return getAutoTypeInternal(DeducedType, Keyword, IsDependent, IsPack,
+                             TypeConstraintConcept, TypeConstraintArgs);
+}
+
 /// Return the uniqued reference to the deduced template specialization type
 /// which has been deduced to the given type, or to the canonical undeduced
 /// such type, or the canonical deduced-but-dependent such type.
@@ -5647,8 +5682,7 @@
   auto *DTST = new (*this, TypeAlignment)
       DeducedTemplateSpecializationType(Template, DeducedType, IsDependent);
   Types.push_back(DTST);
-  if (InsertPos)
-    DeducedTemplateSpecializationTypes.InsertNode(DTST, InsertPos);
+  DeducedTemplateSpecializationTypes.InsertNode(DTST, InsertPos);
   return QualType(DTST, 0);
 }
 
@@ -5685,7 +5719,7 @@
   if (AutoDeductTy.isNull())
     AutoDeductTy = QualType(new (*this, TypeAlignment)
                                 AutoType(QualType(), AutoTypeKeyword::Auto,
-                                         TypeDependence::None,
+                                         TypeDependence::None, QualType(),
                                          /*concept*/ nullptr, /*args*/ {}),
                             0);
   return AutoDeductTy;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -2348,11 +2348,13 @@
                              const CXXScopeSpec &SS, QualType T,
                              TagDecl *OwnedTagDecl = nullptr);
 
-  QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
+  // Returns the underlying type of a decltype with the given expression.
+  QualType getDecltypeForExpr(Expr *E);
+
+  QualType BuildTypeofExprType(Expr *E);
   /// If AsUnevaluated is false, E is treated as though it were an evaluated
   /// context, such as when building a type for decltype(auto).
-  QualType BuildDecltypeType(Expr *E, SourceLocation Loc,
-                             bool AsUnevaluated = true);
+  QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true);
   QualType BuildUnaryTransformType(QualType BaseType,
                                    UnaryTransformType::UTTKind UKind,
                                    SourceLocation Loc);
@@ -8552,6 +8554,14 @@
   /// Substitute Replacement for auto in TypeWithAuto
   TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
                                           QualType Replacement);
+
+  // Substitute auto in TypeWithAuto for a Dependent auto type
+  QualType SubstAutoTypeDependent(QualType TypeWithAuto);
+
+  // Substitute auto in TypeWithAuto for a Dependent auto type
+  TypeSourceInfo *
+  SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
+
   /// Completely replace the \c auto in \p TypeWithAuto by
   /// \p Replacement. This does not retain any \c auto type sugar.
   QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -4944,29 +4944,31 @@
 /// type-dependent, there is no deduced type and the type is canonical. In
 /// the latter case, it is also a dependent type.
 class DeducedType : public Type {
+  QualType DeducedAsType;
+
 protected:
   DeducedType(TypeClass TC, QualType DeducedAsType,
-              TypeDependence ExtraDependence)
-      : Type(TC,
-             // FIXME: Retain the sugared deduced type?
-             DeducedAsType.isNull() ? QualType(this, 0)
-                                    : DeducedAsType.getCanonicalType(),
+              TypeDependence ExtraDependence, QualType Canon)
+      : Type(TC, Canon,
              ExtraDependence | (DeducedAsType.isNull()
                                     ? TypeDependence::None
                                     : DeducedAsType->getDependence() &
-                                          ~TypeDependence::VariablyModified)) {}
+                                          ~TypeDependence::VariablyModified)),
+        DeducedAsType(DeducedAsType) {}
 
 public:
-  bool isSugared() const { return !isCanonicalUnqualified(); }
-  QualType desugar() const { return getCanonicalTypeInternal(); }
+  bool isSugared() const { return !DeducedAsType.isNull(); }
+  QualType desugar() const {
+    return isSugared() ? DeducedAsType : QualType(this, 0);
+  }
 
   /// Get the type deduced for this placeholder type, or null if it's
   /// either not been deduced or was deduced to a dependent type.
   QualType getDeducedType() const {
-    return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
+    return DeducedAsType.isNull() ? QualType() : DeducedAsType;
   }
   bool isDeduced() const {
-    return !isCanonicalUnqualified() || isDependentType();
+    return !DeducedAsType.isNull() || isDependentType();
   }
 
   static bool classof(const Type *T) {
@@ -4983,7 +4985,7 @@
   ConceptDecl *TypeConstraintConcept;
 
   AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
-           TypeDependence ExtraDependence, ConceptDecl *CD,
+           TypeDependence ExtraDependence, QualType Canon, ConceptDecl *CD,
            ArrayRef<TemplateArgument> TypeConstraintArgs);
 
   const TemplateArgument *getArgBuffer() const {
@@ -5057,7 +5059,9 @@
                     toTypeDependence(Template.getDependence()) |
                         (IsDeducedAsDependent
                              ? TypeDependence::DependentInstantiation
-                             : TypeDependence::None)),
+                             : TypeDependence::None),
+                    DeducedAsType.isNull() ? QualType(this, 0)
+                                           : DeducedAsType.getCanonicalType()),
         Template(Template) {}
 
 public:
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -1525,6 +1525,12 @@
   QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args,
                                    const FunctionProtoType::ExtProtoInfo &EPI,
                                    bool OnlyWantCanonical) const;
+  QualType
+  getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword,
+                      bool IsDependent, bool IsPack = false,
+                      ConceptDecl *TypeConstraintConcept = nullptr,
+                      ArrayRef<TemplateArgument> TypeConstraintArgs = {},
+                      bool IsCanon = false) const;
 
 public:
   /// Return the unique reference to the type for the specified type
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-owning-memory.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-owning-memory.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-owning-memory.cpp
@@ -91,13 +91,9 @@
   // FIXME:, flow analysis for the case of reassignment. Value must be released before
   owned_int6 = owned_int3; // BAD, because reassignment without resource release
 
-  auto owned_int7 = returns_owner1(); // Bad, since type deduction eliminates the owner wrapper
-  // CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'int *' with a newly created 'gsl::owner<>'
-  // CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+  auto owned_int7 = returns_owner1(); // Ok, since type deduction does not eliminate the owner wrapper
 
-  const auto owned_int8 = returns_owner2(); // Bad, since type deduction eliminates the owner wrapper
-  // CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'int *const' with a newly created 'gsl::owner<>'
-  // CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+  const auto owned_int8 = returns_owner2(); // Ok, since type deduction does not eliminate the owner wrapper
 
   gsl::owner<int *> owned_int9 = returns_owner1(); // Ok
   int *unowned_int3 = returns_owner1();            // Bad
@@ -285,15 +281,12 @@
   ClassWithOwner C2{A};                                                // Bad, since the owner would be initialized with an non-owner, but catched in the class
   ClassWithOwner C3{gsl::owner<ArbitraryClass *>(new ArbitraryClass)}; // Ok
 
-  const auto Owner1 = C3.buggy_but_returns_owner(); // BAD, deduces Owner1 to ArbitraryClass *const
-  // CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *const' with a newly created 'gsl::owner<>'
-  // CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+  const auto Owner1 = C3.buggy_but_returns_owner(); // Ok, deduces Owner1 to owner<ArbitraryClass *> const
 
-  auto Owner2 = C2.buggy_but_returns_owner(); // BAD, deduces Owner2 to ArbitraryClass *
-  // CHECK-NOTES: [[@LINE-1]]:3: warning: initializing non-owner 'ArbitraryClass *' with a newly created 'gsl::owner<>'
-  // CHECK-NOTES: [[@LINE-2]]:3: note: type deduction did not result in an owner
+  auto Owner2 = C2.buggy_but_returns_owner(); //Ok, deduces Owner2 to owner<ArbitraryClass *>
 
-  Owner2 = &A; // Ok, since type deduction did NOT result in owner<int*>
+  Owner2 = &A; // BAD, since type deduction resulted in owner<ArbitraryClass *>
+  // CHECK-NOTES: [[@LINE-1]]:3: warning: expected assignment source to be of type 'gsl::owner<>'; got 'ArbitraryClass *'
 
   gsl::owner<ArbitraryClass *> Owner3 = C1.buggy_but_returns_owner(); // Ok, still an owner
   Owner3 = &A;                                                        // Bad, since assignment of non-owner to owner
Index: clang-tools-extra/test/clang-tidy/checkers/cert-static-object-exception.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cert-static-object-exception.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/cert-static-object-exception.cpp
@@ -256,7 +256,7 @@
     return []{ S s; return s; };
   }
 };
-auto Okay4 = []{ U u; return u.getBadLambda(); }();
+auto Okay4 = []() noexcept { U u; return u.getBadLambda(); }();
 auto NotOkay3 = []() noexcept { U u; return u.getBadLambda(); }()(); // Because the lambda returned and called is not noexcept
 // CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'NotOkay3' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
 // CHECK-EXCEPTIONS: :[[@LINE-6]]:12: note: possibly throwing function declared here
@@ -272,4 +272,8 @@
 // FIXME: the above should be diagnosed because the capture init can trigger
 // an exception when constructing the Bad object.
 #endif // NONEXCEPTIONS
+
+auto NotOkay5 = []() { U u; return u.getBadLambda(); }();
+// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'NotOkay5' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
+// CHECK-EXCEPTIONS: :[[@LINE-2]]:17: note: possibly throwing function declared here
 }
Index: clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
@@ -57,7 +57,7 @@
   EXPECT_UNAVAILABLE("au^to x = []{};");
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-            "Visible x = inl_ns::Visible();");
+            "inl_ns::Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
             "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -67,8 +67,9 @@
 
   EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
             "ns::Class * foo() { ns::Class * c = foo(); }");
-  EXPECT_EQ(apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
-            "void ns::Func() { Class::Nested * x = new ns::Class::Nested{}; }");
+  EXPECT_EQ(
+      apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
+      "void ns::Func() { ns::Class::Nested * x = new ns::Class::Nested{}; }");
 
   EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
   // expanding types in structured bindings is syntactically invalid.
Index: clang-tools-extra/clangd/unittests/InlayHintTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -466,7 +466,8 @@
       }
     }
   )cpp",
-                  ExpectedHint{": S1", "x"}, ExpectedHint{": Inner<int>", "y"});
+                  ExpectedHint{": S1", "x"},
+                  ExpectedHint{": S2::Inner<int>", "y"});
 }
 
 TEST(TypeHints, Lambda) {
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -461,7 +461,7 @@
        [](HoverInfo &HI) {
          HI.Name = "auto";
          HI.Kind = index::SymbolKind::TypeAlias;
-         HI.Definition = "class Foo<int>";
+         HI.Definition = "Foo<int>";
        }},
       // auto on specialized template
       {R"cpp(
@@ -474,7 +474,7 @@
        [](HoverInfo &HI) {
          HI.Name = "auto";
          HI.Kind = index::SymbolKind::TypeAlias;
-         HI.Definition = "class Foo<int>";
+         HI.Definition = "Foo<int>";
        }},
 
       // macro
@@ -648,7 +648,7 @@
           [](HoverInfo &HI) {
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
-            HI.Definition = "class Foo<X>";
+            HI.Definition = "Foo<X>";
           }},
       {// Falls back to primary template, when the type is not instantiated.
        R"cpp(
@@ -2024,7 +2024,7 @@
           [](HoverInfo &HI) {
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
-            HI.Definition = "int";
+            HI.Definition = "int_type";
           }},
       {
           R"cpp(// auto on alias
@@ -2035,7 +2035,7 @@
           [](HoverInfo &HI) {
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
-            HI.Definition = "struct cls";
+            HI.Definition = "cls_type";
             HI.Documentation = "auto on alias";
           }},
       {
@@ -2047,7 +2047,7 @@
           [](HoverInfo &HI) {
             HI.Name = "auto";
             HI.Kind = index::SymbolKind::TypeAlias;
-            HI.Definition = "struct templ<int>";
+            HI.Definition = "templ<int>";
             HI.Documentation = "auto on alias";
           }},
       {
Index: clang-tools-extra/clangd/unittests/ASTTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -43,7 +43,7 @@
               namespace ns1 { struct S {}; }
               ^auto v = ns1::S{};
           )cpp",
-          "struct ns1::S",
+          "ns1::S",
       },
       {
           R"cpp( // decltype on struct
@@ -63,7 +63,7 @@
             ns1::S& j = i;
             ^decltype(auto) k = j;
           )cpp",
-          "struct ns1::S &",
+          "ns1::S &",
       },
       {
           R"cpp( // auto on template class
@@ -71,7 +71,7 @@
               template<typename T> class Foo {};
               ^auto v = Foo<X>();
           )cpp",
-          "class Foo<class X>",
+          "Foo<class X>",
       },
       {
           R"cpp( // auto on initializer list.
@@ -177,8 +177,8 @@
             using Bar = Foo;
             ^auto x = Bar();
           )cpp",
-          // FIXME: it'd be nice if this resolved to the alias instead
-          "struct Foo",
+          // It's so nice that this is resolved to the alias instead :-D
+          "Bar",
       },
   };
   for (Test T : Tests) {
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -374,7 +374,7 @@
       void VisitDeducedType(const DeducedType *DT) {
         // FIXME: In practice this doesn't work: the AutoType you find inside
         // TypeLoc never has a deduced type. https://llvm.org/PR42914
-        Outer.add(DT->getDeducedType(), Flags | Rel::Underlying);
+        Outer.add(DT->getDeducedType(), Flags);
       }
       void VisitDeducedTemplateSpecializationType(
           const DeducedTemplateSpecializationType *DTST) {
Index: clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
@@ -125,18 +125,22 @@
       };
 
   auto IsBoundToType = refersToType(equalsBoundNode("type"));
+  auto UnlessFunctionType = unless(hasUnqualifiedDesugaredType(functionType()));
+  auto IsAutoDeducedToPointer = [](const auto &...InnerMatchers) {
+    return autoType(hasDeducedType(
+        hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...)))));
+  };
 
   Finder->addMatcher(
-      ExplicitSingleVarDecl(hasType(autoType(hasDeducedType(
-                                pointerType(pointee(unless(functionType())))))),
+      ExplicitSingleVarDecl(hasType(IsAutoDeducedToPointer(UnlessFunctionType)),
                             "auto"),
       this);
 
   Finder->addMatcher(
       ExplicitSingleVarDeclInTemplate(
-          allOf(hasType(autoType(hasDeducedType(pointerType(
-                    pointee(hasUnqualifiedType(qualType().bind("type")),
-                            unless(functionType())))))),
+          allOf(hasType(IsAutoDeducedToPointer(
+                    hasUnqualifiedType(qualType().bind("type")),
+                    UnlessFunctionType)),
                 anyOf(hasAncestor(
                           functionDecl(hasAnyTemplateArgument(IsBoundToType))),
                       hasAncestor(classTemplateSpecializationDecl(
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
@@ -20,9 +20,11 @@
   if (!getLangOpts().CPlusPlus)
     return;
 
-  const auto AllPointerTypes = anyOf(
-      hasType(pointerType()), hasType(autoType(hasDeducedType(pointerType()))),
-      hasType(decltypeType(hasUnderlyingType(pointerType()))));
+  const auto AllPointerTypes =
+      anyOf(hasType(pointerType()),
+            hasType(autoType(
+                hasDeducedType(hasUnqualifiedDesugaredType(pointerType())))),
+            hasType(decltypeType(hasUnderlyingType(pointerType()))));
 
   // Flag all operators +, -, +=, -=, ++, -- that result in a pointer
   Finder->addMatcher(
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp
@@ -134,14 +134,9 @@
   // Matching on initialization operations where the initial value is a newly
   // created owner, but the LHS is not an owner.
   Finder->addMatcher(
-      traverse(
-          TK_AsIs,
-          namedDecl(
-              varDecl(eachOf(allOf(hasInitializer(CreatesOwner),
-                                   unless(IsOwnerType)),
-                             allOf(hasInitializer(ConsideredOwner),
-                                   hasType(autoType().bind("deduced_type")))))
-                  .bind("bad_owner_creation_variable"))),
+      traverse(TK_AsIs, namedDecl(varDecl(allOf(hasInitializer(CreatesOwner),
+                                                unless(IsOwnerType)))
+                                      .bind("bad_owner_creation_variable"))),
       this);
 
   // Match on all function calls that expect owners as arguments, but didn't
@@ -324,13 +319,6 @@
 
     // FIXME: FixitHint to rewrite the type of the initialized variable
     // as 'gsl::owner<OriginalType>'
-
-    // If the type of the variable was deduced, the wrapping owner typedef is
-    // eliminated, therefore the check emits a special note for that case.
-    if (Nodes.getNodeAs<AutoType>("deduced_type")) {
-      diag(BadOwnerInitialization->getBeginLoc(),
-           "type deduction did not result in an owner", DiagnosticIDs::Note);
-    }
     return true;
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to