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

>From a6ee1af04225063bab4d853611c7a57b1db37aa9 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7...@gmail.com>
Date: Thu, 8 May 2025 19:42:51 +0800
Subject: [PATCH] [Clang] Do not eat SFINAE diagnostics for explicit template
 arguments

---
 clang/lib/Sema/SemaOverload.cpp               | 19 ++++++++++++++++++-
 clang/test/AST/ByteCode/builtin-align-cxx.cpp |  3 ++-
 clang/test/AST/ByteCode/cxx20.cpp             |  3 ++-
 .../basic.namespace/namespace.udecl/p12.cpp   | 12 ++++++++----
 clang/test/CXX/drs/cwg2xx.cpp                 |  4 ++++
 clang/test/CXX/drs/cwg3xx.cpp                 |  2 ++
 clang/test/CXX/expr/expr.const/p3-0x.cpp      |  3 ++-
 clang/test/CXX/temp/temp.param/p8-cxx20.cpp   |  3 ++-
 .../test/CXX/temp/temp.res/temp.local/p1.cpp  |  6 ++++--
 clang/test/Modules/cxx-templates.cpp          |  2 ++
 clang/test/SemaCXX/builtin-align-cxx.cpp      |  3 ++-
 clang/test/SemaCXX/calling-conv-compat.cpp    |  3 ++-
 .../constexpr-function-recovery-crash.cpp     |  3 ++-
 clang/test/SemaCXX/cxx2a-template-lambdas.cpp |  6 ++++--
 clang/test/SemaCXX/typo-correction.cpp        |  3 ++-
 .../test/SemaTemplate/concepts-using-decl.cpp |  6 ++++--
 .../test/SemaTemplate/overload-candidates.cpp | 10 ++++++----
 .../SemaTemplate/temp_arg_nontype_cxx11.cpp   |  5 +++--
 18 files changed, 71 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5b224b6c08fef..9b7878434b9ad 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -749,8 +749,16 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     break;
 
   case TemplateDeductionResult::Incomplete:
+    Result.Data = Info.Param.getOpaqueValue();
+    break;
   case TemplateDeductionResult::InvalidExplicitArguments:
     Result.Data = Info.Param.getOpaqueValue();
+    if (Info.hasSFINAEDiagnostic()) {
+      PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt(
+          SourceLocation(), PartialDiagnostic::NullDiagnostic());
+      Info.takeSFINAEDiagnostic(*Diag);
+      Result.HasDiagnostic = true;
+    }
     break;
 
   case TemplateDeductionResult::DeducedMismatch:
@@ -822,7 +830,6 @@ void DeductionFailureInfo::Destroy() {
   case TemplateDeductionResult::Incomplete:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
     break;
@@ -837,6 +844,7 @@ void DeductionFailureInfo::Destroy() {
     Data = nullptr;
     break;
 
+  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::SubstitutionFailure:
     // FIXME: Destroy the template argument list?
     Data = nullptr;
@@ -12166,6 +12174,15 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl 
*Found, Decl *Templated,
              diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
           << (index + 1);
     }
+
+    if (PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic()) {
+      unsigned DiagID =
+          S.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Note, "%0");
+      SmallString<128> SFINAEArgString;
+      PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
+      S.Diag(Templated->getLocation(), DiagID) << SFINAEArgString;
+    }
+
     MaybeEmitInheritedConstructorNote(S, Found);
     return;
 
diff --git a/clang/test/AST/ByteCode/builtin-align-cxx.cpp 
b/clang/test/AST/ByteCode/builtin-align-cxx.cpp
index a1edf307d6c47..973fd1b620525 100644
--- a/clang/test/AST/ByteCode/builtin-align-cxx.cpp
+++ b/clang/test/AST/ByteCode/builtin-align-cxx.cpp
@@ -4,7 +4,8 @@
 
 // Check that we don't crash when using dependent types in __builtin_align:
 template <typename a, a b>
-void *c(void *d) { // both-note{{candidate template ignored}}
+void *c(void *d) { // both-note{{candidate template ignored}} \
+// both-note {{a non-type template parameter cannot have type 'struct x' 
before C++20}}
   return __builtin_align_down(d, b);
 }
 
diff --git a/clang/test/AST/ByteCode/cxx20.cpp 
b/clang/test/AST/ByteCode/cxx20.cpp
index 42e6ae33e92e4..1625f8eee8425 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -753,7 +753,8 @@ namespace FailingDestructor {
     }
   };
   template<D d>
-  void f() {} // both-note {{invalid explicitly-specified argument}}
+  void f() {} // both-note {{invalid explicitly-specified argument}} \
+              // both-note {{non-type template argument is not a constant 
expression}}
 
   void g() {
     f<D{0, false}>(); // both-error {{no matching function}}
diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp 
b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
index f12e0083fb0c9..ee38418acfb32 100644
--- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
+++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
@@ -113,21 +113,25 @@ namespace test3 {
 
   struct Derived1 : Base {
     using Base::foo;
-    template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note 
{{invalid explicitly-specified argument for template parameter 'n'}}
+    template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note 
{{invalid explicitly-specified argument for template parameter 'n'}} \
+    // expected-note {{template argument for non-type template parameter must 
be an expression}}
   };
 
   struct Derived2 : Base {
-    template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note 
{{invalid explicitly-specified argument for template parameter 'n'}}
+    template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note 
{{invalid explicitly-specified argument for template parameter 'n'}} \
+    // expected-note {{template argument for non-type template parameter must 
be an expression}}
     using Base::foo;
   };
 
   struct Derived3 : Base {
     using Base::foo;
-    template <class T> Opaque<3> foo() { return Opaque<3>(); } // 
expected-note {{invalid explicitly-specified argument for template parameter 
'T'}}
+    template <class T> Opaque<3> foo() { return Opaque<3>(); } // 
expected-note {{invalid explicitly-specified argument for template parameter 
'T'}} \
+    // expected-note {{template argument for template type parameter must be a 
type}}
   };
 
   struct Derived4 : Base {
-    template <class T> Opaque<3> foo() { return Opaque<3>(); } // 
expected-note {{invalid explicitly-specified argument for template parameter 
'T'}}
+    template <class T> Opaque<3> foo() { return Opaque<3>(); } // 
expected-note {{invalid explicitly-specified argument for template parameter 
'T'}} \
+    // expected-note {{template argument for template type parameter must be a 
type}}
     using Base::foo;
   };
 
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index b2ae8f88ead74..604a60c9fa0c9 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -650,14 +650,17 @@ namespace cwg241 { // cwg241: 9
     C::f<3>(b);
     // expected-error@-1 {{no matching function for call to 'f'}}
     //   expected-note@#cwg241-C-f {{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'T'}}
+    //   expected-note@#cwg241-C-f {{template argument for template type 
parameter must be a type}}
     C::g<3>(b);
     // expected-error@-1 {{no matching function for call to 'g'}}
     //   expected-note@#cwg241-C-g {{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'T'}}
+    //   expected-note@#cwg241-C-g {{template argument for template type 
parameter must be a type}}
     using C::f;
     using C::g;
     f<3>(b);
     // expected-error@-1 {{no matching function for call to 'f'}}
     //   expected-note@#cwg241-C-f {{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'T'}}
+    //   expected-note@#cwg241-C-f {{template argument for template type 
parameter must be a type}}
     //   expected-note@#cwg241-A-f {{candidate function template not viable: 
requires 0 arguments, but 1 was provided}}
     g<3>(b);
   }
@@ -952,6 +955,7 @@ namespace cwg258 { // cwg258: 2.8
   int &x = b.g<int>(0);
   // expected-error@-1 {{no matching member function for call to 'g'}}
   //   expected-note@#cwg258-B-g {{candidate template ignored: invalid 
explicitly-specified argument for 1st template parameter}}
+  //   expected-note@#cwg258-B-g {{template argument for non-type template 
parameter must be an expression}}
   int &y = b.h();
   float &z = const_cast<const B&>(b).h();
 
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 8b035cf6f2370..b1b8d20187dcb 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -985,7 +985,9 @@ namespace cwg354 { // cwg354: 3.1 c++11
   int b1 = both<(int*)0>();
   // cxx98-error@-1 {{no matching function for call to 'both'}}
   //   cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: invalid 
explicitly-specified argument for 1st template parameter}}
+  //   cxx98-note@#cwg354-both-int-ptr {{non-type template argument does not 
refer to any declaration}}
   //   cxx98-note@#cwg354-both-int {{candidate template ignored: invalid 
explicitly-specified argument for 1st template parameter}}
+  //   cxx98-note@#cwg354-both-int {{non-type template argument of type 'int 
*' must have an integral or enumeration type}}
 
   template<int S::*> struct ptr_mem {}; // #cwg354-ptr_mem
   ptr_mem<0> m0; // #cwg354-m0
diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp 
b/clang/test/CXX/expr/expr.const/p3-0x.cpp
index 3eedef3cf7712..c7dafc59599dd 100644
--- a/clang/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -107,7 +107,8 @@ void c() {
     break;
   }
 }
-template <bool B> int f() { return B; } // expected-note {{candidate template 
ignored: invalid explicitly-specified argument for template parameter 'B'}}
+template <bool B> int f() { return B; } // expected-note {{candidate template 
ignored: invalid explicitly-specified argument for template parameter 'B'}} \
+// expected-note {{conversion from 'int (S::*)() const' to 'bool' is not 
allowed in a converted constant expression}}
 template int f<&S::operator int>(); // expected-error {{does not refer to a 
