================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits