[clang] [clang][Sema] Improve template argument deduction diagnostic (PR #122754)
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 20 03:38:23 PST 2025
================
@@ -11714,27 +11714,51 @@ 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())
- S.Diag(Templated->getLocation(),
- diag::note_ovl_candidate_explicit_arg_mismatch_named)
- << ParamD->getDeclName();
- 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();
- else
- index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
- S.Diag(Templated->getLocation(),
- diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
- << (index + 1);
- }
+ TemplateArgument FirstArg = *DeductionFailure.getFirstArg();
+ TemplateArgument SecondArg = *DeductionFailure.getSecondArg();
+
+ auto TupleResult = [&]() -> std::tuple<int, int, int, int, QualType> {
+ switch (ParamD->getKind()) {
+ case Decl::TemplateTypeParm: {
+ auto *TTPD = cast<TemplateTypeParmDecl>(ParamD);
+ return {1, 0, 1, TTPD->getIndex(), QualType()};
+ }
+ case Decl::NonTypeTemplateParm: {
+ auto *NTTPD = cast<NonTypeTemplateParmDecl>(ParamD);
+ if (SecondArg.isNull()) {
+ return {1, 1, 0, NTTPD->getIndex(), NTTPD->getType()};
+ } else {
+ // 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, -1, -1, NTTPD->getIndex(), NTTPD->getType()};
+ } else {
+ return {2, -1, -1, NTTPD->getIndex(), NTTPD->getType()};
+ }
+ }
+ }
+ case Decl::TemplateTemplateParm: {
+ auto *TTempPD = cast<TemplateTemplateParmDecl>(ParamD);
+ return {3, -1, -1, TTempPD->getIndex(), QualType()};
+ }
+ default:
+ llvm_unreachable("unexpected param decl kind");
+ }
+ };
+ auto [Which, Provided, Expected, Index, Type] = TupleResult();
+ S.NoteTemplateParameterLocation(*ParamD);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_explicit_arg_mismatch)
+ << Which << Provided << Expected << FirstArg << SecondArg << Type
+ << (Index + 1);
----------------
mizvekov wrote:
```suggestion
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch)
<< Which << Provided << Expected << FirstArg << SecondArg << Type
<< (Index + 1);
S.NoteTemplateParameterLocation(*ParamD);
```
The note must always come after the error, otherwise it becomes attached to whatever diagnostic we emitted previously.
https://github.com/llvm/llvm-project/pull/122754
More information about the cfe-commits
mailing list