[clang] [clang][Sema] Improve template argument deduction diagnostic (PR #122754)

Aidan Goldfarb via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 5 08:02:56 PST 2025


https://github.com/AidanGoldfarb updated https://github.com/llvm/llvm-project/pull/122754

>From b6c576fb90362640b2fd4e41bd7f13dfee95d04d Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 13 Jan 2025 11:53:39 -0500
Subject: [PATCH 01/27] initial template arg fix push

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 +-
 clang/include/clang/Sema/TemplateDeduction.h  |  5 ++
 clang/lib/Sema/SemaOverload.cpp               | 56 +++++++++++++++----
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  8 +++
 4 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8be4f946dce1cc..1456f34538bcc0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4871,8 +4871,8 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
 def note_ovl_candidate_explicit_arg_mismatch_named : Note<
-    "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0">;
+    "template argument deduction/substitution failed:" 
+    "error: could not convert '%0' from %1 to %2">;
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
 def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index 28b014fd84e4b3..9edd3724cf53cd 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -250,6 +250,9 @@ class TemplateDeductionInfo {
   /// \brief The constraint satisfaction details resulting from the associated
   /// constraints satisfaction tests.
   ConstraintSatisfaction AssociatedConstraintsSatisfaction;
+
+  /// \brief Type supplied by user for deduction
+  TemplateArgument SuppliedType;
 };
 
 } // namespace sema
@@ -300,6 +303,8 @@ struct DeductionFailureInfo {
   TemplateDeductionResult getResult() const {
     return static_cast<TemplateDeductionResult>(Result);
   }
+
+  const TemplateArgument *getSuppliedType();
 };
 
 /// TemplateSpecCandidate - This is a generalization of OverloadCandidate
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 34c287926b1d7d..6c437a52be21db 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -715,12 +715,18 @@ namespace {
   struct DFIParamWithArguments : DFIArguments {
     TemplateParameter Param;
   };
+
   // Structure used by DeductionFailureInfo to store template argument
   // information and the index of the problematic call argument.
   struct DFIDeducedMismatchArgs : DFIArguments {
     TemplateArgumentList *TemplateArgs;
     unsigned CallArgIndex;
   };
+
+  struct DFIParamWithArgumentsAndSuppliedType : DFIArguments {
+    TemplateParameter Param;
+    TemplateArgument SuppliedType;
+  };
   // Structure used by DeductionFailureInfo to store information about
   // unsatisfied constraints.
   struct CNSInfo {
@@ -736,8 +742,10 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
                                 TemplateDeductionResult TDK,
                                 TemplateDeductionInfo &Info) {
   DeductionFailureInfo Result;
+
   Result.Result = static_cast<unsigned>(TDK);
   Result.HasDiagnostic = false;
+
   switch (TDK) {
   case TemplateDeductionResult::Invalid:
   case TemplateDeductionResult::InstantiationDepth:
@@ -749,10 +757,9 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     break;
 
   case TemplateDeductionResult::Incomplete:
-  case TemplateDeductionResult::InvalidExplicitArguments:
+    // case TemplateDeductionResult::InvalidExplicitArguments:
     Result.Data = Info.Param.getOpaqueValue();
     break;
-
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested: {
     // FIXME: Should allocate from normal heap so that we can free this later.
@@ -777,6 +784,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
   case TemplateDeductionResult::IncompletePack:
     // FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
   case TemplateDeductionResult::Inconsistent:
+
   case TemplateDeductionResult::Underqualified: {
     // FIXME: Should allocate from normal heap so that we can free this later.
     DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
@@ -786,6 +794,16 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     Result.Data = Saved;
     break;
   }
+  case TemplateDeductionResult::InvalidExplicitArguments: {
+    DFIParamWithArgumentsAndSuppliedType *Saved =
+        new (Context) DFIParamWithArgumentsAndSuppliedType;
+    Saved->Param = Info.Param;
+    Saved->FirstArg = Info.FirstArg;
+    Saved->SecondArg = Info.SecondArg;
+    Saved->SuppliedType = Info.SuppliedType;
+    Result.Data = Saved;
+    break;
+  }
 
   case TemplateDeductionResult::SubstitutionFailure:
     Result.Data = Info.takeSugared();
@@ -822,13 +840,14 @@ void DeductionFailureInfo::Destroy() {
   case TemplateDeductionResult::Incomplete:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  case TemplateDeductionResult::InvalidExplicitArguments:
+  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
     break;
 
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
+  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Underqualified:
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested:
@@ -885,11 +904,11 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
     return TemplateParameter();
 
   case TemplateDeductionResult::Incomplete:
-  case TemplateDeductionResult::InvalidExplicitArguments:
     return TemplateParameter::getFromOpaqueValue(Data);
 
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
+  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Underqualified:
     return static_cast<DFIParamWithArguments*>(Data)->Param;
 
@@ -938,6 +957,16 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
   return nullptr;
 }
 
+const TemplateArgument *DeductionFailureInfo::getSuppliedType() {
+  switch (static_cast<TemplateDeductionResult>(Result)) {
+  case TemplateDeductionResult::InvalidExplicitArguments:
+    return &static_cast<DFIParamWithArgumentsAndSuppliedType *>(Data)
+                ->SuppliedType;
+  default:
+    return nullptr;
+  }
+}
+
 const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   switch (static_cast<TemplateDeductionResult>(Result)) {
   case TemplateDeductionResult::Success:
@@ -946,15 +975,17 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   case TemplateDeductionResult::Incomplete:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  case TemplateDeductionResult::InvalidExplicitArguments:
+  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::SubstitutionFailure:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return nullptr;
-
+  // case TemplateDeductionResult::InvalidExplicitArguments: //move back up
+  // there^^
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
+  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Underqualified:
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested:
@@ -979,7 +1010,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  case TemplateDeductionResult::InvalidExplicitArguments:
+  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::SubstitutionFailure:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
@@ -987,6 +1018,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
     return nullptr;
 
   case TemplateDeductionResult::Inconsistent:
+  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Underqualified:
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested:
@@ -11613,6 +11645,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
   (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
   (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
   (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+
   switch (DeductionFailure.getResult()) {
   case TemplateDeductionResult::Success:
     llvm_unreachable(
@@ -11716,11 +11749,14 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
 
   case TemplateDeductionResult::InvalidExplicitArguments:
     assert(ParamD && "no parameter found for invalid explicit arguments");
-    if (ParamD->getDeclName())
+    if (ParamD->getDeclName()) {
+      auto FirstArg = *DeductionFailure.getFirstArg();
+      auto SecondArg = *DeductionFailure.getSecondArg();
+      auto SuppliedType = *DeductionFailure.getSuppliedType();
       S.Diag(Templated->getLocation(),
              diag::note_ovl_candidate_explicit_arg_mismatch_named)
-          << ParamD->getDeclName();
-    else {
+          << FirstArg << SuppliedType << SecondArg;
+    } else {
       int index = 0;
       if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
         index = TTP->getIndex();
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 1c1f6e30ab7b83..92415d49ee7a49 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3575,7 +3575,15 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
     unsigned Index = SugaredBuilder.size();
     if (Index >= TemplateParams->size())
       return TemplateDeductionResult::SubstitutionFailure;
+
     Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
+    Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
+    Info.SecondArg = TemplateArgument(
+        dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
+            ->getType());
+    Info.SuppliedType = TemplateArgument(
+        ExplicitTemplateArgs[Index].getSourceExpression()->getType());
+
     return TemplateDeductionResult::InvalidExplicitArguments;
   }
 

>From e3a60c1f0adbf1801d51ab4d7834469349c0382a Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 14 Jan 2025 11:41:17 -0500
Subject: [PATCH 02/27] Improved safety, added some rt checks

---
 clang/lib/Sema/SemaTemplateDeduction.cpp | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 92415d49ee7a49..521e0da3ef2f92 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -766,6 +766,12 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
 
   return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
 }
+// Helper function to make template argument
+static TemplateArgument makeTemplateArgument(Decl *D) {
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+    return TemplateArgument(NTTP->getType());
+  return TemplateArgument();
+}
 
 /// A pack that we're currently deducing.
 struct clang::DeducedPack {
@@ -3578,11 +3584,19 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
 
     Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
     Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
-    Info.SecondArg = TemplateArgument(
-        dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
-            ->getType());
-    Info.SuppliedType = TemplateArgument(
-        ExplicitTemplateArgs[Index].getSourceExpression()->getType());
+    Info.SecondArg = makeTemplateArgument(TemplateParams->getParam(Index));
+    // Info.SecondArg = TemplateArgument(
+    //     dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
+    //         ->getType());
+
+    // NonTypeTemplateParmDecl tmp =
+    // makeTemplateArgument(TemplateParams->getParam(Index)); if(!tmp.isNull()){
+    //   Info.SecondArg = tmp->getType();
+    // }
+    if (ExplicitTemplateArgs[Index].getArgument().getKind() ==
+        TemplateArgument::Expression)
+      Info.SuppliedType = TemplateArgument(
+          ExplicitTemplateArgs[Index].getSourceExpression()->getType());
 
     return TemplateDeductionResult::InvalidExplicitArguments;
   }

>From 86d44be78faaac1439977ea0ae2f8a213ca28aa3 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Wed, 15 Jan 2025 16:51:10 -0500
Subject: [PATCH 03/27] Fixed error message formatting

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1456f34538bcc0..0afba2ad681319 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4871,8 +4871,8 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
 def note_ovl_candidate_explicit_arg_mismatch_named : Note<
-    "template argument deduction/substitution failed:" 
-    "error: could not convert '%0' from %1 to %2">;
+    "candidate template ignored: invalid explicitly-specified argument "
+    "could not convert '%0' from %1 to %2">;
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
 def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<

>From 9c1210d7a711a5324a10cba8af770028244cf34d Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 20 Jan 2025 15:49:02 -0500
Subject: [PATCH 04/27] Update logic and tests

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  18 ++-
 clang/lib/Sema/SemaOverload.cpp               | 133 ++++++++++++++++--
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  46 ++++--
 clang/test/CXX/drs/cwg2xx.cpp                 |   6 +-
 clang/test/CXX/expr/expr.const/p3-0x.cpp      |   2 +-
 clang/test/SemaCXX/nullptr-98.cpp             |   2 +-
 .../test/SemaTemplate/overload-candidates.cpp |   4 +-
 .../SemaTemplate/temp_arg_nontype_cxx11.cpp   |   2 +-
 8 files changed, 180 insertions(+), 33 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0afba2ad681319..a6110d14564e83 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4870,9 +4870,25 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
+
 def note_ovl_candidate_explicit_arg_mismatch_named : Note<
     "candidate template ignored: invalid explicitly-specified argument "
-    "could not convert '%0' from %1 to %2">;
+    "for template parameter %0: ">;
+
+def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
+    "candidate template ignored: invalid explicitly-specified argument "
+    "for template parameter %0: "
+    "could not convert '%1' from %2 to %4 '%3' (expected a %4, but got '%1')">;
+
+def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_sp : Note<
+    "candidate template ignored: invalid explicitly-specified argument "
+    "for template parameter %0: "
+    "could not convert '%1' from %2 to %3">;
+def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_nsp : Note<
+    "candidate template ignored: invalid explicitly-specified argument "
+    "for template parameter %0: "
+    "expected constant of type %1 got type %2">;
+
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
 def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6c437a52be21db..e1e5bdd268ef49 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -902,7 +902,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return TemplateParameter();
-
+  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Incomplete:
     return TemplateParameter::getFromOpaqueValue(Data);
 
@@ -11641,10 +11641,27 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
                                  unsigned NumArgs,
                                  bool TakingCandidateAddress) {
   TemplateParameter Param = DeductionFailure.getTemplateParameter();
+  int form;
   NamedDecl *ParamD;
-  (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
-  (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
-  (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+  TemplateTypeParmDecl *TTPD;
+  NonTypeTemplateParmDecl *NTTPD;
+  TemplateTemplateParmDecl *TTempPD;
+  if ((ParamD = Param.dyn_cast<TemplateTypeParmDecl *>())) {
+    llvm::dbgs() << "case 1" << '\n';
+    TTPD = cast<TemplateTypeParmDecl>(ParamD);
+    form = 1;
+  } else if ((ParamD = Param.dyn_cast<NonTypeTemplateParmDecl *>())) {
+    llvm::dbgs() << "case 2" << '\n';
+    NTTPD = cast<NonTypeTemplateParmDecl>(ParamD);
+    form = 2;
+  } else if ((ParamD = Param.dyn_cast<TemplateTemplateParmDecl *>())) {
+    llvm::dbgs() << "case 3" << '\n';
+    TTempPD = cast<TemplateTemplateParmDecl>(ParamD);
+    form = 3;
+  } else {
+    llvm::dbgs() << "case 0" << '\n';
+    form = 0;
+  }
 
   switch (DeductionFailure.getResult()) {
   case TemplateDeductionResult::Success:
@@ -11747,15 +11764,108 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
     return;
   }
 
-  case TemplateDeductionResult::InvalidExplicitArguments:
+  case TemplateDeductionResult::InvalidExplicitArguments: {
     assert(ParamD && "no parameter found for invalid explicit arguments");
+
     if (ParamD->getDeclName()) {
-      auto FirstArg = *DeductionFailure.getFirstArg();
-      auto SecondArg = *DeductionFailure.getSecondArg();
-      auto SuppliedType = *DeductionFailure.getSuppliedType();
-      S.Diag(Templated->getLocation(),
-             diag::note_ovl_candidate_explicit_arg_mismatch_named)
-          << FirstArg << SuppliedType << SecondArg;
+      TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
+      std::string SecondArg = ParamD->getNameAsString();
+      TemplateArgument SuppliedType = *DeductionFailure.getSuppliedType();
+      // llvm::dbgs() << ParamD->getNameAsString() << '\n';
+      // llvm::dbgs() << ParamD->getDeclName().getAsString() << '\n';
+      // llvm::dbgs() << ParamD->getQualifiedNameAsString() << '\n';
+      // llvm::dbgs() << ParamD->getUnderlyingDecl()->getNameAsString() << '\n';
+      // llvm::dbgs() << NTTPD->getType() << '\n';
+      // llvm::dbgs() << '\n';
+      // FirstArg.dump();
+      // llvm::dbgs() << '\n';
+      // SuppliedType.dump();
+      // llvm::dbgs() << '\n';
+      // llvm::dbgs() << SecondArg << '\n';
+      switch (form) {
+
+      // TemplateTypeParmDecl
+      case 1: {
+        // could not convert '42' from 'int' to TypeParam T
+        assert(TTPD);
+        TTPD->dump();
+        if (TTPD->wasDeclaredWithTypename())
+          S.Diag(Templated->getLocation(),
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
+              << ParamD->getDeclName() << FirstArg << SuppliedType << SecondArg
+              << "type";
+        else {
+          // TODO write tests for type constrained classes
+          if (auto *constraint = TTPD->getTypeConstraint())
+            S.Diag(Templated->getLocation(),
+                   diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
+                << ParamD->getDeclName() << FirstArg << SuppliedType
+                << SecondArg << "valid type-constrained class";
+          else
+            S.Diag(Templated->getLocation(),
+                   diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
+                << ParamD->getDeclName() << FirstArg << SuppliedType
+                << SecondArg << "class";
+        }
+        break;
+      }
+      // NonTypeTemplateParmDecl
+      case 2: {
+        assert(NTTPD);
+        if (SuppliedType.isNull()) {
+          // Expected constant of type 'int', got type 'int'
+          S.Diag(Templated->getLocation(),
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_nsp)
+              << ParamD->getDeclName() << FirstArg << NTTPD->getType();
+        } else {
+          // Could not convert A from B to C
+          S.Diag(Templated->getLocation(),
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_sp)
+              << ParamD->getDeclName() << FirstArg << SuppliedType
+              << NTTPD->getType();
+        }
+        break;
+      }
+      case 3: {
+        assert(TTempPD);
+        // FirstArg.dump();
+        // llvm::dbgs() << SecondArg << '\n' << SuppliedType.isNull() << '\n';
+        // llvm::dbgs() << TTempPD->getDefaultArgument().getTypeSourceInfo() <<
+        // '\n';
+
+        // expected a template of type 'template<class> class T', got
+        // 'template<class T1, class T2> struct InvalidTemplate'
+
+        S.Diag(Templated->getLocation(),
+               diag::note_ovl_candidate_explicit_arg_mismatch_named)
+            << ParamD->getDeclName();
+        break;
+      }
+      default:
+        llvm_unreachable("unexpected case");
+      }
+
+      // auto SecondArg = *DeductionFailure.getSecondArg();
+
+      // S.Diag(Templated->getLocation(),
+      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
+      //     << FirstArg << SuppliedType << SecondArg;
+      // if(SecondArg.isNull()){
+      //   S.Diag(Templated->getLocation(),
+      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
+      //     << FirstArg << SuppliedType << ParamD->getDeclName();
+      // }
+      // else if(SuppliedType.isNull()){
+      //   S.Diag(Templated->getLocation(),
+      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
+      //     << FirstArg << "SuppliedTypeNull" << SecondArg;
+      // }
+      // else{
+      //   S.Diag(Templated->getLocation(),
+      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
+      //     << FirstArg << SuppliedType << SecondArg;
+      // }
+
     } else {
       int index = 0;
       if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
@@ -11771,6 +11881,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
     }
     MaybeEmitInheritedConstructorNote(S, Found);
     return;
+  }
 
   case TemplateDeductionResult::ConstraintsNotSatisfied: {
     // Format the template argument list into the argument string.
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 521e0da3ef2f92..d36d8b7fb250f5 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -768,8 +768,12 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
 }
 // Helper function to make template argument
 static TemplateArgument makeTemplateArgument(Decl *D) {
-  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(
+          D)) // I in template<int I, typename T>
     return TemplateArgument(NTTP->getType());
+  // if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D)) // T in
+  // template<int I, typename T>
+  //   return TemplateArgument(TTP);
   return TemplateArgument();
 }
 
@@ -3582,21 +3586,37 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
     if (Index >= TemplateParams->size())
       return TemplateDeductionResult::SubstitutionFailure;
 
+    /*
+
+      template<int I, typename T>  //TemplateParams
+      void get(const T&);
+
+      void test_get(void *ptr) {
+        get<int>(ptr);             //TemplateArgs
+      }
+    */
     Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
     Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
     Info.SecondArg = makeTemplateArgument(TemplateParams->getParam(Index));
-    // Info.SecondArg = TemplateArgument(
-    //     dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(Index))
-    //         ->getType());
-
-    // NonTypeTemplateParmDecl tmp =
-    // makeTemplateArgument(TemplateParams->getParam(Index)); if(!tmp.isNull()){
-    //   Info.SecondArg = tmp->getType();
-    // }
-    if (ExplicitTemplateArgs[Index].getArgument().getKind() ==
-        TemplateArgument::Expression)
-      Info.SuppliedType = TemplateArgument(
-          ExplicitTemplateArgs[Index].getSourceExpression()->getType());
+    // FunctionTemplate->dump();
+    // Info.SuppliedType = makeTemplateArgument(TemplateParams->getParam(1));
+    // llvm::dbgs() << TemplateParams->getParam(1) << '\n' <<
+    // TemplateParams->getParam(1)->getNameAsString(); llvm::dbgs() <<
+    // TemplateParams->size() << ExplicitTemplateArgs.size() <<
+    // ParamTypes.size() << Deduced.size() << DeducedArgs.size() << "\n";
+
+    switch (ExplicitTemplateArgs[Index].getArgument().getKind()) {
+    case TemplateArgument::Expression:
+      Info.SuppliedType =
+          ExplicitTemplateArgs[Index].getSourceExpression()->getType();
+      break;
+    case TemplateArgument::Type:
+      Info.SuppliedType =
+          TemplateArgument(); // ExplicitTemplateArgs[Index].getArgument();
+      break;
+    default:
+      break;
+    }
 
     return TemplateDeductionResult::InvalidExplicitArguments;
   }
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 0d644bae783828..08180c70faad63 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -649,15 +649,15 @@ namespace cwg241 { // cwg241: 9
     A::g<3>(b);
     C::f<3>(b);
     // expected-error at -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 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': could not convert '3' from 'int' to class 'T' (expected a class, but got '3')}}
     C::g<3>(b);
     // expected-error at -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 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': could not convert '3' from 'int' to class 'T' (expected a class, but got '3')}}
     using C::f;
     using C::g;
     f<3>(b);
     // expected-error at -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 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': could not convert '3' from 'int' to class 'T' (expected a class, but got '3')}}
     //   expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
     g<3>(b);
   }
diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp
index 5bd70c5250b598..c8e96ef963e5f8 100644
--- a/clang/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -105,7 +105,7 @@ 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': could not convert '&S::operator int' from 'int (S::*)() const' to 'bool'}}
 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/SemaCXX/nullptr-98.cpp b/clang/test/SemaCXX/nullptr-98.cpp
index 306b2033e45688..fbbceb90d1d9fc 100644
--- a/clang/test/SemaCXX/nullptr-98.cpp
+++ b/clang/test/SemaCXX/nullptr-98.cpp
@@ -1,4 +1,4 @@
 // RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
 // expected-no-diagnostics
 void f(void *);
-void g() { f(__nullptr); }
+void g() { f(__nullptr); }
\ No newline at end of file
diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp
index de998d74f9af60..abfd896a611ba4 100644
--- a/clang/test/SemaTemplate/overload-candidates.cpp
+++ b/clang/test/SemaTemplate/overload-candidates.cpp
@@ -17,7 +17,7 @@ void test_dyn_cast(int* ptr) {
 }
 
 template<int I, typename T> 
-  void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I'}}
+  void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I': expected constant of type 'int' got type 'int'}}
 template<template<class T> class, typename T> 
   void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 
@@ -163,4 +163,4 @@ namespace PR15673 {
            CONCEPT_REQUIRES_(some_passing_trait<T>::value && some_trait<T>::value)>
   void rangesv3(); // expected-note{{candidate template ignored: requirement 'some_trait<int>::value' was not satisfied [with T = int, x = 42]}}
   void test_rangesv3() { rangesv3<int>(); } // expected-error{{no matching function for call to 'rangesv3'}}
-}
+}
\ No newline at end of file
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 5752cbac0291d6..50ae078867534b 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -43,7 +43,7 @@ void TempFunc() {}
 
 void Useage() {
   //expected-error at +2 {{no matching function}}
-  //expected-note at -4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b'}}
+  //expected-note at -4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b': could not convert '-1' from 'int' to 'unsigned int'}}
   TempFunc<1, -1, 1>();
 }
 }

>From 4aca9d7247380f945757044aeddd906a04d75f6e Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 20 Jan 2025 18:55:31 -0500
Subject: [PATCH 05/27] Cleaned up code, removed suppliedType

---
 clang/include/clang/Sema/TemplateDeduction.h |   5 -
 clang/lib/Sema/SemaOverload.cpp              | 134 +++----------------
 clang/lib/Sema/SemaTemplateDeduction.cpp     |  42 +-----
 3 files changed, 23 insertions(+), 158 deletions(-)

diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index 9edd3724cf53cd..28b014fd84e4b3 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -250,9 +250,6 @@ class TemplateDeductionInfo {
   /// \brief The constraint satisfaction details resulting from the associated
   /// constraints satisfaction tests.
   ConstraintSatisfaction AssociatedConstraintsSatisfaction;
-
-  /// \brief Type supplied by user for deduction
-  TemplateArgument SuppliedType;
 };
 
 } // namespace sema
@@ -303,8 +300,6 @@ struct DeductionFailureInfo {
   TemplateDeductionResult getResult() const {
     return static_cast<TemplateDeductionResult>(Result);
   }
-
-  const TemplateArgument *getSuppliedType();
 };
 
 /// TemplateSpecCandidate - This is a generalization of OverloadCandidate
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index e1e5bdd268ef49..e1fed0e9c9e9e4 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -723,10 +723,6 @@ namespace {
     unsigned CallArgIndex;
   };
 
-  struct DFIParamWithArgumentsAndSuppliedType : DFIArguments {
-    TemplateParameter Param;
-    TemplateArgument SuppliedType;
-  };
   // Structure used by DeductionFailureInfo to store information about
   // unsatisfied constraints.
   struct CNSInfo {
@@ -795,12 +791,10 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     break;
   }
   case TemplateDeductionResult::InvalidExplicitArguments: {
-    DFIParamWithArgumentsAndSuppliedType *Saved =
-        new (Context) DFIParamWithArgumentsAndSuppliedType;
+    DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
     Saved->Param = Info.Param;
     Saved->FirstArg = Info.FirstArg;
     Saved->SecondArg = Info.SecondArg;
-    Saved->SuppliedType = Info.SuppliedType;
     Result.Data = Saved;
     break;
   }
@@ -902,10 +896,8 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return TemplateParameter();
-  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Incomplete:
     return TemplateParameter::getFromOpaqueValue(Data);
-
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
   case TemplateDeductionResult::InvalidExplicitArguments:
@@ -937,7 +929,6 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
     return nullptr;
-
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested:
     return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
@@ -957,16 +948,6 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
   return nullptr;
 }
 
-const TemplateArgument *DeductionFailureInfo::getSuppliedType() {
-  switch (static_cast<TemplateDeductionResult>(Result)) {
-  case TemplateDeductionResult::InvalidExplicitArguments:
-    return &static_cast<DFIParamWithArgumentsAndSuppliedType *>(Data)
-                ->SuppliedType;
-  default:
-    return nullptr;
-  }
-}
-
 const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   switch (static_cast<TemplateDeductionResult>(Result)) {
   case TemplateDeductionResult::Success:
@@ -975,14 +956,11 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   case TemplateDeductionResult::Incomplete:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::SubstitutionFailure:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return nullptr;
-  // case TemplateDeductionResult::InvalidExplicitArguments: //move back up
-  // there^^
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
   case TemplateDeductionResult::InvalidExplicitArguments:
@@ -1010,13 +988,11 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::SubstitutionFailure:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return nullptr;
-
   case TemplateDeductionResult::Inconsistent:
   case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Underqualified:
@@ -11641,27 +11617,11 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
                                  unsigned NumArgs,
                                  bool TakingCandidateAddress) {
   TemplateParameter Param = DeductionFailure.getTemplateParameter();
-  int form;
   NamedDecl *ParamD;
-  TemplateTypeParmDecl *TTPD;
-  NonTypeTemplateParmDecl *NTTPD;
-  TemplateTemplateParmDecl *TTempPD;
-  if ((ParamD = Param.dyn_cast<TemplateTypeParmDecl *>())) {
-    llvm::dbgs() << "case 1" << '\n';
-    TTPD = cast<TemplateTypeParmDecl>(ParamD);
-    form = 1;
-  } else if ((ParamD = Param.dyn_cast<NonTypeTemplateParmDecl *>())) {
-    llvm::dbgs() << "case 2" << '\n';
-    NTTPD = cast<NonTypeTemplateParmDecl>(ParamD);
-    form = 2;
-  } else if ((ParamD = Param.dyn_cast<TemplateTemplateParmDecl *>())) {
-    llvm::dbgs() << "case 3" << '\n';
-    TTempPD = cast<TemplateTemplateParmDecl>(ParamD);
-    form = 3;
-  } else {
-    llvm::dbgs() << "case 0" << '\n';
-    form = 0;
-  }
+
+  (ParamD = Param.dyn_cast<TemplateTypeParmDecl *>()) ||
+      (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl *>()) ||
+      (ParamD = Param.dyn_cast<TemplateTemplateParmDecl *>());
 
   switch (DeductionFailure.getResult()) {
   case TemplateDeductionResult::Success:
@@ -11769,50 +11729,30 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
 
     if (ParamD->getDeclName()) {
       TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
-      std::string SecondArg = ParamD->getNameAsString();
-      TemplateArgument SuppliedType = *DeductionFailure.getSuppliedType();
-      // llvm::dbgs() << ParamD->getNameAsString() << '\n';
-      // llvm::dbgs() << ParamD->getDeclName().getAsString() << '\n';
-      // llvm::dbgs() << ParamD->getQualifiedNameAsString() << '\n';
-      // llvm::dbgs() << ParamD->getUnderlyingDecl()->getNameAsString() << '\n';
-      // llvm::dbgs() << NTTPD->getType() << '\n';
-      // llvm::dbgs() << '\n';
-      // FirstArg.dump();
-      // llvm::dbgs() << '\n';
-      // SuppliedType.dump();
-      // llvm::dbgs() << '\n';
-      // llvm::dbgs() << SecondArg << '\n';
-      switch (form) {
-
-      // TemplateTypeParmDecl
-      case 1: {
-        // could not convert '42' from 'int' to TypeParam T
-        assert(TTPD);
-        TTPD->dump();
+      std::string ParamName = ParamD->getNameAsString();
+      TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
+
+      if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
         if (TTPD->wasDeclaredWithTypename())
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-              << ParamD->getDeclName() << FirstArg << SuppliedType << SecondArg
+              << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
               << "type";
         else {
           // TODO write tests for type constrained classes
           if (auto *constraint = TTPD->getTypeConstraint())
             S.Diag(Templated->getLocation(),
                    diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-                << ParamD->getDeclName() << FirstArg << SuppliedType
-                << SecondArg << "valid type-constrained class";
+                << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
+                << "valid type-constrained class";
           else
             S.Diag(Templated->getLocation(),
                    diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-                << ParamD->getDeclName() << FirstArg << SuppliedType
-                << SecondArg << "class";
+                << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
+                << "class";
         }
-        break;
-      }
-      // NonTypeTemplateParmDecl
-      case 2: {
-        assert(NTTPD);
-        if (SuppliedType.isNull()) {
+      } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
+        if (SecondArg.isNull()) {
           // Expected constant of type 'int', got type 'int'
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_nsp)
@@ -11821,51 +11761,15 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
           // Could not convert A from B to C
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_sp)
-              << ParamD->getDeclName() << FirstArg << SuppliedType
+              << ParamD->getDeclName() << FirstArg << SecondArg
               << NTTPD->getType();
         }
-        break;
-      }
-      case 3: {
-        assert(TTempPD);
-        // FirstArg.dump();
-        // llvm::dbgs() << SecondArg << '\n' << SuppliedType.isNull() << '\n';
-        // llvm::dbgs() << TTempPD->getDefaultArgument().getTypeSourceInfo() <<
-        // '\n';
-
-        // expected a template of type 'template<class> class T', got
-        // 'template<class T1, class T2> struct InvalidTemplate'
-
+      } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
         S.Diag(Templated->getLocation(),
                diag::note_ovl_candidate_explicit_arg_mismatch_named)
             << ParamD->getDeclName();
-        break;
-      }
-      default:
+      } else
         llvm_unreachable("unexpected case");
-      }
-
-      // auto SecondArg = *DeductionFailure.getSecondArg();
-
-      // S.Diag(Templated->getLocation(),
-      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
-      //     << FirstArg << SuppliedType << SecondArg;
-      // if(SecondArg.isNull()){
-      //   S.Diag(Templated->getLocation(),
-      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
-      //     << FirstArg << SuppliedType << ParamD->getDeclName();
-      // }
-      // else if(SuppliedType.isNull()){
-      //   S.Diag(Templated->getLocation(),
-      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
-      //     << FirstArg << "SuppliedTypeNull" << SecondArg;
-      // }
-      // else{
-      //   S.Diag(Templated->getLocation(),
-      //        diag::note_ovl_candidate_explicit_arg_mismatch_named)
-      //     << FirstArg << SuppliedType << SecondArg;
-      // }
-
     } else {
       int index = 0;
       if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index d36d8b7fb250f5..806da4ba240c49 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -766,16 +766,6 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
 
   return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
 }
-// Helper function to make template argument
-static TemplateArgument makeTemplateArgument(Decl *D) {
-  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(
-          D)) // I in template<int I, typename T>
-    return TemplateArgument(NTTP->getType());
-  // if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D)) // T in
-  // template<int I, typename T>
-  //   return TemplateArgument(TTP);
-  return TemplateArgument();
-}
 
 /// A pack that we're currently deducing.
 struct clang::DeducedPack {
@@ -3586,37 +3576,13 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
     if (Index >= TemplateParams->size())
       return TemplateDeductionResult::SubstitutionFailure;
 
-    /*
-
-      template<int I, typename T>  //TemplateParams
-      void get(const T&);
-
-      void test_get(void *ptr) {
-        get<int>(ptr);             //TemplateArgs
-      }
-    */
     Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
     Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
-    Info.SecondArg = makeTemplateArgument(TemplateParams->getParam(Index));
-    // FunctionTemplate->dump();
-    // Info.SuppliedType = makeTemplateArgument(TemplateParams->getParam(1));
-    // llvm::dbgs() << TemplateParams->getParam(1) << '\n' <<
-    // TemplateParams->getParam(1)->getNameAsString(); llvm::dbgs() <<
-    // TemplateParams->size() << ExplicitTemplateArgs.size() <<
-    // ParamTypes.size() << Deduced.size() << DeducedArgs.size() << "\n";
-
-    switch (ExplicitTemplateArgs[Index].getArgument().getKind()) {
-    case TemplateArgument::Expression:
-      Info.SuppliedType =
+    Info.SecondArg = TemplateArgument();
+    if (ExplicitTemplateArgs[Index].getArgument().getKind() ==
+        TemplateArgument::Expression)
+      Info.SecondArg =
           ExplicitTemplateArgs[Index].getSourceExpression()->getType();
-      break;
-    case TemplateArgument::Type:
-      Info.SuppliedType =
-          TemplateArgument(); // ExplicitTemplateArgs[Index].getArgument();
-      break;
-    default:
-      break;
-    }
 
     return TemplateDeductionResult::InvalidExplicitArguments;
   }

>From 9c10aa953002243cf9ffbb9f99fd0ec94e503169 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 20 Jan 2025 18:58:39 -0500
Subject: [PATCH 06/27] removed newlines diagnosticSemKinds.td

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a6110d14564e83..ea1013f7ef7b7e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4870,16 +4870,13 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
-
 def note_ovl_candidate_explicit_arg_mismatch_named : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: ">;
-
 def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
     "could not convert '%1' from %2 to %4 '%3' (expected a %4, but got '%1')">;
-
 def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_sp : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
@@ -4888,7 +4885,6 @@ def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_nsp : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
     "expected constant of type %1 got type %2">;
-
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
 def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<

>From 35d79a7e6224684f9d6e81b839ac0ab1947cfc4e Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <47676355+AidanGoldfarb at users.noreply.github.com>
Date: Mon, 20 Jan 2025 19:03:00 -0500
Subject: [PATCH 07/27] Update clang/lib/Sema/SemaOverload.cpp

Co-authored-by: Justin Fargnoli <jfargnoli at nvidia.com>
---
 clang/lib/Sema/SemaOverload.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index e1fed0e9c9e9e4..61564ed4f1ca20 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11618,7 +11618,6 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
                                  bool TakingCandidateAddress) {
   TemplateParameter Param = DeductionFailure.getTemplateParameter();
   NamedDecl *ParamD;
-
   (ParamD = Param.dyn_cast<TemplateTypeParmDecl *>()) ||
       (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl *>()) ||
       (ParamD = Param.dyn_cast<TemplateTemplateParmDecl *>());

>From babe495ac378a49440b1fa2de80b0cea4d026b3e Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <47676355+AidanGoldfarb at users.noreply.github.com>
Date: Mon, 20 Jan 2025 19:03:10 -0500
Subject: [PATCH 08/27] Update clang/lib/Sema/SemaOverload.cpp

Co-authored-by: Justin Fargnoli <jfargnoli at nvidia.com>
---
 clang/lib/Sema/SemaOverload.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 61564ed4f1ca20..63b63c85d1d84c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11725,7 +11725,6 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
 
   case TemplateDeductionResult::InvalidExplicitArguments: {
     assert(ParamD && "no parameter found for invalid explicit arguments");
-
     if (ParamD->getDeclName()) {
       TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
       std::string ParamName = ParamD->getNameAsString();

>From 7984368fbf47884f378bb6af80c03b3dc5a495c1 Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <47676355+AidanGoldfarb at users.noreply.github.com>
Date: Mon, 20 Jan 2025 19:03:33 -0500
Subject: [PATCH 09/27] Update clang/test/SemaCXX/nullptr-98.cpp

Co-authored-by: Justin Fargnoli <jfargnoli at nvidia.com>
---
 clang/test/SemaCXX/nullptr-98.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaCXX/nullptr-98.cpp b/clang/test/SemaCXX/nullptr-98.cpp
index fbbceb90d1d9fc..306b2033e45688 100644
--- a/clang/test/SemaCXX/nullptr-98.cpp
+++ b/clang/test/SemaCXX/nullptr-98.cpp
@@ -1,4 +1,4 @@
 // RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
 // expected-no-diagnostics
 void f(void *);
-void g() { f(__nullptr); }
\ No newline at end of file
+void g() { f(__nullptr); }

>From 13607304b7a608a01e39de1d5ad8abba27d1a752 Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <47676355+AidanGoldfarb at users.noreply.github.com>
Date: Mon, 20 Jan 2025 19:04:40 -0500
Subject: [PATCH 10/27] Apply suggestions from code review

Co-authored-by: Justin Fargnoli <jfargnoli at nvidia.com>
---
 clang/lib/Sema/SemaOverload.cpp                 | 3 ---
 clang/lib/Sema/SemaTemplateDeduction.cpp        | 1 -
 clang/test/SemaTemplate/overload-candidates.cpp | 2 +-
 3 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 63b63c85d1d84c..aa64f631dbe44d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -753,7 +753,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     break;
 
   case TemplateDeductionResult::Incomplete:
-    // case TemplateDeductionResult::InvalidExplicitArguments:
     Result.Data = Info.Param.getOpaqueValue();
     break;
   case TemplateDeductionResult::DeducedMismatch:
@@ -780,7 +779,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
   case TemplateDeductionResult::IncompletePack:
     // FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
   case TemplateDeductionResult::Inconsistent:
-
   case TemplateDeductionResult::Underqualified: {
     // FIXME: Should allocate from normal heap so that we can free this later.
     DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
@@ -834,7 +832,6 @@ void DeductionFailureInfo::Destroy() {
   case TemplateDeductionResult::Incomplete:
   case TemplateDeductionResult::TooManyArguments:
   case TemplateDeductionResult::TooFewArguments:
-  // case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
     break;
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 806da4ba240c49..18f82ef0b936a0 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3575,7 +3575,6 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
     unsigned Index = SugaredBuilder.size();
     if (Index >= TemplateParams->size())
       return TemplateDeductionResult::SubstitutionFailure;
-
     Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
     Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
     Info.SecondArg = TemplateArgument();
diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp
index abfd896a611ba4..bc181c7942402c 100644
--- a/clang/test/SemaTemplate/overload-candidates.cpp
+++ b/clang/test/SemaTemplate/overload-candidates.cpp
@@ -163,4 +163,4 @@ namespace PR15673 {
            CONCEPT_REQUIRES_(some_passing_trait<T>::value && some_trait<T>::value)>
   void rangesv3(); // expected-note{{candidate template ignored: requirement 'some_trait<int>::value' was not satisfied [with T = int, x = 42]}}
   void test_rangesv3() { rangesv3<int>(); } // expected-error{{no matching function for call to 'rangesv3'}}
-}
\ No newline at end of file
+}

>From ffdc1b6fce146748107a7828f0f02920e68c163b Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 20 Jan 2025 19:10:10 -0500
Subject: [PATCH 11/27] some newlines removed

---
 clang/lib/Sema/SemaOverload.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index aa64f631dbe44d..5400f4cdcfc934 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -715,14 +715,12 @@ namespace {
   struct DFIParamWithArguments : DFIArguments {
     TemplateParameter Param;
   };
-
   // Structure used by DeductionFailureInfo to store template argument
   // information and the index of the problematic call argument.
   struct DFIDeducedMismatchArgs : DFIArguments {
     TemplateArgumentList *TemplateArgs;
     unsigned CallArgIndex;
   };
-
   // Structure used by DeductionFailureInfo to store information about
   // unsatisfied constraints.
   struct CNSInfo {
@@ -738,10 +736,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
                                 TemplateDeductionResult TDK,
                                 TemplateDeductionInfo &Info) {
   DeductionFailureInfo Result;
-
   Result.Result = static_cast<unsigned>(TDK);
   Result.HasDiagnostic = false;
-
   switch (TDK) {
   case TemplateDeductionResult::Invalid:
   case TemplateDeductionResult::InstantiationDepth:

>From b22f2390fe2bbde7daab9cd72ceb73d20be265a6 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 20 Jan 2025 19:12:41 -0500
Subject: [PATCH 12/27] some newlines added

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

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5400f4cdcfc934..13be184267c1cc 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -889,8 +889,10 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return TemplateParameter();
+
   case TemplateDeductionResult::Incomplete:
     return TemplateParameter::getFromOpaqueValue(Data);
+
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
   case TemplateDeductionResult::InvalidExplicitArguments:
@@ -922,6 +924,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
   case TemplateDeductionResult::CUDATargetMismatch:
   case TemplateDeductionResult::NonDependentConversionFailure:
     return nullptr;
+
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested:
     return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
@@ -954,6 +957,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return nullptr;
+
   case TemplateDeductionResult::IncompletePack:
   case TemplateDeductionResult::Inconsistent:
   case TemplateDeductionResult::InvalidExplicitArguments:
@@ -986,6 +990,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
   case TemplateDeductionResult::NonDependentConversionFailure:
   case TemplateDeductionResult::ConstraintsNotSatisfied:
     return nullptr;
+
   case TemplateDeductionResult::Inconsistent:
   case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::Underqualified:

>From 170825651d8bf1897f592e21b5ab9a2ab488b033 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 20 Jan 2025 19:15:14 -0500
Subject: [PATCH 13/27] a newline added

---
 clang/lib/Sema/SemaOverload.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 13be184267c1cc..6c14535176886f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -751,6 +751,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
   case TemplateDeductionResult::Incomplete:
     Result.Data = Info.Param.getOpaqueValue();
     break;
+
   case TemplateDeductionResult::DeducedMismatch:
   case TemplateDeductionResult::DeducedMismatchNested: {
     // FIXME: Should allocate from normal heap so that we can free this later.

>From 256d22b0cf7c81279030b1f3da936efc29824298 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 21 Jan 2025 10:38:46 -0500
Subject: [PATCH 14/27] more cleanup

---
 clang/lib/Sema/SemaOverload.cpp | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6c14535176886f..856b2fe5c7b4bc 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -773,6 +773,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     break;
   }
 
+  case TemplateDeductionResult::InvalidExplicitArguments:
   case TemplateDeductionResult::IncompletePack:
     // FIXME: It's slightly wasteful to allocate two TemplateArguments for this.
   case TemplateDeductionResult::Inconsistent:
@@ -785,14 +786,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
     Result.Data = Saved;
     break;
   }
-  case TemplateDeductionResult::InvalidExplicitArguments: {
-    DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
-    Saved->Param = Info.Param;
-    Saved->FirstArg = Info.FirstArg;
-    Saved->SecondArg = Info.SecondArg;
-    Result.Data = Saved;
-    break;
-  }
 
   case TemplateDeductionResult::SubstitutionFailure:
     Result.Data = Info.takeSugared();

>From 8a7ce10e282af2104c78635a4d1cd1f7c7ff72b4 Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <agoldfa7 at u.rochester.edu>
Date: Wed, 22 Jan 2025 14:59:54 -0500
Subject: [PATCH 15/27] Apply suggestions from code review

Co-authored-by: Justin Fargnoli <jfargnoli at nvidia.com>
---
 clang/lib/Sema/SemaOverload.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 856b2fe5c7b4bc..559d4c26b7fdc4 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11610,10 +11610,9 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
                                  bool TakingCandidateAddress) {
   TemplateParameter Param = DeductionFailure.getTemplateParameter();
   NamedDecl *ParamD;
-  (ParamD = Param.dyn_cast<TemplateTypeParmDecl *>()) ||
-      (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl *>()) ||
-      (ParamD = Param.dyn_cast<TemplateTemplateParmDecl *>());
-
+  (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
+  (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
+  (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
   switch (DeductionFailure.getResult()) {
   case TemplateDeductionResult::Success:
     llvm_unreachable(

>From 29491ec15180f650fabc6d2a7a79aa5dc625d6ad Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Wed, 22 Jan 2025 18:58:51 -0500
Subject: [PATCH 16/27] remove unneeded diag

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  4 ++--
 clang/lib/Sema/SemaOverload.cpp                  | 13 +++++--------
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ea1013f7ef7b7e..a30caebc8fb2fd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4877,11 +4877,11 @@ def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
     "could not convert '%1' from %2 to %4 '%3' (expected a %4, but got '%1')">;
-def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_sp : Note<
+def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
     "could not convert '%1' from %2 to %3">;
-def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_nsp : Note<
+def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_a : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
     "expected constant of type %1 got type %2">;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 559d4c26b7fdc4..ef6d820ed6a6bc 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11728,12 +11728,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
               << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
               << "type";
         else {
-          // TODO write tests for type constrained classes
-          if (auto *constraint = TTPD->getTypeConstraint())
-            S.Diag(Templated->getLocation(),
-                   diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-                << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
-                << "valid type-constrained class";
+          if (TTPD->getTypeConstraint())
+            llvm_unreachable("ill-formed program");
           else
             S.Diag(Templated->getLocation(),
                    diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
@@ -11744,16 +11740,17 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
         if (SecondArg.isNull()) {
           // Expected constant of type 'int', got type 'int'
           S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_nsp)
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_a)
               << ParamD->getDeclName() << FirstArg << NTTPD->getType();
         } else {
           // Could not convert A from B to C
           S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_sp)
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b)
               << ParamD->getDeclName() << FirstArg << SecondArg
               << NTTPD->getType();
         }
       } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
+        TTempPD->dump();
         S.Diag(Templated->getLocation(),
                diag::note_ovl_candidate_explicit_arg_mismatch_named)
             << ParamD->getDeclName();

>From 11fb7499e762bde2fb7fc792cd11256401028b3a Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Fri, 24 Jan 2025 13:32:18 -0500
Subject: [PATCH 17/27] cleaned up code

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 ++--
 clang/lib/Sema/SemaOverload.cpp               | 21 +++++++++----------
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  1 -
 3 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a30caebc8fb2fd..3016677fc33a75 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4870,9 +4870,9 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
-def note_ovl_candidate_explicit_arg_mismatch_named : Note<
+def note_ovl_candidate_explicit_arg_mismatch_named_temptemppd : Note<
     "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0: ">;
+    "for template parameter %0">;
 def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index ef6d820ed6a6bc..f8987306fac780 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11728,31 +11728,30 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
               << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
               << "type";
         else {
-          if (TTPD->getTypeConstraint())
-            llvm_unreachable("ill-formed program");
-          else
-            S.Diag(Templated->getLocation(),
-                   diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-                << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
-                << "class";
+          // Concept satisfied but not modeled => ill-formed
+          assert(!TTPD->getTypeConstraint() &&
+                 "Concept satisfied but not modeled");
+
+          S.Diag(Templated->getLocation(),
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
+              << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
+              << "class";
         }
       } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
         if (SecondArg.isNull()) {
-          // Expected constant of type 'int', got type 'int'
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_a)
               << ParamD->getDeclName() << FirstArg << NTTPD->getType();
         } else {
-          // Could not convert A from B to C
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b)
               << ParamD->getDeclName() << FirstArg << SecondArg
               << NTTPD->getType();
         }
       } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
-        TTempPD->dump();
+        // FIXME: Emit a better message here
         S.Diag(Templated->getLocation(),
-               diag::note_ovl_candidate_explicit_arg_mismatch_named)
+               diag::note_ovl_candidate_explicit_arg_mismatch_named_temptemppd)
             << ParamD->getDeclName();
       } else
         llvm_unreachable("unexpected case");
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 18f82ef0b936a0..74e9c45b4e8c42 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3577,7 +3577,6 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
       return TemplateDeductionResult::SubstitutionFailure;
     Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
     Info.FirstArg = ExplicitTemplateArgs[Index].getArgument();
-    Info.SecondArg = TemplateArgument();
     if (ExplicitTemplateArgs[Index].getArgument().getKind() ==
         TemplateArgument::Expression)
       Info.SecondArg =

>From 2acdb18a3c1b93f893d94a6c473473923d6c76cb Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 28 Jan 2025 15:03:15 -0500
Subject: [PATCH 18/27] simplified ttpd case and updated test

---
 .../include/clang/Basic/DiagnosticSemaKinds.td |  2 +-
 clang/lib/Sema/SemaOverload.cpp                | 18 +++---------------
 clang/test/CXX/drs/cwg2xx.cpp                  |  6 +++---
 3 files changed, 7 insertions(+), 19 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3016677fc33a75..b80e67a4b8f071 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4876,7 +4876,7 @@ def note_ovl_candidate_explicit_arg_mismatch_named_temptemppd : Note<
 def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
-    "could not convert '%1' from %2 to %4 '%3' (expected a %4, but got '%1')">;
+    "expectd a type, but got value '%1' (of type %2)">;
 def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index f8987306fac780..82fa00ca014f7f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11722,21 +11722,9 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
       TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
 
       if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
-        if (TTPD->wasDeclaredWithTypename())
-          S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-              << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
-              << "type";
-        else {
-          // Concept satisfied but not modeled => ill-formed
-          assert(!TTPD->getTypeConstraint() &&
-                 "Concept satisfied but not modeled");
-
-          S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-              << ParamD->getDeclName() << FirstArg << SecondArg << ParamName
-              << "class";
-        }
+        S.Diag(Templated->getLocation(),
+               diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
+            << ParamD->getDeclName() << FirstArg << SecondArg;
       } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
         if (SecondArg.isNull()) {
           S.Diag(Templated->getLocation(),
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 08180c70faad63..28fb9d86d4ff9c 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -649,15 +649,15 @@ namespace cwg241 { // cwg241: 9
     A::g<3>(b);
     C::f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': could not convert '3' from 'int' to class 'T' (expected a class, but got '3')}}
+    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expectd a type, but got value '3' (of type 'int')}}
     C::g<3>(b);
     // expected-error at -1 {{no matching function for call to 'g'}}
-    //   expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': could not convert '3' from 'int' to class 'T' (expected a class, but got '3')}}
+    //   expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expectd a type, but got value '3' (of type 'int')}}
     using C::f;
     using C::g;
     f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': could not convert '3' from 'int' to class 'T' (expected a class, but got '3')}}
+    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expectd a type, but got value '3' (of type 'int')}}
     //   expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
     g<3>(b);
   }

>From b36ff68a3f1404052080c3c0066c1c6a78ca924d Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <agoldfa7 at u.rochester.edu>
Date: Tue, 28 Jan 2025 15:24:19 -0500
Subject: [PATCH 19/27] Fixed type

Co-authored-by: Matheus Izvekov <mizvekov at gmail.com>
---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b80e67a4b8f071..b0d1298d095322 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4876,7 +4876,7 @@ def note_ovl_candidate_explicit_arg_mismatch_named_temptemppd : Note<
 def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "
-    "expectd a type, but got value '%1' (of type %2)">;
+    "expected a type, but got value '%1' (of type %2)">;
 def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for template parameter %0: "

>From 6db7a7a98d0c378efa89cc33a5bde6ba74103522 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 28 Jan 2025 15:25:46 -0500
Subject: [PATCH 20/27] typo fixed

---
 clang/test/CXX/drs/cwg2xx.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 28fb9d86d4ff9c..2373b769b91722 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -649,15 +649,15 @@ namespace cwg241 { // cwg241: 9
     A::g<3>(b);
     C::f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expectd a type, but got value '3' (of type 'int')}}
+    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expected a type, but got value '3' (of type 'int')}}
     C::g<3>(b);
     // expected-error at -1 {{no matching function for call to 'g'}}
-    //   expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expectd a type, but got value '3' (of type 'int')}}
+    //   expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expected a type, but got value '3' (of type 'int')}}
     using C::f;
     using C::g;
     f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expectd a type, but got value '3' (of type 'int')}}
+    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for template parameter 'T': expected a type, but got value '3' (of type 'int')}}
     //   expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
     g<3>(b);
   }

>From fc7fec12efc2a1cf951922fa6f49a572a6021295 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 28 Jan 2025 20:49:39 -0500
Subject: [PATCH 21/27] merged diag defs into one

---
 .../clang/Basic/DiagnosticSemaKinds.td        | 20 ++++++-------------
 clang/lib/Sema/SemaOverload.cpp               | 17 ++++++++--------
 .../test/SemaTemplate/overload-candidates.cpp |  2 +-
 3 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b0d1298d095322..19af6eb6c6aaf9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4870,21 +4870,13 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
-def note_ovl_candidate_explicit_arg_mismatch_named_temptemppd : Note<
+def note_ovl_candidate_explicit_arg_mismatch_named : Note<
     "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0">;
-def note_ovl_candidate_explicit_arg_mismatch_named_ttpd : Note<
-    "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0: "
-    "expected a type, but got value '%1' (of type %2)">;
-def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b : Note<
-    "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0: "
-    "could not convert '%1' from %2 to %3">;
-def note_ovl_candidate_explicit_arg_mismatch_named_nttpd_a : Note<
-    "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0: "
-    "expected constant of type %1 got type %2">;
+    "for template parameter %1%select{"
+    "|: expected a type, but got value '%2' (of type %3)"
+    "|: could not convert '%2' from %3 to %4"
+    "|: expected constant of type %2 but got type %3"
+    "|}0">;
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
 def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 82fa00ca014f7f..486e050aede16e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11723,24 +11723,25 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
 
       if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
         S.Diag(Templated->getLocation(),
-               diag::note_ovl_candidate_explicit_arg_mismatch_named_ttpd)
-            << ParamD->getDeclName() << FirstArg << SecondArg;
+               diag::note_ovl_candidate_explicit_arg_mismatch_named)
+            << 1 << ParamD->getDeclName() << FirstArg << SecondArg;
+
       } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
         if (SecondArg.isNull()) {
           S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_a)
-              << ParamD->getDeclName() << FirstArg << NTTPD->getType();
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named)
+              << 3 << ParamD->getDeclName() << NTTPD->getType() << FirstArg;
         } else {
           S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named_nttpd_b)
