[clang] [Clang] Clarify diagnostic notes for implicitly generated deduction guides (PR #96084)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 25 19:54:22 PDT 2024


https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/96084

>From 23844cd8b8fad07bce0c34f58430322090c5a793 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Wed, 19 Jun 2024 23:25:13 +0800
Subject: [PATCH 1/7] [Clang] Add diagnostic notes for implcitly generated
 deduction guides

---
 clang/docs/ReleaseNotes.rst                   |  3 ++
 .../clang/Basic/DiagnosticSemaKinds.td        |  1 +
 clang/lib/Sema/SemaOverload.cpp               | 30 +++++++++++++++++++
 clang/test/CXX/drs/cwg26xx.cpp                |  3 ++
 .../CXX/expr/expr.post/expr.type.conv/p1.cpp  |  2 +-
 .../over.match.class.deduct/p2.cpp            |  2 +-
 .../temp.deduct/temp.deduct.call/p3-0x.cpp    |  4 +--
 clang/test/Modules/template_name_lookup.cpp   |  2 ++
 clang/test/PCH/cxx-explicit-specifier.cpp     |  2 +-
 clang/test/Sema/tls_alignment.cpp             |  4 ++-
 ...xx1z-class-template-argument-deduction.cpp |  6 ++--
 clang/test/SemaCXX/cxx20-ctad-type-alias.cpp  | 17 +++++++++--
 clang/test/SemaCXX/cxx2a-explicit-bool.cpp    |  2 ++
 clang/test/SemaCXX/gh65522.cpp                |  3 +-
 ...deduction-guide-as-template-candidates.cpp |  4 ++-
 .../lookup-template-name-extern-CXX.cpp       |  6 ++--
 .../aggregate-deduction-candidate.cpp         | 24 ++++++++-------
 clang/test/SemaTemplate/class-template-id.cpp |  2 ++
 clang/test/SemaTemplate/ctad.cpp              |  6 ++--
 clang/test/SemaTemplate/deduction-crash.cpp   |  3 +-
 clang/test/SemaTemplate/deduction-guide.cpp   |  6 ++--
 .../nested-implicit-deduction-guides.cpp      |  3 ++
 clang/test/SemaTemplate/temp_arg.cpp          |  4 ++-
 23 files changed, 108 insertions(+), 31 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 69aea6c21ad39..423f1e9198948 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -580,6 +580,9 @@ Improvements to Clang's diagnostics
 - Clang no longer emits a "declared here" note for a builtin function that has no declaration in source.
   Fixes #GH93369.
 
+- Clang now emits implicit deduction guides corresponding to non-user-defined constructors while at a failure
+  of overload resolution.
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ab223f2b806d5..a65491b0c4399 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2405,6 +2405,7 @@ def err_selected_explicit_constructor : Error<
   "chosen constructor is explicit in copy-initialization">;
 def note_explicit_ctor_deduction_guide_here : Note<
   "explicit %select{constructor|deduction guide}0 declared here">;
+def note_implicit_deduction_guide : Note<"implicit deduction guide declared as '%0'">;
 
 // C++11 auto
 def warn_cxx98_compat_auto_type_specifier : Warning<
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index fb4ff72e42eb5..31b908eb3cc3c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -40,6 +40,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
@@ -12114,6 +12115,35 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
     return;
   }
 
+  // If this is an implicit deduction guide against a non-user-defined
+  // constructor, add a note for it. These deduction guides nor their
+  // corresponding constructors are not explicitly spelled in the source code,
+  // and simply producing a deduction failure note around the heading of the
+  // enclosing RecordDecl is confusing.
+  //
+  // We prefer adding such notes at the end of the last deduction failure
+  // reason because duplicate code snippets appearing in the diagnostic
+  // are likely becoming noisy.
+  auto _ = llvm::make_scope_exit([&] {
+    auto *DG = dyn_cast<CXXDeductionGuideDecl>(Fn);
+    if (!DG || !DG->isImplicit() || DG->getCorrespondingConstructor())
+      return;
+    std::string FunctionProto;
+    llvm::raw_string_ostream OS(FunctionProto);
+    FunctionTemplateDecl *Template = DG->getDescribedFunctionTemplate();
+    // This also could be an instantiation. Find out the primary template.
+    if (!Template) {
+      FunctionDecl *Pattern = DG->getTemplateInstantiationPattern();
+      assert(Pattern && Pattern->getDescribedFunctionTemplate() &&
+             "Cannot find the associated function template of "
+             "CXXDeductionGuideDecl?");
+      Template = Pattern->getDescribedFunctionTemplate();
+    }
+    Template->print(OS);
+    S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
+        << FunctionProto;
+  });
+
   switch (Cand->FailureKind) {
   case ovl_fail_too_many_arguments:
   case ovl_fail_too_few_arguments:
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index 2b17c8101438d..95dfa229530fb 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -194,8 +194,11 @@ static_assert(__is_same(decltype(i), I<char, 4>));
 J j = { "ghi" };
 // since-cxx20-error at -1 {{no viable constructor or deduction guide}}
 //   since-cxx20-note@#cwg2681-J {{candidate template ignored: could not match 'J<N>' against 'const char *'}}
+//   since-cxx20-note@#cwg2681-J {{implicit deduction guide declared as 'template <size_t N> J(J<N>) -> J<N>'}}
 //   since-cxx20-note@#cwg2681-J {{candidate template ignored: could not match 'const unsigned char' against 'const char'}}
+//   since-cxx20-note@#cwg2681-J {{implicit deduction guide declared as 'template <size_t N> J(const unsigned char (&)[N]) -> J<N>'}}
 //   since-cxx20-note@#cwg2681-J {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
+//   since-cxx20-note@#cwg2681-J {{implicit deduction guide declared as 'template <size_t N> J() -> J<N>'}}
 #endif
 }
 
diff --git a/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp b/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp
index f3608bc378bc7..aa3c022e9b134 100644
--- a/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp
+++ b/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -std=c++1z -verify %s
 