function template}}
 template int f<(bool)&S::operator int>();
 
diff --git a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp 
b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
index a3478c0669661..953b613eeef4a 100644
--- a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
+++ b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
@@ -40,7 +40,8 @@ namespace ConstDestruction {
   };
 
   template<D d>
-  void f() {} // expected-note 2{{invalid explicitly-specified argument}}
+  void f() {} // expected-note 2{{invalid explicitly-specified argument}} \
+  // expected-note 2{{non-type template argument is not a constant expression}}
 
   void g() {
     f<D{0, true}>();
diff --git a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp 
b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
index faa85cb5fce30..8a49fc39e2d2b 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
@@ -10,9 +10,11 @@ template<typename> char id;
 template<typename> struct TempType {};
 template<template<typename> class> struct TempTemp {};
 
-template<typename> void use(int&); // expected-note {{invalid 
explicitly-specified argument}} expected-note {{no known conversion}}
+template<typename> void use(int&); // expected-note {{invalid 
explicitly-specified argument}} expected-note {{no known conversion}} \
+// expected-note {{use of class template 'B::template C' requires template 
arguments}}
 template<template<typename> class> void use(float&); // expected-note 2{{no 
known conversion}}
-template<int> void use(char&); // expected-note 2{{invalid 
explicitly-specified argument}}
+template<int> void use(char&); // expected-note 2{{invalid 
explicitly-specified argument}} \
+// expected-note 2{{template argument for non-type template parameter must be 
an expression}}
 
 template<typename T> struct A {
   template<typename> struct C {};
diff --git a/clang/test/Modules/cxx-templates.cpp 
b/clang/test/Modules/cxx-templates.cpp
index f587af4beb7ce..dce93f866b15c 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -43,11 +43,13 @@ void g() {
 
   template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function 
for call}}
   // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
+  // expected-note@Inputs/cxx-templates-a.h:11 {{too many template arguments 
for class template 'Tmpl_T_C'}}
   // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}
 
   template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
   // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
   // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}
+  // expected-note@Inputs/cxx-templates-b.h:11 {{non-type parameter of 
template template parameter cannot be narrowed from type 'int' to 'char'}}
 
   template_param_kinds_3<Tmpl_T_T_A>();
   template_param_kinds_3<Tmpl_T_T_B>();
diff --git a/clang/test/SemaCXX/builtin-align-cxx.cpp 
b/clang/test/SemaCXX/builtin-align-cxx.cpp
index d18bc2bf66551..a680ac2aaa763 100644
--- a/clang/test/SemaCXX/builtin-align-cxx.cpp
+++ b/clang/test/SemaCXX/builtin-align-cxx.cpp
@@ -3,7 +3,8 @@
 
 // Check that we don't crash when using dependent types in __builtin_align:
 template <typename a, a b>
-void *c(void *d) { // expected-note{{candidate template ignored}}
+void *c(void *d) { // expected-note{{candidate template ignored}} \
+// expected-note {{a non-type template parameter cannot have type 'struct x' 
before C++20}}
   return __builtin_align_down(d, b);
 }
 
diff --git a/clang/test/SemaCXX/calling-conv-compat.cpp 
b/clang/test/SemaCXX/calling-conv-compat.cpp
index 9bb448ffef225..8e67528717c5b 100644
--- a/clang/test/SemaCXX/calling-conv-compat.cpp
+++ b/clang/test/SemaCXX/calling-conv-compat.cpp
@@ -425,6 +425,7 @@ namespace D50526 {
   void h() { g<void, h>(); }
 #if !_M_X64
   // expected-error@-2 {{no matching function for call to}}
-  // expected-note@-4 {{invalid explicitly-specified argument}}
+  // expected-note@-4 {{invalid explicitly-specified argument}} \
+  // expected-note@-4 {{non-type template argument of type 'void ()' cannot be 
converted to a value of type 'void (*)() __attribute__((stdcall))'}}
 #endif
 }
diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp 
b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
index 90ee7892b2fc2..086bfa15fe0ea 100644
--- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -60,7 +60,8 @@ constexpr void test8() {
   throw "bad";
 }
 
-template<int x> constexpr int f(int y) { // expected-note {{candidate template 
ignored}}
+template<int x> constexpr int f(int y) { // expected-note {{candidate template 
ignored}} \
+                                         // expected-note {{non-type template 
argument is not a constant expression}}
   return x * y;
 }
 constexpr int test9(int x) {
diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp 
b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
index 00ba291fbd198..413bf7cd09667 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++03 -verify -Dstatic_assert=_Static_assert 
-Wno-c++11-extensions -Wno-c++14-extensions -Wno-c++17-extensions 
-Wno-c++20-extensions %s
 // RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11,cxx11-cxx14 
-Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions  %s
 // RUN: %clang_cc1 -std=c++14 -verify=expected,cxx11-cxx14,cxx14 
-Wno-c++20-extensions -Wno-c++17-extensions %s
-// RUN: %clang_cc1 -std=c++17 -verify -Wno-c++20-extensions %s
-// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx17,cxx17-cxx20 
-Wno-c++20-extensions %s
+// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20,cxx17-cxx20 %s
 
 template<typename, typename>
 inline const bool is_same = false;
@@ -47,6 +47,8 @@ constexpr T outer() {
   return []<T x>() { return x; }.template operator()<123>(); // expected-error 
{{no matching member function}}  \
                                                                 expected-note 
{{candidate template ignored}}    \
         cxx11-note {{non-literal type '<dependent type>' cannot be used in a 
constant expression}} \
+        cxx11-cxx14-note {{non-type template argument does not refer to any 
declaration}} \
+        cxx17-cxx20-note {{value of type 'int' is not implicitly convertible 
to 'int *'}} \
         cxx14-note {{non-literal type}}
 }
 static_assert(outer<int>() == 123); // cxx11-cxx14-error {{not an integral 
constant expression}} cxx11-cxx14-note {{in call}}
diff --git a/clang/test/SemaCXX/typo-correction.cpp 
b/clang/test/SemaCXX/typo-correction.cpp
index 45f42c4260358..c25d01eade890 100644
--- a/clang/test/SemaCXX/typo-correction.cpp
+++ b/clang/test/SemaCXX/typo-correction.cpp
@@ -614,7 +614,8 @@ int bar() {
 
 namespace testIncludeTypeInTemplateArgument {
 template <typename T, typename U>
-void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}}
+void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}} \
+                            // expected-note {{template argument for template 
type parameter must be a type}}
 
 class AddObservation {}; // expected-note {{declared here}}
 int bar1() {
diff --git a/clang/test/SemaTemplate/concepts-using-decl.cpp 
b/clang/test/SemaTemplate/concepts-using-decl.cpp
index fca69dea5c88f..cad160fd585c0 100644
--- a/clang/test/SemaTemplate/concepts-using-decl.cpp
+++ b/clang/test/SemaTemplate/concepts-using-decl.cpp
@@ -165,8 +165,10 @@ struct base {
 
 struct bar : public base {
   using base::foo;
-  template <int N> 
-  int foo() { return 2; }; // expected-note {{candidate template ignored: 
substitution failure: too many template arguments for function template 'foo'}}
+  template <int N>
+  int foo() { return 2; };
+  // expected-note@-1 {{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'N'}} \
+  // expected-note@-1 {{too many template arguments for function template 
'foo'}}
 };
 
 void func() {
diff --git a/clang/test/SemaTemplate/overload-candidates.cpp 
b/clang/test/SemaTemplate/overload-candidates.cpp
index de998d74f9af6..25f0492a71729 100644
--- a/clang/test/SemaTemplate/overload-candidates.cpp
+++ b/clang/test/SemaTemplate/overload-candidates.cpp
@@ -16,10 +16,12 @@ void test_dyn_cast(int* ptr) {
   (void)dyn_cast(ptr); // expected-error{{no matching function for call to 
'dyn_cast'}}
 }
 
-template<int I, typename T> 
-  void get(const T&); // expected-note{{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'I'}}
-template<template<class T> class, typename T> 
-  void get(const T&); // expected-note{{candidate template ignored: invalid 
explicitly-specified argument for 1st template parameter}}
+template<int I, typename T>
+  void get(const T&); // expected-note{{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'I'}} \
+  // expected-note {{template argument for non-type template parameter must be 
an expression}}
+template<template<class T> class, typename T>
+  void get(const T&); // expected-note{{candidate template ignored: invalid 
explicitly-specified argument for 1st template parameter}} \
+  // expected-note {{template argument for template template parameter must be 
a class template}}
 
 void test_get(void *ptr) {
   get<int>(ptr); // expected-error{{no matching function for call to 'get'}}
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp 
b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 5752cbac0291d..44bc5b7642f76 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -42,8 +42,9 @@ template <int a, unsigned b, int c>
 void TempFunc() {}
 
 void Useage() {
-  //expected-error@+2 {{no matching function}}
-  //expected-note@-4 {{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'b'}}
+  //expected-error@+3 {{no matching function}}
+  //expected-note@-4 {{candidate template ignored: invalid 
explicitly-specified argument for template parameter 'b'}} \
+  //expected-note@-4 {{non-type template argument evaluates to -1, which 
cannot be narrowed to type 'unsigned int'}}
   TempFunc<1, -1, 1>();
 }
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to