[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();
----------------
mizvekov wrote:
I would drop the `TupleResult` thing and just immediately invoke and decompose the lambda.
This would be fine for me and you don't need to change, but here is another idea in case you like it, or other people prefer it:
```suggestion
SemaDiagnosticBuilder DB = S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch);
switch (ParamD->getKind()) {
case Decl::TemplateTypeParm:
DB << 1 << 0 << 1 << cast<TemplateTypeParmDecl>(ParamD)->getIndex() << QualType();
break;
...
}
```
And so on. You would need to introduce an extra scope here for 'DB', as it needs to be destroyed for the diagnostic to be emitted, and this needs to happen before we emit any notes.
https://github.com/llvm/llvm-project/pull/122754
More information about the cfe-commits
mailing list