-template<typename T> struct A { // expected-note 2{{candidate}}
+template<typename T> struct A { // expected-note 2{{candidate}} {{implicit deduction guide}}
   T t, u;
 };
 template<typename T> A(T, T) -> A<T>; // expected-note {{deduced conflicting types for parameter 'T'}}
diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
index 49fde292f6a36..4bcf4ee2e3fe7 100644
--- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
+++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
@@ -35,7 +35,7 @@ namespace std {
 }
 
 namespace p0702r1 {
-  template<typename T> struct X { // expected-note {{candidate}}
+  template<typename T> struct X { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
     X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'std::initializer_list<T>' against 'Z'}}
   };
 
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
index 8592626269eed..2e39697a1f07f 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
@@ -6,7 +6,7 @@
 #if __cplusplus > 201402L
 namespace ClassTemplateParamNotForwardingRef {
   // This is not a forwarding reference.
-  template<typename T> struct A { // expected-note {{candidate}}
+  template<typename T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
     A(T&&); // expected-note {{expects an rvalue}}
   };
   int n;
@@ -75,7 +75,7 @@ namespace std_example {
   int n3 = g(i); // expected-error{{no matching function for call to 'g'}}
 
 #if __cplusplus > 201402L
-  template<class T> struct A { // expected-note {{candidate}}
+  template<class T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
     template<class U>
     A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}}
     A(T &&, int *);       // expected-note {{requires 2}}
diff --git a/clang/test/Modules/template_name_lookup.cpp b/clang/test/Modules/template_name_lookup.cpp
index 29375e514025f..82b06e83afce3 100644
--- a/clang/test/Modules/template_name_lookup.cpp
+++ b/clang/test/Modules/template_name_lookup.cpp
@@ -7,5 +7,7 @@ import foo;
 void use() {
   X x; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'X'}}
        // expected-note at Inputs/template_name_lookup/foo.cppm:3 {{candidate template ignored: couldn't infer template argument 'T'}}
+       // expected-note at Inputs/template_name_lookup/foo.cppm:3 {{implicit deduction guide declared as 'template <typename T> X(X<T>) -> X<T>'}}
        // expected-note at Inputs/template_name_lookup/foo.cppm:3 {{candidate function template not viable: requires 1 argument, but 0 were provided}}
+       // expected-note at Inputs/template_name_lookup/foo.cppm:3 {{implicit deduction guide declared as 'template <typename T> X() -> X<T>'}}
 }
diff --git a/clang/test/PCH/cxx-explicit-specifier.cpp b/clang/test/PCH/cxx-explicit-specifier.cpp
index 94ca9f7b080db..68dfc911164c5 100644
--- a/clang/test/PCH/cxx-explicit-specifier.cpp
+++ b/clang/test/PCH/cxx-explicit-specifier.cpp
@@ -79,7 +79,7 @@ struct A {
 B<true> b_true;
 B<false> b_false;
 #else
-//expected-note at -8 {{candidate template ignored}}
+//expected-note at -8 {{candidate template ignored}} expected-note at -8 {{implicit deduction guide declared as 'template <bool b> A(A<b>) -> A<b>'}}
 //expected-note at -8 {{explicit constructor declared here}}
 //expected-note at -15+ {{candidate constructor}}
 //expected-note at -8+ {{explicit conversion function is not a candidate (explicit specifier}}
diff --git a/clang/test/Sema/tls_alignment.cpp b/clang/test/Sema/tls_alignment.cpp
index c5c79aafa9ead..65b6b035e7917 100644
--- a/clang/test/Sema/tls_alignment.cpp
+++ b/clang/test/Sema/tls_alignment.cpp
@@ -22,7 +22,9 @@ struct  struct_with_aligned_field {
 template <typename>
 struct templated_struct {};
 // expected-note at -1{{candidate template ignored: couldn't infer template argument ''}}
-// expected-note at -2{{candidate function template not viable: requires 1 argument, but 0 were provided}}
+// expected-note at -2{{implicit deduction guide declared as 'template <typename> templated_struct() -> templated_struct<type-parameter-0-0>'}}
+// expected-note at -3{{candidate function template not viable: requires 1 argument, but 0 were provided}}
+// expected-note at -4{{implicit deduction guide declared as 'template <typename> templated_struct(templated_struct<type-parameter-0-0>) -> templated_struct<type-parameter-0-0>'}}
 
 // A typedef of the aligned struct.
 typedef aligned_struct another_aligned_struct;
diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 90404f115c75f..0a296b32cfb6f 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -139,7 +139,8 @@ namespace look_into_current_instantiation {
                     // templates, and members of the current instantiation
   A<float> &r = a;
 
-  template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}}
+  template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}} \
+                                     expected-note {{implicit deduction guide declared as 'template <typename T> B(B<T>) -> B<T>'}}
     struct X {
       typedef T type;
     };
@@ -564,7 +565,8 @@ namespace PR47175 {
 
 // Ensure we don't crash when CTAD fails.
 template <typename T1, typename T2>
-struct Foo {   // expected-note{{candidate function template not viable}}
+struct Foo {   // expected-note{{candidate function template not viable}} \
+                  expected-note{{implicit deduction guide declared as 'template <typename T1, typename T2> Foo(Foo<T1, T2>) -> Foo<T1, T2>'}}
   Foo(T1, T2); // expected-note{{candidate function template not viable}}
 };
 
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index b71dfc6ccaf4f..901f64434bbee 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -108,8 +108,11 @@ struct Foo {
   Foo(T const (&)[N]);
 };
 
+// FIXME: Clarify that __is_deducible constraints are unsatisfied. For example, GCC currently prints the code snippet around constructors
+// FIXME: Prefer non-canonical template arguments in the deduction guide?
 template <typename X, int Y>
 using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \
+                               // expected-note {{implicit deduction guide declared as 'template <typename X> Bar(Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
                                // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \
                                // expected-note {{cannot deduce template arguments for 'Bar' from 'Foo<int, 4UL>'}}
 
@@ -137,9 +140,12 @@ struct A {};
 template<class T> struct Foo { T c; };
 template<class X, class Y=A>
 using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0>' against 'int'}} \
+                    // expected-note {{implicit deduction guide declared as 'template <class Y = A> AFoo(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}} \
                     // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \
                     // expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo<int>'}} \
-                    // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
+                    // expected-note {{implicit deduction guide declared as 'template <class Y = A> AFoo(type-parameter-0-0) -> Foo<type-parameter-0-0>'}} \
+                    // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} \
+                    // expected-note {{implicit deduction guide declared as 'template <class Y = A> AFoo() -> Foo<type-parameter-0-0>'}}
 
 AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}}
 } // namespace test11
@@ -192,6 +198,7 @@ struct Foo {
 template <int K>
 using Bar = Foo<double, K>; // expected-note {{constraints not satisfied for class template 'Foo'}}
 // expected-note at -1 {{candidate template ignored: could not match}}
+// expected-note at -2 {{implicit deduction guide declared as 'template <int K> Bar(Foo<double, K>) -> Foo<double, K>'}}
 double abc[3];
 Bar s2 = {abc}; // expected-error {{no viable constructor or deduction guide for deduction }}
 } // namespace test14
@@ -204,6 +211,7 @@ template<typename> concept False = false;
 template<False W>
 using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \
                       // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \
+                      // expected-note {{implicit deduction guide declared as 'template <class V> BFoo(Foo<type-parameter-0-0 *>) -> Foo<type-parameter-0-0 *>'}} \
                       // expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0 *>' against 'int *'}}
 int i = 0;
 AFoo a1(&i); // OK, deduce Foo<int *>
@@ -256,7 +264,9 @@ Foo(T) -> Foo<int>;
 template <typename U>
 using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>' against 'int'}} \
                     // expected-note {{candidate template ignored: constraints not satisfied}} \
-                    // expected-note {{candidate function template not viable}}
+                    // expected-note {{candidate function template not viable}} \
+                    // expected-note {{implicit deduction guide declared as 'template <typename U> Bar() -> Foo<type-parameter-0-0>'}} \
+                    // expected-note {{implicit deduction guide declared as 'template <typename U> Bar(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}}
 
 Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
 } // namespace test18
@@ -284,7 +294,8 @@ class Foo {};
 // Verify that template template type parameter TTP is referenced/used in the
 // template arguments of the RHS.
 template <template<typename> typename TTP>
-using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<template-parameter-0-0>>' against 'int'}}
+using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<template-parameter-0-0>>' against 'int'}} \
+                        // expected-note {{implicit deduction guide declared as 'template <template <typename> typename TTP> Bar(Foo<K<template-parameter-0-0>>) -> Foo<K<template-parameter-0-0>>'}}
 
 template <class T>
 class Container {};
diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
index 9fdc059493aac..13b5ff1d59b31 100644
--- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
+++ b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
@@ -394,6 +394,7 @@ using type = T;
 template<typename T1, typename T2, bool b>
 struct A {
   // expected-note at -1+ {{candidate function}}
+  // expected-note at -2+ {{implicit deduction guide}}
   explicit(false)
   A(typename nondeduced<T1>::type, typename nondeduced<T2>::type, typename nondeduced<B<b>>::type) {}
   // expected-note at -1+ {{candidate template ignored}}
@@ -678,6 +679,7 @@ namespace deduction_guide2 {
 template<typename T1 = int, typename T2 = int>
 struct A {
   // expected-note at -1+ {{candidate template ignored}}
+  // expected-note at -2+ {{implicit deduction guide}}
   explicit(!is_same<T1, T2>::value)
   A(T1 = 0, T2 = 0) {}
   // expected-note at -1 {{explicit constructor declared here}}
diff --git a/clang/test/SemaCXX/gh65522.cpp b/clang/test/SemaCXX/gh65522.cpp
index 2d6331b0372a3..bfc3a1e12fe76 100644
--- a/clang/test/SemaCXX/gh65522.cpp
+++ b/clang/test/SemaCXX/gh65522.cpp
@@ -3,7 +3,8 @@
 class X {};
 
 template<typename T>
-class B3 { // expected-note {{candidate template ignored: could not match 'B3<T>' against 'int'}}
+class B3 { // expected-note {{candidate template ignored: could not match 'B3<T>' against 'int'}} \
+           // expected-note {{implicit deduction guide declared as 'template <typename T> B3(B3<T>) -> B3<T>'}}
   template<X x> B3(T); // expected-warning 2{{non-type template parameter of type 'X' is incompatible with C++ standards before C++20}} \
                        // expected-note {{candidate template ignored: couldn't infer template argument 'x'}}
 };
diff --git a/clang/test/SemaCXX/invalid-deduction-guide-as-template-candidates.cpp b/clang/test/SemaCXX/invalid-deduction-guide-as-template-candidates.cpp
index e9b362d67cd23..ad7441ff48477 100644
--- a/clang/test/SemaCXX/invalid-deduction-guide-as-template-candidates.cpp
+++ b/clang/test/SemaCXX/invalid-deduction-guide-as-template-candidates.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
 
 template <class T> class Foo {}; // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} \
-                                 // expected-note {{candidate function template not viable: requires 1 argument, but 0 were provided}}
+                                 // expected-note {{implicit deduction guide declared as 'template <class T> Foo(Foo<T>) -> Foo<T>'}} \
+                                 // expected-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
+                                 // expected-note {{implicit deduction guide declared as 'template <class T> Foo() -> Foo<T>'}}
 Foo(); // expected-error {{deduction guide declaration without trailing return type}}
 Foo vs; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'Foo'}}
diff --git a/clang/test/SemaCXX/lookup-template-name-extern-CXX.cpp b/clang/test/SemaCXX/lookup-template-name-extern-CXX.cpp
index 93e7fb6199354..f851af7ecec26 100644
--- a/clang/test/SemaCXX/lookup-template-name-extern-CXX.cpp
+++ b/clang/test/SemaCXX/lookup-template-name-extern-CXX.cpp
@@ -3,8 +3,10 @@
 // RUN: %clang_cc1 -std=c++20 %s -fsyntax-only -verify
 extern "C++" {
 template <class T>
-class X {}; // expected-note {{candidate template ignored: couldn't infer template argument 'T'}}
-            // expected-note at -1 {{candidate function template not viable: requires 1 argument, but 0 were provided}}
+class X {}; // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} \
+            // expected-note {{implicit deduction guide declared as 'template <class T> X(X<T>) -> X<T>'}} \
+            // expected-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
+            // expected-note {{implicit deduction guide declared as 'template <class T> X() -> X<T>'}}
 }
 
 void foo() {
diff --git a/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp b/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
index 5a50332d73307..49afb6b860620 100644
--- a/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
+++ b/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
@@ -2,7 +2,7 @@
 // RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20 -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace
 
 namespace Basic {
-  template<class T> struct A { // cxx17-note 6 {{candidate}}
+  template<class T> struct A { // cxx17-note 6 {{candidate}} cxx17-note 6 {{implicit deduction guide}}
     T x;
     T y;
   };
@@ -36,12 +36,14 @@ namespace Basic {
     T y;
   };
 
-  template <typename T> struct C { // cxx20-note 10 {{candidate}} cxx17-note 12 {{candidate}}
+  template <typename T> struct C { // cxx20-note 10 {{candidate}} cxx17-note 12 {{candidate}} \
+                                      cxx20-note 10 {{implicit deduction guide}} cxx17-note 12 {{implicit deduction guide}}
     S<T> s;
     T t;
   };
 
-  template <typename T> struct D { // cxx20-note 6 {{candidate}} cxx17-note 8 {{candidate}}
+  template <typename T> struct D { // cxx20-note 6 {{candidate}} cxx17-note 8 {{candidate}} \
+                                      cxx20-note 6 {{implicit deduction guide}} cxx17-note 8 {{implicit deduction guide}}
     S<int> s;
     T t;
   };
@@ -99,7 +101,7 @@ namespace Basic {
   // CHECK:   |-ClassTemplateSpecialization {{.*}} 'S'
   // CHECK:   `-BuiltinType {{.*}} 'int'
 
-  template <typename T> struct E { // cxx17-note 4 {{candidate}}
+  template <typename T> struct E { // cxx17-note 4 {{candidate}} cxx17-note 4 {{implicit deduction guide}}
     T t;
     decltype(t) t2;
   };
@@ -133,7 +135,7 @@ namespace Basic {
   };
 
   template <typename T>
-  struct F { // cxx17-note 2 {{candidate}}
+  struct F { // cxx17-note 2 {{candidate}} cxx17-note 2 {{implicit deduction guide}}
     typename I<T>::type i;
     T t;
   };
@@ -161,7 +163,8 @@ namespace Basic {
 
 namespace Array {
   typedef unsigned long size_t;
-  template <typename T, size_t N> struct A { // cxx20-note 2 {{candidate}} cxx17-note 14 {{candidate}}
+  template <typename T, size_t N> struct A { // cxx20-note 2 {{candidate}} cxx17-note 14 {{candidate}} \
+                                                cxx20-note 2 {{implicit deduction guide}} cxx17-note 14 {{implicit deduction guide}}
     T array[N];
   };
 
@@ -217,7 +220,7 @@ namespace Array {
 }
 
 namespace BraceElision {
-  template <typename T> struct A { // cxx17-note 4 {{candidate}}
+  template <typename T> struct A { // cxx17-note 4 {{candidate}} cxx17-note 4 {{implicit deduction guide}}
     T array[2];
   };
 
@@ -247,7 +250,7 @@ namespace BraceElision {
 }
 
 namespace TrailingPack {
-  template<typename... T> struct A : T... { // cxx17-note 4 {{candidate}}
+  template<typename... T> struct A : T... { // cxx17-note 4 {{candidate}} cxx17-note 4 {{implicit deduction guide}}
   };
 
   A a1 = { // cxx17-error {{no viable}}
@@ -286,7 +289,7 @@ namespace TrailingPack {
 }
 
 namespace NonTrailingPack {
-  template<typename... T> struct A : T... { // expected-note 4 {{candidate}}
+  template<typename... T> struct A : T... { // expected-note 4 {{candidate}} expected-note 4 {{implicit deduction guide}}
     int a;
   };
 
@@ -303,7 +306,8 @@ namespace NonTrailingPack {
 
 namespace DeduceArity {
   template <typename... T> struct Types {};
-  template <typename... T> struct F : Types<T...>, T... {}; // cxx20-note 12 {{candidate}} cxx17-note 16 {{candidate}}
+  template <typename... T> struct F : Types<T...>, T... {}; // cxx20-note 12 {{candidate}} cxx17-note 16 {{candidate}} \
+                                                               cxx20-note 12 {{implicit deduction guide}} cxx17-note 16 {{implicit deduction guide}}
 
   struct X {};
   struct Y {};
diff --git a/clang/test/SemaTemplate/class-template-id.cpp b/clang/test/SemaTemplate/class-template-id.cpp
index eade4f6290424..96696f62b78a2 100644
--- a/clang/test/SemaTemplate/class-template-id.cpp
+++ b/clang/test/SemaTemplate/class-template-id.cpp
@@ -45,6 +45,8 @@ typedef N::C<float> c2;
 // PR5655
 template<typename T> struct Foo { }; // precxx17-note {{template is declared here}} \
                                         cxx17-note {{candidate template ignored: couldn't infer template argument 'T'}} \
+                                        cxx17-note {{implicit deduction guide declared as 'template <typename T> Foo() -> Foo<T>'}} \
+                                        cxx17-note {{implicit deduction guide declared as 'template <typename T> Foo(Foo<T>) -> Foo<T>'}} \
                                         cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}}
 
 void f(void) { Foo bar; } // precxx17-error {{use of class template 'Foo' requires template arguments}} \
diff --git a/clang/test/SemaTemplate/ctad.cpp b/clang/test/SemaTemplate/ctad.cpp
index e981ea8d5ecfb..c5e467a8d7724 100644
--- a/clang/test/SemaTemplate/ctad.cpp
+++ b/clang/test/SemaTemplate/ctad.cpp
@@ -20,7 +20,8 @@ namespace Access {
   protected:
     struct type {};
   };
-  template<typename T> struct D : B { // expected-note {{not viable}}
+  template<typename T> struct D : B { // expected-note {{not viable}} \
+                                         expected-note {{implicit deduction guide declared as 'template <typename T> D(D<T>) -> D<T>'}}
     D(T, typename T::type); // expected-note {{private member}}
   };
   D b = {B(), {}};
@@ -64,7 +65,8 @@ class C : A<int> {
   using A::A;
 };
 template <typename>
-class D : C { // expected-note {{candidate function template not viable: requires 1 argument}}
+class D : C { // expected-note {{candidate function template not viable: requires 1 argument}} \
+                 expected-note {{implicit deduction guide declared as 'template <typename> D(D<type-parameter-0-0>) -> D<type-parameter-0-0>'}}
   using C::C;
 };
 D abc; // expected-error {{no viable constructor or deduction guide}}
diff --git a/clang/test/SemaTemplate/deduction-crash.cpp b/clang/test/SemaTemplate/deduction-crash.cpp
index 86ec9f7980a7d..e3f97c594aa90 100644
--- a/clang/test/SemaTemplate/deduction-crash.cpp
+++ b/clang/test/SemaTemplate/deduction-crash.cpp
@@ -166,8 +166,9 @@ namespace PR51872_part1 {
   template<int> class T1 { template <struct U1> T1(); };
   // expected-error at -1 {{non-type template parameter has incomplete type 'struct U1'}}
   // expected-note at -2  {{forward declaration of 'PR51872_part1::U1'}}
+  // expected-note at -3  {{implicit deduction guide declared as 'template <int> T1(T1<>) -> T1<>'}}
 
   T1 t1 = 0;
   // expected-error at -1 {{no viable constructor or deduction guide for deduction of template arguments of 'T1'}}
-  // expected-note at -6  {{candidate template ignored: could not match 'T1<>' against 'int'}}
+  // expected-note at -7  {{candidate template ignored: could not match 'T1<>' against 'int'}}
 }
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp
index 163b36519950f..54420be9ee969 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -123,7 +123,8 @@ using CT = C<int>;
 // CHECK: |   `-TemplateArgument template
 // CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2
 
-template<typename ...T> struct D { // expected-note {{candidate}}
+template<typename ...T> struct D { // expected-note {{candidate}} \
+                                      expected-note {{implicit deduction guide declared as 'template <typename ...T> D(D<T...>) -> D<T...>'}}
   template<typename... U> using B = int(int (*...p)(T, U));
   template<typename U1, typename U2> D(B<U1, U2>*); // expected-note {{candidate}}
 };
@@ -166,7 +167,8 @@ using DT = D<int, int>;
 // CHECK-NOT: Subst
 // CHECK:                     `-TemplateTypeParmType
 
-template<int ...N> struct E { // expected-note {{candidate}}
+template<int ...N> struct E { // expected-note {{candidate}} \
+                                 expected-note {{implicit deduction guide declared as 'template <int ...N> E(E<N...>) -> E<N...>'}}
   template<int ...M> using B = Z<X<N, M>...>;
   template<int M1, int M2> E(B<M1, M2>); // expected-note {{candidate}}
 };
diff --git a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
index a4ae046ac5274..af3e3358f6138 100644
--- a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
+++ b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
@@ -82,8 +82,11 @@ using NIL = nested_init_list<int>::B<int>;
 // expected-error at +1 {{no viable constructor or deduction guide for deduction of template arguments of 'nested_init_list<int>::concept_fail'}}
 nested_init_list<int>::concept_fail nil_invalid{1, ""};
 // expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: substitution failure [with F = const char *]: constraints not satisfied for class template 'concept_fail' [with F = const char *]}}
+// expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail(int, F) -> concept_fail<F>'}}
 // expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 1 argument, but 2 were provided}}
+// expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail(concept_fail<F>) -> concept_fail<F>'}}
 // expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 0 arguments, but 2 were provided}}
+// expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail() -> concept_fail<F>'}}
 
 namespace GH88142 {
 
diff --git a/clang/test/SemaTemplate/temp_arg.cpp b/clang/test/SemaTemplate/temp_arg.cpp
index 2db4a51d6cccb..538056a4e44c7 100644
--- a/clang/test/SemaTemplate/temp_arg.cpp
+++ b/clang/test/SemaTemplate/temp_arg.cpp
@@ -6,7 +6,9 @@ template<typename T,
   class A; // precxx17-note 3 {{template is declared here}} \
               cxx17-note 2 {{template is declared here}} \
               cxx17-note {{candidate template ignored: couldn't infer template argument 'T'}} \
-              cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}}
+              cxx17-note {{implicit deduction guide declared as 'template <typename T, int I, template <typename> class TT> A(A<T, I, TT>) -> A<T, I, TT>'}} \
+              cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
+              cxx17-note {{implicit deduction guide declared as 'template <typename T, int I, template <typename> class TT> A() -> A<T, I, TT>'}} \
 
 template<typename> class X;
 

>From 68a06465fc2385e8bd8a29eb5c353f1ae5cc916d Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Fri, 21 Jun 2024 11:25:47 +0800
Subject: [PATCH 2/7] Apply suggestions from Sirraide

Co-authored-by: Sirraide <aeternalmail at gmail.com>
---
 clang/docs/ReleaseNotes.rst     |  4 ++--
 clang/lib/Sema/SemaOverload.cpp | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 423f1e9198948..558792fb82e7e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -580,8 +580,8 @@ Improvements to Clang's diagnostics
 - Clang no longer emits a "declared here" note for a builtin function that has no declaration in source.
   Fixes #GH93369.
 
-- Clang now emits implicit deduction guides corresponding to non-user-defined constructors while at a failure
-  of overload resolution.
+- Clang now shows implicit deduction guides corresponding to implcitly defined constructors when 
+  diagnosing overload resolution failure.
 
 Improvements to Clang's time-trace
 ----------------------------------
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 31b908eb3cc3c..38e52581ab5af 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12115,15 +12115,15 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
     return;
   }
 
-  // If this is an implicit deduction guide against a non-user-defined
-  // constructor, add a note for it. These deduction guides nor their
-  // corresponding constructors are not explicitly spelled in the source code,
+  // If this is an implicit deduction guide against an implicitly defined
+  // constructor, add a note for it. Neither these deduction guides nor their
+  // corresponding constructors are explicitly spelled in the source code,
   // and simply producing a deduction failure note around the heading of the
-  // enclosing RecordDecl is confusing.
+  // enclosing RecordDecl would be confusing.
   //
   // We prefer adding such notes at the end of the last deduction failure
   // reason because duplicate code snippets appearing in the diagnostic
-  // are likely becoming noisy.
+  // would likely become noisy.
   auto _ = llvm::make_scope_exit([&] {
     auto *DG = dyn_cast<CXXDeductionGuideDecl>(Fn);
     if (!DG || !DG->isImplicit() || DG->getCorrespondingConstructor())

>From 616da22375b870090215e2318f1c98ffc3a23a5a Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Fri, 21 Jun 2024 11:28:12 +0800
Subject: [PATCH 3/7] Fix tests

---
 clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp b/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp
index aa3c022e9b134..f8d88e13fce31 100644
--- a/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp
+++ b/clang/test/CXX/expr/expr.post/expr.type.conv/p1.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -std=c++1z -verify %s
 
-template<typename T> struct A { // expected-note 2{{candidate}} {{implicit deduction guide}}
+template<typename T> struct A { // expected-note 2{{candidate}} expected-note 2{{implicit deduction guide}}
   T t, u;
 };
 template<typename T> A(T, T) -> A<T>; // expected-note {{deduced conflicting types for parameter 'T'}}

>From a468b7ccad1f70e9db3fc4c1f1c6f6478479bd93 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 25 Jun 2024 19:53:33 +0800
Subject: [PATCH 4/7] Address Hokein's feedback

---
 clang/docs/ReleaseNotes.rst                   |  2 +-
 clang/lib/Sema/SemaOverload.cpp               | 25 ++++++++++++-------
 .../over.match.class.deduct/p2.cpp            |  3 ++-
 .../temp.deduct/temp.deduct.call/p3-0x.cpp    |  8 +++---
 clang/test/PCH/cxx-explicit-specifier.cpp     |  2 +-
 ...xx1z-class-template-argument-deduction.cpp | 12 +++++----
 clang/test/SemaCXX/cxx20-ctad-type-alias.cpp  |  6 ++++-
 clang/test/SemaCXX/cxx2a-explicit-bool.cpp    |  2 ++
 clang/test/SemaCXX/gh65522.cpp                |  3 ++-
 clang/test/SemaTemplate/ctad.cpp              |  6 +++--
 clang/test/SemaTemplate/deduction-guide.cpp   |  8 +++---
 11 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4c9f2b76a5e15..71ed84a9fff4a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -610,7 +610,7 @@ Improvements to Clang's diagnostics
   The check is now stricter to prevent crashes for some unsupported declarations (Fixes #GH95495).
 
 - Clang now shows implicit deduction guides corresponding to implcitly defined constructors when 
-  diagnosing overload resolution failure.
+  diagnosing overload resolution failure. #GH92393.
 
 Improvements to Clang's time-trace
 ----------------------------------
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 38e52581ab5af..4214c0041da56 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12115,18 +12115,25 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
     return;
   }
 
-  // If this is an implicit deduction guide against an implicitly defined
-  // constructor, add a note for it. Neither these deduction guides nor their
-  // corresponding constructors are explicitly spelled in the source code,
-  // and simply producing a deduction failure note around the heading of the
-  // enclosing RecordDecl would be confusing.
+  // If this is a synthesized deduction guide we're deducing against, add a note
+  // for it. These deduction guides are not explicitly spelled in the source
+  // code, so simply printing a deduction failure note mentioning synthesized
+  // template parameters or pointing to the header of the surrounding RecordDecl
+  // would be confusing.
   //
-  // We prefer adding such notes at the end of the last deduction failure
-  // reason because duplicate code snippets appearing in the diagnostic
-  // would likely become noisy.
+  // We prefer adding such notes at the end of the deduction failure because
+  // duplicate code snippets appearing in the diagnostic would likely become
+  // noisy.
   auto _ = llvm::make_scope_exit([&] {
     auto *DG = dyn_cast<CXXDeductionGuideDecl>(Fn);
-    if (!DG || !DG->isImplicit() || DG->getCorrespondingConstructor())
+    if (!DG)
+      return;
+    // We want to always print synthesized deduction guides for type aliases.
+    // They would retain the explicit bit of the corresponding constructor.
+    if (TemplateDecl *OriginTemplate =
+            DG->getDeclName().getCXXDeductionGuideTemplate();
+        !DG->isImplicit() &&
+        (!OriginTemplate || !OriginTemplate->isTypeAlias()))
       return;
     std::string FunctionProto;
     llvm::raw_string_ostream OS(FunctionProto);
diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
index 4bcf4ee2e3fe7..d192070132d78 100644
--- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
+++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
@@ -36,7 +36,8 @@ namespace std {
 
 namespace p0702r1 {
   template<typename T> struct X { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
-    X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'std::initializer_list<T>' against 'Z'}}
+    X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'std::initializer_list<T>' against 'Z'}} \
+                                 // expected-note {{implicit deduction guide declared as 'template <typename T> X(std::initializer_list<T>) -> X<T>'}}
   };
 
   X xi = {0};
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
index 2e39697a1f07f..ed445360c4fdd 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
@@ -7,7 +7,7 @@
 namespace ClassTemplateParamNotForwardingRef {
   // This is not a forwarding reference.
   template<typename T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
-    A(T&&); // expected-note {{expects an rvalue}}
+    A(T&&); // expected-note {{expects an rvalue}} expected-note {{implicit deduction guide}}
   };
   int n;
   A a = n; // expected-error {{no viable constructor or deduction guide}}
@@ -77,8 +77,10 @@ namespace std_example {
 #if __cplusplus > 201402L
   template<class T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
     template<class U>
-    A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}}
-    A(T &&, int *);       // expected-note {{requires 2}}
+    A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}} \
+                          // expected-note {{implicit deduction guide declared as 'template <class T, class U> A(T &&, type-parameter-0-1 &&, int *) -> A<T>'}}
+    A(T &&, int *);       // expected-note {{requires 2}} \
+                          // expected-note {{implicit deduction guide declared as 'template <class T> A(T &&, int *) -> A<T>'}}
   };
   template<class T> A(T &&, int *) -> A<T>; // expected-note {{requires 2}}
 
diff --git a/clang/test/PCH/cxx-explicit-specifier.cpp b/clang/test/PCH/cxx-explicit-specifier.cpp
index 68dfc911164c5..84548faf48810 100644
--- a/clang/test/PCH/cxx-explicit-specifier.cpp
+++ b/clang/test/PCH/cxx-explicit-specifier.cpp
@@ -80,7 +80,7 @@ B<true> b_true;
 B<false> b_false;
 #else
 //expected-note at -8 {{candidate template ignored}} expected-note at -8 {{implicit deduction guide declared as 'template <bool b> A(A<b>) -> A<b>'}}
-//expected-note at -8 {{explicit constructor declared here}}
+//expected-note at -8 {{explicit constructor declared here}} expected-note at -8 {{implicit deduction guide declared as 'template <bool b> explicit(b) A(B<b>) -> A<b>'}}
 //expected-note at -15+ {{candidate constructor}}
 //expected-note at -8+ {{explicit conversion function is not a candidate (explicit specifier}}
 //expected-note at -11 {{explicit constructor is not a candidate (explicit specifier}}
diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 0a296b32cfb6f..9ef5303a9c4df 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -140,11 +140,12 @@ namespace look_into_current_instantiation {
   A<float> &r = a;
 
   template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}} \
-                                     expected-note {{implicit deduction guide declared as 'template <typename T> B(B<T>) -> B<T>'}}
+                                  // expected-note {{implicit deduction guide declared as 'template <typename T> B(B<T>) -> B<T>'}}
     struct X {
       typedef T type;
     };
-    B(typename X::type); // expected-note {{couldn't infer template argument 'T'}}
+    B(typename X::type); // expected-note {{couldn't infer template argument 'T'}} \
+                         // expected-note {{implicit deduction guide declared as 'template <typename T> B(typename X::type) -> B<T>'}}
   };
   B b = 0; // expected-error {{no viable}}
 
@@ -565,9 +566,10 @@ namespace PR47175 {
 
 // Ensure we don't crash when CTAD fails.
 template <typename T1, typename T2>
-struct Foo {   // expected-note{{candidate function template not viable}} \
-                  expected-note{{implicit deduction guide declared as 'template <typename T1, typename T2> Foo(Foo<T1, T2>) -> Foo<T1, T2>'}}
-  Foo(T1, T2); // expected-note{{candidate function template not viable}}
+struct Foo {   // expected-note {{candidate function template not viable}} \
+               // expected-note {{implicit deduction guide declared as 'template <typename T1, typename T2> Foo(Foo<T1, T2>) -> Foo<T1, T2>'}}
+  Foo(T1, T2); // expected-note {{candidate function template not viable}} \
+               // expected-note {{implicit deduction guide declared as 'template <typename T1, typename T2> Foo(T1, T2) -> Foo<T1, T2>'}}
 };
 
 template <typename... Args>
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index 901f64434bbee..4cd53e10e74c5 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -113,6 +113,7 @@ struct Foo {
 template <typename X, int Y>
 using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \
                                // expected-note {{implicit deduction guide declared as 'template <typename X> Bar(Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
+                               // expected-note {{implicit deduction guide declared as 'template <typename X> Bar(const type-parameter-0-0 (&)[sizeof(type-parameter-0-0)]) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
                                // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \
                                // expected-note {{cannot deduce template arguments for 'Bar' from 'Foo<int, 4UL>'}}
 
@@ -199,6 +200,7 @@ template <int K>
 using Bar = Foo<double, K>; // expected-note {{constraints not satisfied for class template 'Foo'}}
 // expected-note at -1 {{candidate template ignored: could not match}}
 // expected-note at -2 {{implicit deduction guide declared as 'template <int K> Bar(Foo<double, K>) -> Foo<double, K>'}}
+// expected-note at -3 {{implicit deduction guide declared as 'template <int K> Bar(const double (&)[K]) -> Foo<double, K>'}}
 double abc[3];
 Bar s2 = {abc}; // expected-error {{no viable constructor or deduction guide for deduction }}
 } // namespace test14
@@ -211,6 +213,7 @@ template<typename> concept False = false;
 template<False W>
 using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \
                       // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \
+                      // expected-note {{implicit deduction guide declared as 'template <class V> BFoo(type-parameter-0-0 *) -> Foo<type-parameter-0-0 *>'}} \
                       // expected-note {{implicit deduction guide declared as 'template <class V> BFoo(Foo<type-parameter-0-0 *>) -> Foo<type-parameter-0-0 *>'}} \
                       // expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0 *>' against 'int *'}}
 int i = 0;
@@ -266,7 +269,8 @@ using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>'
                     // expected-note {{candidate template ignored: constraints not satisfied}} \
                     // expected-note {{candidate function template not viable}} \
                     // expected-note {{implicit deduction guide declared as 'template <typename U> Bar() -> Foo<type-parameter-0-0>'}} \
-                    // expected-note {{implicit deduction guide declared as 'template <typename U> Bar(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}}
+                    // expected-note {{implicit deduction guide declared as 'template <typename U> Bar(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}} \
+                    // expected-note {{implicit deduction guide declared as 'template <typename T> Bar(type-parameter-0-0) -> Foo<int>'}}
 
 Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
 } // namespace test18
diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
index 13b5ff1d59b31..03799c52654a5 100644
--- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
+++ b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
@@ -398,6 +398,7 @@ struct A {
   explicit(false)
   A(typename nondeduced<T1>::type, typename nondeduced<T2>::type, typename nondeduced<B<b>>::type) {}
   // expected-note at -1+ {{candidate template ignored}}
+  // expected-note at -2+ {{implicit deduction guide}}
 };
 
 template<typename T1, typename T2, bool b>
@@ -684,6 +685,7 @@ struct A {
   A(T1 = 0, T2 = 0) {}
   // expected-note at -1 {{explicit constructor declared here}}
   // expected-note at -2 2{{explicit constructor is not a candidate}}
+  // expected-note at -3 2{{implicit deduction guide declared}}
 };
 
 A a0 = 0;
diff --git a/clang/test/SemaCXX/gh65522.cpp b/clang/test/SemaCXX/gh65522.cpp
index bfc3a1e12fe76..80281248c6d49 100644
--- a/clang/test/SemaCXX/gh65522.cpp
+++ b/clang/test/SemaCXX/gh65522.cpp
@@ -6,7 +6,8 @@ template<typename T>
 class B3 { // expected-note {{candidate template ignored: could not match 'B3<T>' against 'int'}} \
            // expected-note {{implicit deduction guide declared as 'template <typename T> B3(B3<T>) -> B3<T>'}}
   template<X x> B3(T); // expected-warning 2{{non-type template parameter of type 'X' is incompatible with C++ standards before C++20}} \
-                       // expected-note {{candidate template ignored: couldn't infer template argument 'x'}}
+                       // expected-note {{candidate template ignored: couldn't infer template argument 'x'}} \
+                       // expected-note {{implicit deduction guide declared as 'template <typename T, X x> B3(T) -> B3<T>'}}
 };
 B3 b3 = 0; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'B3'}} \
            // expected-note {{while building implicit deduction guide first needed here}}
diff --git a/clang/test/SemaTemplate/ctad.cpp b/clang/test/SemaTemplate/ctad.cpp
index c5e467a8d7724..1bf605f823bbe 100644
--- a/clang/test/SemaTemplate/ctad.cpp
+++ b/clang/test/SemaTemplate/ctad.cpp
@@ -22,7 +22,8 @@ namespace Access {
   };
   template<typename T> struct D : B { // expected-note {{not viable}} \
                                          expected-note {{implicit deduction guide declared as 'template <typename T> D(D<T>) -> D<T>'}}
-    D(T, typename T::type); // expected-note {{private member}}
+    D(T, typename T::type); // expected-note {{private member}} \
+                            // expected-note {{implicit deduction guide declared as 'template <typename T> D(T, typename T::type) -> D<T>'}}
   };
   D b = {B(), {}};
 
@@ -59,7 +60,8 @@ Y y(1);
 namespace NoCrashOnGettingDefaultArgLoc {
 template <typename>
 class A {
-  A(int = 1); // expected-note {{candidate template ignored: couldn't infer template argumen}}
+  A(int = 1); // expected-note {{candidate template ignored: couldn't infer template argumen}} \
+              // expected-note {{implicit deduction guide declared as 'template <typename> D(int = <null expr>) -> D<type-parameter-0-0>'}}
 };
 class C : A<int> {
   using A::A;
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp
index 54420be9ee969..7b9ca4d83b020 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -124,9 +124,10 @@ using CT = C<int>;
 // CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2
 
 template<typename ...T> struct D { // expected-note {{candidate}} \
-                                      expected-note {{implicit deduction guide declared as 'template <typename ...T> D(D<T...>) -> D<T...>'}}
+                                   // expected-note {{implicit deduction guide declared as 'template <typename ...T> D(D<T...>) -> D<T...>'}}
   template<typename... U> using B = int(int (*...p)(T, U));
-  template<typename U1, typename U2> D(B<U1, U2>*); // expected-note {{candidate}}
+  template<typename U1, typename U2> D(B<U1, U2>*); // expected-note {{candidate}} \
+                                                    // expected-note {{implicit deduction guide declared as 'template <typename ...T, typename U1, typename U2> D(B<type-parameter-0-1, type-parameter-0-2> *) -> D<T...>'}}
 };
 int f(int(int, int), int(int, int));
 // FIXME: We can't deduce this because we can't deduce through a
@@ -170,7 +171,8 @@ using DT = D<int, int>;
 template<int ...N> struct E { // expected-note {{candidate}} \
                                  expected-note {{implicit deduction guide declared as 'template <int ...N> E(E<N...>) -> E<N...>'}}
   template<int ...M> using B = Z<X<N, M>...>;
-  template<int M1, int M2> E(B<M1, M2>); // expected-note {{candidate}}
+  template<int M1, int M2> E(B<M1, M2>); // expected-note {{candidate}} \
+                                         // expected-note {{implicit deduction guide declared as 'template <int ...N, int M1, int M2> E(B<M1, M2>) -> E<N...>'}}}}
 };
 // FIXME: We can't deduce this because we can't deduce through a
 // SubstNonTypeTemplateParmPackExpr.

>From 34b665e55ceded46da20c492a99179b9a41a15b6 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 25 Jun 2024 20:17:52 +0800
Subject: [PATCH 5/7] Remove an unnecessary FIXME

---
 clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index 4cd53e10e74c5..761648926f99b 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -108,7 +108,6 @@ struct Foo {
   Foo(T const (&)[N]);
 };
 
-// FIXME: Clarify that __is_deducible constraints are unsatisfied. For example, GCC currently prints the code snippet around constructors
 // FIXME: Prefer non-canonical template arguments in the deduction guide?
 template <typename X, int Y>
 using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \

>From 8ef907675dc2448aca68182d6729dba4c53acbba Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Wed, 26 Jun 2024 10:51:55 +0800
Subject: [PATCH 6/7] Move the function out-of-line and adapt to #96686

---
 clang/lib/Sema/SemaOverload.cpp | 59 +++++++++++++++++++++------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4214c0041da56..8165ede26f1f4 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12058,6 +12058,43 @@ static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) {
       << (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange());
 }
 
+static void maybeNoteImplicitDeductionGuide(Sema &S,
+                                            CXXDeductionGuideDecl *DG) {
+  // We want to always print synthesized deduction guides for type aliases.
+  // They would retain the explicit bit of the corresponding constructor.
+  TemplateDecl *OriginTemplate =
+      DG->getDeclName().getCXXDeductionGuideTemplate();
+  if (!DG->isImplicit() && (!OriginTemplate || !OriginTemplate->isTypeAlias()))
+    return;
+  std::string FunctionProto;
+  llvm::raw_string_ostream OS(FunctionProto);
+  FunctionTemplateDecl *Template = DG->getDescribedFunctionTemplate();
+  if (!Template) {
+    // This also could be an instantiation. Find out the primary template.
+    FunctionDecl *Pattern =
+        DG->getTemplateInstantiationPattern(/*ForDefinition=*/false);
+    if (!Pattern) {
+      // The implicit deduction guide is built on an explicit non-template
+      // deduction guide. Currently, this might be the case only for type
+      // aliases.
+      // FIXME: Add a test once https://github.com/llvm/llvm-project/pull/96686
+      // gets merged.
+      assert(OriginTemplate->isTypeAlias() &&
+            "Only deduction guides for type aliases can have no template Decls");
+      DG->print(OS);
+      S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
+          << FunctionProto;
+      return;
+    }
+    Template = Pattern->getDescribedFunctionTemplate();
+    assert(Template && "Cannot find the associated function template of "
+                       "CXXDeductionGuideDecl?");
+  }
+  Template->print(OS);
+  S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
+      << FunctionProto;
+}
+
 /// Generates a 'note' diagnostic for an overload candidate.  We've
 /// already generated a primary error at the call site.
 ///
@@ -12128,27 +12165,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
     auto *DG = dyn_cast<CXXDeductionGuideDecl>(Fn);
     if (!DG)
       return;
-    // We want to always print synthesized deduction guides for type aliases.
-    // They would retain the explicit bit of the corresponding constructor.
-    if (TemplateDecl *OriginTemplate =
-            DG->getDeclName().getCXXDeductionGuideTemplate();
-        !DG->isImplicit() &&
-        (!OriginTemplate || !OriginTemplate->isTypeAlias()))
-      return;
-    std::string FunctionProto;
-    llvm::raw_string_ostream OS(FunctionProto);
-    FunctionTemplateDecl *Template = DG->getDescribedFunctionTemplate();
-    // This also could be an instantiation. Find out the primary template.
-    if (!Template) {
-      FunctionDecl *Pattern = DG->getTemplateInstantiationPattern();
-      assert(Pattern && Pattern->getDescribedFunctionTemplate() &&
-             "Cannot find the associated function template of "
-             "CXXDeductionGuideDecl?");
-      Template = Pattern->getDescribedFunctionTemplate();
-    }
-    Template->print(OS);
-    S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
-        << FunctionProto;
+    maybeNoteImplicitDeductionGuide(S, DG);
   });
 
   switch (Cand->FailureKind) {

>From bb0b8364228474d0a9734bdfc60f696c692f2d9e Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Wed, 26 Jun 2024 10:54:02 +0800
Subject: [PATCH 7/7] Format

---
 clang/lib/Sema/SemaOverload.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 8165ede26f1f4..64d7294a6bf29 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12079,8 +12079,9 @@ static void maybeNoteImplicitDeductionGuide(Sema &S,
       // aliases.
       // FIXME: Add a test once https://github.com/llvm/llvm-project/pull/96686
       // gets merged.
-      assert(OriginTemplate->isTypeAlias() &&
-            "Only deduction guides for type aliases can have no template Decls");
+      assert(
+          OriginTemplate->isTypeAlias() &&
+          "Only deduction guides for type aliases can have no template Decls");
       DG->print(OS);
       S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
           << FunctionProto;



More information about the cfe-commits mailing list