-              << ParamD->getDeclName() << FirstArg << SecondArg
+                 diag::note_ovl_candidate_explicit_arg_mismatch_named)
+              << 2 << ParamD->getDeclName() << FirstArg << SecondArg
               << NTTPD->getType();
         }
       } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
         // FIXME: Emit a better message here
         S.Diag(Templated->getLocation(),
-               diag::note_ovl_candidate_explicit_arg_mismatch_named_temptemppd)
-            << ParamD->getDeclName();
+               diag::note_ovl_candidate_explicit_arg_mismatch_named)
+            << 4 << ParamD->getDeclName();
       } else
         llvm_unreachable("unexpected case");
     } else {
diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp
index bc181c7942402c..98ed02d8e92930 100644
--- a/clang/test/SemaTemplate/overload-candidates.cpp
+++ b/clang/test/SemaTemplate/overload-candidates.cpp
@@ -17,7 +17,7 @@ void test_dyn_cast(int* ptr) {
 }
 
 template<int I, typename T> 
-  void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I': expected constant of type 'int' got type 'int'}}
+  void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I': expected constant of type 'int' but got type 'int'}}
 template<template<class T> class, typename T> 
   void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 

>From b578b870dd6d65a945b63a84fcd5c93c1ee0daba Mon Sep 17 00:00:00 2001
From: Aidan Goldfarb <agoldfa7 at u.rochester.edu>
Date: Wed, 29 Jan 2025 10:29:07 -0500
Subject: [PATCH 22/27] Apply suggestions from code review

Co-authored-by: Matheus Izvekov <mizvekov at gmail.com>
---
 clang/lib/Sema/SemaOverload.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 486e050aede16e..5b2f7734f81c27 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11718,7 +11718,6 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
     assert(ParamD && "no parameter found for invalid explicit arguments");
     if (ParamD->getDeclName()) {
       TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
-      std::string ParamName = ParamD->getNameAsString();
       TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
 
       if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
@@ -11743,7 +11742,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
                diag::note_ovl_candidate_explicit_arg_mismatch_named)
             << 4 << ParamD->getDeclName();
       } else
-        llvm_unreachable("unexpected case");
+        llvm_unreachable("unexpected param decl kind");
     } else {
       int index = 0;
       if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))

>From 340627d442e7bf221463ad5a66845006d1a68cef Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Wed, 29 Jan 2025 14:18:37 -0500
Subject: [PATCH 23/27] reverted caret change, pipped sourceRange instead

---
 clang/lib/Sema/SemaOverload.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5b2f7734f81c27..a386dcdf253555 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11723,24 +11723,26 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
       if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
         S.Diag(Templated->getLocation(),
                diag::note_ovl_candidate_explicit_arg_mismatch_named)
-            << 1 << ParamD->getDeclName() << FirstArg << SecondArg;
+            << 1 << ParamD->getDeclName() << FirstArg << SecondArg
+            << TTPD->getSourceRange();
 
       } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
         if (SecondArg.isNull()) {
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named)
-              << 3 << ParamD->getDeclName() << NTTPD->getType() << FirstArg;
+              << 3 << ParamD->getDeclName() << NTTPD->getType() << FirstArg
+              << NTTPD->getSourceRange();
         } else {
           S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_explicit_arg_mismatch_named)
               << 2 << ParamD->getDeclName() << FirstArg << SecondArg
-              << NTTPD->getType();
+              << NTTPD->getType() << NTTPD->getSourceRange();
         }
       } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
         // FIXME: Emit a better message here
         S.Diag(Templated->getLocation(),
                diag::note_ovl_candidate_explicit_arg_mismatch_named)
-            << 4 << ParamD->getDeclName();
+            << 4 << ParamD->getDeclName() << TTempPD->getSourceRange();
       } else
         llvm_unreachable("unexpected param decl kind");
     } else {

>From 64584bc2650f8e1f42f3c8e7a8e2b664880b78a7 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Thu, 30 Jan 2025 12:12:51 -0500
Subject: [PATCH 24/27] refactor. split diag into two notes, updated tests.

---
 .../clang/Basic/DiagnosticSemaKinds.td        | 16 ++---
 clang/lib/Sema/SemaOverload.cpp               | 71 ++++++++-----------
 clang/test/CXX/drs/cwg2xx.cpp                 |  9 ++-
 clang/test/CXX/expr/expr.const/p3-0x.cpp      |  4 +-
 .../test/SemaTemplate/overload-candidates.cpp |  4 +-
 .../SemaTemplate/temp_arg_nontype_cxx11.cpp   |  5 +-
 6 files changed, 53 insertions(+), 56 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 19af6eb6c6aaf9..0c533b76e3b5c2 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4870,18 +4870,16 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
-def note_ovl_candidate_explicit_arg_mismatch_named : Note<
+def note_ovl_candidate_explicit_arg_mismatch : Note<
     "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %1%select{"
-    "|: expected a type, but got value '%2' (of type %3)"
-    "|: could not convert '%2' from %3 to %4"
-    "|: expected constant of type %2 but got type %3"
-    "|}0">;
+    "for %ordinal0 template parameter">;
+def note_ovl_candidate_explicit_arg_mismatch_detail : Note<
+    "%select{"
+    "|: expected a type, but got value '%1'"
+    "|: expected constant of type %3 but got type %1"
+    "|: could not convert '%1' from %2 to %3}0">;
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
-def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
-    "candidate template ignored: invalid explicitly-specified argument "
-    "for %ordinal0 template parameter">;
 def note_ovl_candidate_instantiation_depth : Note<
     "candidate template ignored: substitution exceeded maximum template "
     "instantiation depth">;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a386dcdf253555..5d050da63570de 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11716,48 +11716,39 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
 
   case TemplateDeductionResult::InvalidExplicitArguments: {
     assert(ParamD && "no parameter found for invalid explicit arguments");
-    if (ParamD->getDeclName()) {
-      TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
-      TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
-
-      if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
-        S.Diag(Templated->getLocation(),
-               diag::note_ovl_candidate_explicit_arg_mismatch_named)
-            << 1 << ParamD->getDeclName() << FirstArg << SecondArg
-            << TTPD->getSourceRange();
-
-      } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
-        if (SecondArg.isNull()) {
-          S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named)
-              << 3 << ParamD->getDeclName() << NTTPD->getType() << FirstArg
-              << NTTPD->getSourceRange();
-        } else {
-          S.Diag(Templated->getLocation(),
-                 diag::note_ovl_candidate_explicit_arg_mismatch_named)
-              << 2 << ParamD->getDeclName() << FirstArg << SecondArg
-              << NTTPD->getType() << NTTPD->getSourceRange();
-        }
-      } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
-        // FIXME: Emit a better message here
-        S.Diag(Templated->getLocation(),
-               diag::note_ovl_candidate_explicit_arg_mismatch_named)
-            << 4 << ParamD->getDeclName() << TTempPD->getSourceRange();
-      } else
-        llvm_unreachable("unexpected param decl kind");
-    } else {
-      int index = 0;
-      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
-        index = TTP->getIndex();
-      else if (NonTypeTemplateParmDecl *NTTP
-                                  = dyn_cast<NonTypeTemplateParmDecl>(ParamD))
-        index = NTTP->getIndex();
+    int Which = 0;
+    int Index = 0;
+    TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
+    TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
+    QualType Type;
+    SourceRange SrcRange;
+
+    if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
+      Which = 1;
+      Index = TTPD->getIndex();
+      SrcRange = TTPD->getSourceRange();
+    } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
+      if (SecondArg.isNull())
+        Which = 2;
       else
