|
40 | 40 | #include "llvm/ADT/DenseSet.h" |
41 | 41 | #include "llvm/ADT/STLExtras.h" |
42 | 42 | #include "llvm/ADT/STLForwardCompat.h" |
| 43 | +#include "llvm/ADT/ScopeExit.h" |
43 | 44 | #include "llvm/ADT/SmallPtrSet.h" |
44 | 45 | #include "llvm/ADT/SmallString.h" |
45 | 46 | #include "llvm/ADT/SmallVector.h" |
@@ -11884,6 +11885,46 @@ static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) { |
11884 | 11885 | << (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange()); |
11885 | 11886 | } |
11886 | 11887 |
|
| 11888 | +static void NoteImplicitDeductionGuide(Sema &S, FunctionDecl *Fn) { |
| 11889 | + auto *DG = dyn_cast<CXXDeductionGuideDecl>(Fn); |
| 11890 | + if (!DG) |
| 11891 | + return; |
| 11892 | + TemplateDecl *OriginTemplate = |
| 11893 | + DG->getDeclName().getCXXDeductionGuideTemplate(); |
| 11894 | + // We want to always print synthesized deduction guides for type aliases. |
| 11895 | + // They would retain the explicit bit of the corresponding constructor. |
| 11896 | + if (!(DG->isImplicit() || (OriginTemplate && OriginTemplate->isTypeAlias()))) |
| 11897 | + return; |
| 11898 | + std::string FunctionProto; |
| 11899 | + llvm::raw_string_ostream OS(FunctionProto); |
| 11900 | + FunctionTemplateDecl *Template = DG->getDescribedFunctionTemplate(); |
| 11901 | + if (!Template) { |
| 11902 | + // This also could be an instantiation. Find out the primary template. |
| 11903 | + FunctionDecl *Pattern = |
| 11904 | + DG->getTemplateInstantiationPattern(/*ForDefinition=*/false); |
| 11905 | + if (!Pattern) { |
| 11906 | + // The implicit deduction guide is built on an explicit non-template |
| 11907 | + // deduction guide. Currently, this might be the case only for type |
| 11908 | + // aliases. |
| 11909 | + // FIXME: Add a test once https://github.com/llvm/llvm-project/pull/96686 |
| 11910 | + // gets merged. |
| 11911 | + assert(OriginTemplate->isTypeAlias() && |
| 11912 | + "Non-template implicit deduction guides are only possible for " |
| 11913 | + "type aliases"); |
| 11914 | + DG->print(OS); |
| 11915 | + S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide) |
| 11916 | + << FunctionProto; |
| 11917 | + return; |
| 11918 | + } |
| 11919 | + Template = Pattern->getDescribedFunctionTemplate(); |
| 11920 | + assert(Template && "Cannot find the associated function template of " |
| 11921 | + "CXXDeductionGuideDecl?"); |
| 11922 | + } |
| 11923 | + Template->print(OS); |
| 11924 | + S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide) |
| 11925 | + << FunctionProto; |
| 11926 | +} |
| 11927 | + |
11887 | 11928 | /// Generates a 'note' diagnostic for an overload candidate. We've |
11888 | 11929 | /// already generated a primary error at the call site. |
11889 | 11930 | /// |
@@ -11941,6 +11982,17 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, |
11941 | 11982 | return; |
11942 | 11983 | } |
11943 | 11984 |
|
| 11985 | + // If this is a synthesized deduction guide we're deducing against, add a note |
| 11986 | + // for it. These deduction guides are not explicitly spelled in the source |
| 11987 | + // code, so simply printing a deduction failure note mentioning synthesized |
| 11988 | + // template parameters or pointing to the header of the surrounding RecordDecl |
| 11989 | + // would be confusing. |
| 11990 | + // |
| 11991 | + // We prefer adding such notes at the end of the deduction failure because |
| 11992 | + // duplicate code snippets appearing in the diagnostic would likely become |
| 11993 | + // noisy. |
| 11994 | + auto _ = llvm::make_scope_exit([&] { NoteImplicitDeductionGuide(S, Fn); }); |
| 11995 | + |
11944 | 11996 | switch (Cand->FailureKind) { |
11945 | 11997 | case ovl_fail_too_many_arguments: |
11946 | 11998 | case ovl_fail_too_few_arguments: |
|
0 commit comments