-        index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
+        Which = 3;
+      Index = NTTPD->getIndex();
+      Type = NTTPD->getType();
+      SrcRange = NTTPD->getSourceRange();
+    } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
+      Which = 4;
+      Index = TTempPD->getIndex();
+      SrcRange = TTempPD->getSourceRange();
+    } else
+      llvm_unreachable("unexpected param decl kind");
+
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_explicit_arg_mismatch)
+        << (Index + 1) << SrcRange;
+    if (ParamD->getDeclName() && Which != 4)
       S.Diag(Templated->getLocation(),
-             diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
-          << (index + 1);
-    }
+             diag::note_ovl_candidate_explicit_arg_mismatch_detail)
+          << Which << FirstArg << SecondArg << Type;
     MaybeEmitInheritedConstructorNote(S, Found);
     return;
   }
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 2373b769b91722..b7e72df9d1ee35 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -649,15 +649,18 @@ namespace cwg241 { // cwg241: 9
     A::g<3>(b);
     C::f<3>(b);
     // expected-error at -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 a type, but got value '3' (of type 'int')}}
+    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
+    //   expected-note@#cwg241-C-f {{expected a type, but got value '3'}}
     C::g<3>(b);
     // expected-error at -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 a type, but got value '3' (of type 'int')}}
+    //   expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
+    //   expected-note@#cwg241-C-g {{expected a type, but got value '3'}}
     using C::f;
     using C::g;
     f<3>(b);
     // expected-error at -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 a type, but got value '3' (of type 'int')}}
+    //   expected-note@#cwg241-C-f {{andidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
+    //   expected-note@#cwg241-C-f {{expected a type, but got value '3'}}
     //   expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
     g<3>(b);
   }
diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp
index c8e96ef963e5f8..cc96c93920330e 100644
--- a/clang/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -105,7 +105,9 @@ void c() {
     break;
   }
 }
-template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B': could not convert '&S::operator int' from 'int (S::*)() const' to 'bool'}}
+template <bool B> int f() { return B; } // #f-bool-int
+// expected-note@#f-bool-int {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
+// expected-note@#f-bool-int {{could not convert '&S::operator int' from 'int (S::*)() const' to 'bool'}}
 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/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp
index 98ed02d8e92930..fa3598b8071029 100644
--- a/clang/test/SemaTemplate/overload-candidates.cpp
+++ b/clang/test/SemaTemplate/overload-candidates.cpp
@@ -17,7 +17,9 @@ void test_dyn_cast(int* ptr) {
 }
 
 template<int I, typename T> 
-  void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I': expected constant of type 'int' but got type 'int'}}
+  void get(const T&); // #get-int-typename
+  // expected-note@#get-int-typename {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
+  // expected-note@#get-int-typename {{expected constant of type 'int' but got type 'int'}}
 template<template<class T> class, typename T> 
   void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 50ae078867534b..e470802aee64b3 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 at +2 {{no matching function}}
-  //expected-note at -4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b': could not convert '-1' from 'int' to 'unsigned int'}}
+  //expected-error at +3 {{no matching function}}
+  //expected-note at -4 {{candidate template ignored: invalid explicitly-specified argument for 2nd template parameter}}
+  //expected-note at -5 {{could not convert '-1' from 'int' to 'unsigned int'}}
   TempFunc<1, -1, 1>();
 }
 }

>From 1468562a02661632b928a08a48acaf6951e3af4a Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 4 Feb 2025 12:19:37 -0500
Subject: [PATCH 25/27] const expr hack

---
 .../clang/Basic/DiagnosticSemaKinds.td        | 10 +--
 clang/lib/AST/ExprConstant.cpp                | 13 +++-
 clang/lib/Sema/SemaOverload.cpp               | 65 ++++++++++---------
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  4 ++
 clang/test/AST/ByteCode/builtin-align-cxx.cpp |  4 +-
 clang/test/AST/ByteCode/cxx20.cpp             |  4 +-
 .../basic.namespace/namespace.udecl/p12.cpp   |  8 +--
 clang/test/CXX/temp/temp.param/p8-cxx20.cpp   | 16 ++---
 clang/test/SemaCXX/builtin-align-cxx.cpp      |  4 +-
 clang/test/SemaCXX/calling-conv-compat.cpp    |  5 +-
 .../constexpr-function-recovery-crash.cpp     |  2 +-
 clang/test/SemaCXX/cxx2a-template-lambdas.cpp |  3 +-
 clang/test/SemaCXX/typo-correction.cpp        |  2 +-
 clang/test/SemaTemplate/cwg2398.cpp           |  3 +-
 14 files changed, 82 insertions(+), 61 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0c533b76e3b5c2..2006bf667e7486 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4870,14 +4870,16 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
-def note_ovl_candidate_explicit_arg_mismatch : Note<
-    "candidate template ignored: invalid explicitly-specified argument "
-    "for %ordinal0 template parameter">;
+
 def note_ovl_candidate_explicit_arg_mismatch_detail : Note<
+    "candidate template ignored: invalid explicitly-specified argument"
     "%select{"
     "|: expected a type, but got value '%1'"
     "|: expected constant of type %3 but got type %1"
-    "|: could not convert '%1' from %2 to %3}0">;
+    "|: could not convert '%1' from %2 to %3"
+    "| for %ordinal4 template parameter"
+    "|: expr is not a valid const expr in the expected context}0">;
+
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
 def note_ovl_candidate_instantiation_depth : Note<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 2e680d1569f60f..8530f4ccb06a16 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16814,8 +16814,17 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
       (!EvaluateDestruction(Ctx, Base, Result.Val, T, getBeginLoc(), Result,
                             true) ||
        Result.HasSideEffects)) {
-    // FIXME: Prefix a note to indicate that the problem is lack of constant
-    // destruction.
+
+    // FIXME: err_constexpr_var_requires_const_destruction?
+    PartialDiagnostic PD(diag::err_constexpr_var_requires_const_destruction,
+                         const_cast<ASTContext &>(Ctx).getDiagAllocator());
+    std::string ExprStr;
+    llvm::raw_string_ostream OS(ExprStr);
+    this->printPretty(OS, nullptr, PrintingPolicy(Ctx.getLangOpts()));
+    PD << ExprStr;
+    SourceLocation Loc = this->getBeginLoc();
+    Result.Diag->insert(Result.Diag->begin(), PartialDiagnosticAt(Loc, PD));
+
     return false;
   }
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5d050da63570de..3964656ffda0aa 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11716,39 +11716,46 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
 
   case TemplateDeductionResult::InvalidExplicitArguments: {
     assert(ParamD && "no parameter found for invalid explicit arguments");
-    int Which = 0;
-    int Index = 0;
     TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
     TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
-    QualType Type;
-    SourceRange SrcRange;
-
-    if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
-      Which = 1;
-      Index = TTPD->getIndex();
-      SrcRange = TTPD->getSourceRange();
-    } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
-      if (SecondArg.isNull())
-        Which = 2;
-      else
-        Which = 3;
-      Index = NTTPD->getIndex();
-      Type = NTTPD->getType();
-      SrcRange = NTTPD->getSourceRange();
-    } else if (auto *TTempPD = dyn_cast<TemplateTemplateParmDecl>(ParamD)) {
-      Which = 4;
-      Index = TTempPD->getIndex();
-      SrcRange = TTempPD->getSourceRange();
-    } else
-      llvm_unreachable("unexpected param decl kind");
 
+    auto TupleResult = [&]() -> std::tuple<int, int, QualType> {
+      switch (ParamD->getKind()) {
+      case Decl::TemplateTypeParm: {
+        auto *TTPD = cast<TemplateTypeParmDecl>(ParamD);
+        return {1, TTPD->getIndex(), QualType()};
+      }
+      case Decl::NonTypeTemplateParm: {
+        auto *NTTPD = cast<NonTypeTemplateParmDecl>(ParamD);
+        if (SecondArg.isNull())
+          return {2, NTTPD->getIndex(), NTTPD->getType()};
+        else {
+          // FIXME: this is a hack, we should do this in SemaTempalteDeduction
+          // or even ExprConstant. Perhaps an InvalidExplicitArguments error
+          // is not what we want
+          QualType qt = NTTPD->getType();
+          if (qt.getCanonicalType() !=
+              SecondArg.getAsType().getCanonicalType()) {
+            return {3, NTTPD->getIndex(), NTTPD->getType()};
+          } else {
+            return {5, NTTPD->getIndex(), NTTPD->getType()};
+          }
+        }
+      }
+      case Decl::TemplateTemplateParm: {
+        auto *TTempPD = cast<TemplateTemplateParmDecl>(ParamD);
+        return {4, TTempPD->getIndex(), QualType()};
+      }
+      default:
+        llvm_unreachable("unexpected param decl kind");
+      }
+    };
+    auto [Which, Index, Type] = TupleResult();
+    S.NoteTemplateParameterLocation(*ParamD);
     S.Diag(Templated->getLocation(),
-           diag::note_ovl_candidate_explicit_arg_mismatch)
-        << (Index + 1) << SrcRange;
-    if (ParamD->getDeclName() && Which != 4)
-      S.Diag(Templated->getLocation(),
-             diag::note_ovl_candidate_explicit_arg_mismatch_detail)
-          << Which << FirstArg << SecondArg << Type;
+           diag::note_ovl_candidate_explicit_arg_mismatch_detail)
+        << Which << FirstArg << SecondArg << Type << (Index + 1);
+
     MaybeEmitInheritedConstructorNote(S, Found);
     return;
   }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 74e9c45b4e8c42..10abe58b0c944b 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3572,6 +3572,10 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
                                 SugaredBuilder, CanonicalBuilder,
                                 /*UpdateArgsWithConversions=*/false) ||
       Trap.hasErrorOccurred()) {
+
+    // FIXME: decide if ill formed const expr or regular
+    // InvalidExplicitArguments?
+
     unsigned Index = SugaredBuilder.size();
     if (Index >= TemplateParams->size())
       return TemplateDeductionResult::SubstitutionFailure;
diff --git a/clang/test/AST/ByteCode/builtin-align-cxx.cpp b/clang/test/AST/ByteCode/builtin-align-cxx.cpp
index a1edf307d6c479..7a554f55af49cd 100644
--- a/clang/test/AST/ByteCode/builtin-align-cxx.cpp
+++ b/clang/test/AST/ByteCode/builtin-align-cxx.cpp
@@ -3,8 +3,8 @@
 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=ref,both
 
 // 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}}
+template <typename a, a b> // both-note{{template parameter is declared here}}
+void *c(void *d) { // both-note{{candidate template ignored: invalid explicitly-specified argument: could not convert 'foo' from 'x' to 'a'}}
   return __builtin_align_down(d, b);
 }
 
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index 268362ceff635b..4581ea08faaab3 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -750,8 +750,8 @@ namespace FailingDestructor {
         throw "oh no";
     }
   };
-  template<D d>
-  void f() {} // both-note {{invalid explicitly-specified argument}}
+  template<D d> // both-note{{template parameter is declared here}}
+  void f() {} // both-note{{candidate template ignored: invalid explicitly-specified argument: expr is not a valid const expr in the expected context}}
 
   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 f12e0083fb0c95..53f395e060e4ea 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,21 @@ 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{{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument: expected constant of type 'int' but got type 'int'}}
   };
 
   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{{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument: expected constant of type 'int' but got type 'int'}}
     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{{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument: expected a type, but got value '0'}}
   };
 
   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{{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument: expected a type, but got value '0'}}
     using Base::foo;
   };
 
diff --git a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
index a3478c06696614..a5f9614422f3c8 100644
--- a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
+++ b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
@@ -35,12 +35,12 @@ namespace ConstDestruction {
 
     constexpr ~D() {
       if (!can_destroy)
-        throw "oh no"; // expected-note {{subexpression not valid}}
+        throw "oh no";
     }
   };
 
-  template<D d>
-  void f() {} // expected-note 2{{invalid explicitly-specified argument}}
+  template<D d> // expected-note 2{{template parameter is declared here}}
+  void f() {} // expected-note 2{{candidate template ignored: invalid explicitly-specified argument: expr is not a valid const expr in the expected context}}
 
   void g() {
     f<D{0, true}>();
@@ -48,18 +48,14 @@ namespace ConstDestruction {
   }
 
   // We can SFINAE on constant destruction.
-  template<typename T> auto h(T t) -> decltype(f<T{1, false}>());
-  template<typename T> auto h(T t) -> decltype(f<T{1, true}>());
+  // template<typename T> auto h(T t) -> decltype(f<T{1, false}>());
+  // template<typename T> auto h(T t) -> decltype(f<T{1, true}>());
 
   void i() {
-    h(D());
+    //h(D());
     // Ensure we don't cache an invalid template argument after we've already
     // seen it in a SFINAE context.
     f<D{1, false}>(); // expected-error {{no matching function}}
     f<D{1, true}>();
   }
-
-  template<D d> struct Z {};
-  Z<D{2, true}> z1;
-  Z<D{2, false}> z2; // expected-error {{non-type template argument is not a constant expression}} expected-note-re {{in call to '{{.*}}.~D()'}}
 }
diff --git a/clang/test/SemaCXX/builtin-align-cxx.cpp b/clang/test/SemaCXX/builtin-align-cxx.cpp
index d18bc2bf665511..2392e94141ab2b 100644
--- a/clang/test/SemaCXX/builtin-align-cxx.cpp
+++ b/clang/test/SemaCXX/builtin-align-cxx.cpp
@@ -2,8 +2,8 @@
 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 -o - %s -fsyntax-only -verify
 
 // 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}}
+template <typename a, a b> // expected-note{{template parameter is declared here}}
+void *c(void *d) { // expected-note{{candidate template ignored: invalid explicitly-specified argument: could not convert 'foo' from 'x' to 'a'}}
   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 5a51e34b1478c6..fcb2eafea73c95 100644
--- a/clang/test/SemaCXX/calling-conv-compat.cpp
+++ b/clang/test/SemaCXX/calling-conv-compat.cpp
@@ -424,7 +424,8 @@ namespace D50526 {
   template<typename T, T (__stdcall f)()> void g();
   void h() { g<void, h>(); }
 #if !_M_X64
-  // expected-error at -2 {{no matching function for call to}}
-  // expected-note at -4 {{invalid explicitly-specified argument}}
+  // expected-note at -3 {{template parameter is declared here}}
+  // expected-error at -3 {{no matching function for call to}}
+  // expected-note at -5 {{candidate template ignored: invalid explicitly-specified argument: could not convert 'h' from 'void ()' to 'T (*)() __attribute__((stdcall))}}
 #endif
 }
diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
index 90ee7892b2fc2e..542967aa952fc6 100644
--- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -60,7 +60,7 @@ 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 {{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument: expr is not a valid const expr in the expected context}}
   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 00ba291fbd1981..b4389b7183a6d9 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -45,7 +45,8 @@ template<typename T>
 constexpr T outer() {
   // FIXME: The C++11 error seems wrong
   return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}}  \
-                                                                expected-note {{candidate template ignored}}    \
+                                                                expected-note {{template parameter is declared here}} \
+                                                                expected-note {{candidate template ignored: invalid explicitly-specified argument: could not convert '123' from 'int' to 'int *'}}    \
         cxx11-note {{non-literal type '<dependent type>' cannot be used in a constant expression}} \
         cxx14-note {{non-literal type}}
 }
diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp
index 45f42c42603589..ef1fa9b18479dd 100644
--- a/clang/test/SemaCXX/typo-correction.cpp
+++ b/clang/test/SemaCXX/typo-correction.cpp
@@ -613,7 +613,7 @@ int bar() {
 }
 
 namespace testIncludeTypeInTemplateArgument {
-template <typename T, typename U>
+template <typename T, typename U> // expected-note {{template parameter is declared here}}
 void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}}
 
 class AddObservation {}; // expected-note {{declared here}}
diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp
index 6dc7af6ea17899..5a041a13679e9f 100644
--- a/clang/test/SemaTemplate/cwg2398.cpp
+++ b/clang/test/SemaTemplate/cwg2398.cpp
@@ -138,7 +138,8 @@ namespace ttp_defaults {
 
   template <template <class T2> class TT2> void f(A<TT2>);
   // new-note at -1 {{explicit instantiation candidate}}
-  // old-note at -2 {{invalid explicitly-specified argument for template parameter 'TT2'}}
+  // old-note at -2 {{template parameter is declared here}}
+  // old-note at -3 {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 
   // FIXME: The default arguments on the TTP are not available during partial ordering.
   template <template <class T3, class T4 = float> class TT3> void f(A<TT3>) {};

>From 6c4804193d1951d1dd4fa52642d114c2d13ffa0d Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Tue, 4 Feb 2025 14:16:11 -0500
Subject: [PATCH 26/27] revert tests, will be changed later. One should still
 fail

---
 clang/test/CXX/drs/cwg2xx.cpp                 | 19 ++++++++++---------
 clang/test/CXX/drs/cwg3xx.cpp                 |  6 ++++--
 clang/test/CXX/expr/expr.const/p3-0x.cpp      |  4 ++--
 .../test/CXX/temp/temp.res/temp.local/p1.cpp  |  4 ++--
 clang/test/Modules/cxx-templates.cpp          |  2 ++
 .../test/SemaTemplate/overload-candidates.cpp |  9 ++++-----
 .../SemaTemplate/temp_arg_nontype_cxx11.cpp   |  4 ++--
 7 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index b7e72df9d1ee35..c74096cc9383d6 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -645,23 +645,23 @@ namespace cwg241 { // cwg241: 9
     // cxx98-17-error at -1 {{use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension}}
     A::f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
+    // expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
     A::g<3>(b);
     C::f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-C-f {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
-    //   expected-note@#cwg241-C-f {{expected a type, but got value '3'}}
+    // expected-note@#cwg241-C-f 2{{template parameter is declared here}}
+    // expected-note@#cwg241-C-f 2{{candidate template ignored: invalid explicitly-specified argument: expected a type, but got value '3}}
+
     C::g<3>(b);
     // expected-error at -1 {{no matching function for call to 'g'}}
-    //   expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
-    //   expected-note@#cwg241-C-g {{expected a type, but got value '3'}}
+    // expected-note@#cwg241-C-g {{template parameter is declared here}}
+    // expected-note@#cwg241-C-g {{candidate template ignored: invalid explicitly-specified argument: expected a type, but got value '3}}
+
     using C::f;
     using C::g;
     f<3>(b);
     // expected-error at -1 {{no matching function for call to 'f'}}
-    //   expected-note@#cwg241-C-f {{andidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
-    //   expected-note@#cwg241-C-f {{expected a type, but got value '3'}}
-    //   expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
+    // expected-note@#cwg241-A-f {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
     g<3>(b);
   }
 } // namespace cwg241
@@ -954,7 +954,8 @@ namespace cwg258 { // cwg258: 2.8
   int &w = b.f(0);
   int &x = b.g<int>(0);
   // expected-error at -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 parameter is declared here}}
+  // expected-note@#cwg258-B-g {{candidate template ignored: invalid explicitly-specified argument: expected constant of type 'int' but got type 'int'}}
   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 b5e07a66bb4eda..634f9bf35d36a8 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -981,8 +981,10 @@ namespace cwg354 { // cwg354: 3.1 c++11
   int b0 = both<0>();
   int b1 = both<(int*)0>();
   // cxx98-error at -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 {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
+  // cxx98-note@#cwg354-both-int-ptr {{template parameter is declared here}}
+  // cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: invalid explicitly-specified argument: could not convert '(int *)0' from 'int *' to 'int'}}
+  // cxx98-note@#cwg354-both-int {{template parameter is declared here}}
+  // cxx98-note@#cwg354-both-int {{candidate template ignored: invalid explicitly-specified argument: could not convert '(int *)0' from 'int *' to 'int'}}
 
   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 cc96c93920330e..6e54acb44e2d44 100644
--- a/clang/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -106,8 +106,8 @@ void c() {
   }
 }
 template <bool B> int f() { return B; } // #f-bool-int
-// expected-note@#f-bool-int {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
-// expected-note@#f-bool-int {{could not convert '&S::operator int' from 'int (S::*)() const' to 'bool'}}
+// expected-note@#f-bool-int {{template parameter is declared here}}
+// expected-note@#f-bool-int {{candidate template ignored: invalid explicitly-specified argument: could not convert '&S::operator int' from 'int (S::*)() const' to 'bool'}}
 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.res/temp.local/p1.cpp b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
index faa85cb5fce300..16c8ca05f39b3c 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,9 @@ 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{{template parameter is declared here}} // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}}
 template<template<typename> class> void use(float&); // expected-note 2{{no known conversion}}
-template<int> void use(char&); // expected-note 2{{invalid explicitly-specified argument}}
+template<int> void use(char&); // expected-note 2{{template parameter is declared here}} // expected-note 2{{invalid explicitly-specified argument}}
 
 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 7b41a0b0bfb2c9..88ac89226e7f10 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -42,10 +42,12 @@ void g() {
   template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
 
   template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function}}
+  // expected-note at Inputs/cxx-templates-a.h:11 {{template parameter is declared here}}
   // expected-note at Inputs/cxx-templates-a.h:11 {{invalid explicitly-specified argument}}
   // expected-note at Inputs/cxx-templates-b.h:11 {{invalid explicitly-specified argument}}
 
   template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
+  // expected-note at Inputs/cxx-templates-b.h:11 {{template parameter is declared here}}
   // expected-note at Inputs/cxx-templates-a.h:11 {{candidate}}
   // expected-note at Inputs/cxx-templates-b.h:11 {{candidate}}
 
diff --git a/clang/test/SemaTemplate/overload-candidates.cpp b/clang/test/SemaTemplate/overload-candidates.cpp
index fa3598b8071029..9d8a6932f6dfca 100644
--- a/clang/test/SemaTemplate/overload-candidates.cpp
+++ b/clang/test/SemaTemplate/overload-candidates.cpp
@@ -16,12 +16,11 @@ 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> 
+template<int I, typename T> // expected-note {{template parameter is declared here}}
   void get(const T&); // #get-int-typename
-  // expected-note@#get-int-typename {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
-  // expected-note@#get-int-typename {{expected constant of type 'int' but got type 'int'}}
-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@#get-int-typename {{candidate template ignored: invalid explicitly-specified argument: expected constant of type 'int' but got type 'int'}}
+template<template<class T> class, typename T> // expected-note {{template parameter is declared here}}
+  void get(const T&); // expected-note {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 
 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 e470802aee64b3..343d168d2560c2 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -43,8 +43,8 @@ void TempFunc() {}
 
 void Useage() {
   //expected-error at +3 {{no matching function}}
-  //expected-note at -4 {{candidate template ignored: invalid explicitly-specified argument for 2nd template parameter}}
-  //expected-note at -5 {{could not convert '-1' from 'int' to 'unsigned int'}}
+  //expected-note at -5 {{template parameter is declared here}}
+  //expected-note at -5 {{candidate template ignored: invalid explicitly-specified argument: could not convert '-1' from 'int' to 'unsigned int'}}
   TempFunc<1, -1, 1>();
 }
 }

>From 199dc79be3ea064ad00b1be8397ef168be2f685f Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Wed, 5 Feb 2025 11:02:13 -0500
Subject: [PATCH 27/27] revert hack/tests. Next commit will clean up error
 messages

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td   |  3 +--
 clang/lib/AST/ExprConstant.cpp                     | 13 ++-----------
 clang/lib/Sema/SemaOverload.cpp                    | 14 +++++++-------
 clang/lib/Sema/SemaTemplateDeduction.cpp           |  3 ---
 clang/test/AST/ByteCode/cxx20.cpp                  |  2 +-
 clang/test/CXX/drs/cwg3xx.cpp                      |  2 +-
 clang/test/CXX/temp/temp.param/p8-cxx20.cpp        |  2 +-
 .../SemaCXX/constexpr-function-recovery-crash.cpp  |  2 +-
 8 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2006bf667e7486..1fa73c761f3791 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4877,8 +4877,7 @@ def note_ovl_candidate_explicit_arg_mismatch_detail : Note<
     "|: expected a type, but got value '%1'"
     "|: expected constant of type %3 but got type %1"
     "|: could not convert '%1' from %2 to %3"
-    "| for %ordinal4 template parameter"
-    "|: expr is not a valid const expr in the expected context}0">;
+    "| for %ordinal4 template parameter}0">;
 
 def note_ovl_candidate_unsatisfied_constraints : Note<
     "candidate template ignored: constraints not satisfied%0">;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8530f4ccb06a16..2e680d1569f60f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16814,17 +16814,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
       (!EvaluateDestruction(Ctx, Base, Result.Val, T, getBeginLoc(), Result,
                             true) ||
        Result.HasSideEffects)) {
-
-    // FIXME: err_constexpr_var_requires_const_destruction?
-    PartialDiagnostic PD(diag::err_constexpr_var_requires_const_destruction,
-                         const_cast<ASTContext &>(Ctx).getDiagAllocator());
-    std::string ExprStr;
-    llvm::raw_string_ostream OS(ExprStr);
-    this->printPretty(OS, nullptr, PrintingPolicy(Ctx.getLangOpts()));
-    PD << ExprStr;
-    SourceLocation Loc = this->getBeginLoc();
-    Result.Diag->insert(Result.Diag->begin(), PartialDiagnosticAt(Loc, PD));
-
+    // FIXME: Prefix a note to indicate that the problem is lack of constant
+    // destruction.
     return false;
   }
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 3964656ffda0aa..899331f151b7a0 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11730,15 +11730,15 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
         if (SecondArg.isNull())
           return {2, NTTPD->getIndex(), NTTPD->getType()};
         else {
-          // FIXME: this is a hack, we should do this in SemaTempalteDeduction
-          // or even ExprConstant. Perhaps an InvalidExplicitArguments error
-          // is not what we want
+          // FIXME: This is a hack. We should emit a better message
+          // for ill-formed const exprs in >=C++20.
           QualType qt = NTTPD->getType();
-          if (qt.getCanonicalType() !=
-              SecondArg.getAsType().getCanonicalType()) {
-            return {3, NTTPD->getIndex(), NTTPD->getType()};
+          if (qt.getCanonicalType() ==
+                  SecondArg.getAsType().getCanonicalType() &&
+              __cplusplus <= 201703) {
+            return {4, NTTPD->getIndex(), NTTPD->getType()};
           } else {
-            return {5, NTTPD->getIndex(), NTTPD->getType()};
+            return {3, NTTPD->getIndex(), NTTPD->getType()};
           }
         }
       }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 10abe58b0c944b..48b4febce89baf 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3573,9 +3573,6 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
                                 /*UpdateArgsWithConversions=*/false) ||
       Trap.hasErrorOccurred()) {
 
-    // FIXME: decide if ill formed const expr or regular
-    // InvalidExplicitArguments?
-
     unsigned Index = SugaredBuilder.size();
     if (Index >= TemplateParams->size())
       return TemplateDeductionResult::SubstitutionFailure;
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index 4581ea08faaab3..dfff819bf84d50 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -751,7 +751,7 @@ namespace FailingDestructor {
     }
   };
   template<D d> // both-note{{template parameter is declared here}}
-  void f() {} // both-note{{candidate template ignored: invalid explicitly-specified argument: expr is not a valid const expr in the expected context}}
+  void f() {} // both-note{{andidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 
   void g() {
     f<D{0, false}>(); // both-error {{no matching function}}
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 634f9bf35d36a8..bf91f745ecb0fa 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -982,7 +982,7 @@ namespace cwg354 { // cwg354: 3.1 c++11
   int b1 = both<(int*)0>();
   // cxx98-error at -1 {{no matching function for call to 'both'}}
   // cxx98-note@#cwg354-both-int-ptr {{template parameter is declared here}}
-  // cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: invalid explicitly-specified argument: could not convert '(int *)0' from 'int *' to 'int'}}
+  // cxx98-note@#cwg354-both-int-ptr {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
   // cxx98-note@#cwg354-both-int {{template parameter is declared here}}
   // cxx98-note@#cwg354-both-int {{candidate template ignored: invalid explicitly-specified argument: could not convert '(int *)0' from 'int *' to 'int'}}
 
diff --git a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
index a5f9614422f3c8..48cf1c874eb2f0 100644
--- a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
+++ b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
@@ -40,7 +40,7 @@ namespace ConstDestruction {
   };
 
   template<D d> // expected-note 2{{template parameter is declared here}}
-  void f() {} // expected-note 2{{candidate template ignored: invalid explicitly-specified argument: expr is not a valid const expr in the expected context}}
+  void f() {} // expected-note 2{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
 
   void g() {
     f<D{0, true}>();
diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
index 542967aa952fc6..34e0d01c150dc9 100644
--- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -60,7 +60,7 @@ constexpr void test8() {
   throw "bad";
 }
 
-template<int x> constexpr int f(int y) { //expected-note {{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument: expr is not a valid const expr in the expected context}}
+template<int x> constexpr int f(int y) { //expected-note {{template parameter is declared here}} // expected-note {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
   return x * y;
 }
 constexpr int test9(int x) {



More information about the cfe-commits mailing list