diff options
author | John McCall <rjmccall@apple.com> | 2010-01-12 02:15:36 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-01-12 02:15:36 +0000 |
commit | 3c80f573dfbc01f29cc292f6c1fc794705823d52 (patch) | |
tree | ba8385cf151d59b57a79ad33a20ba025ffedf882 /lib/Sema/SemaOverload.cpp | |
parent | 8776382f7ed8c6bf34cfa196357ca0d7b51a776a (diff) |
Reorganize some of the code to note overload candidates. Improves the
fidelity with which we note them as functions/constructors and templates
thereof. Also will be helpful when reporting bad conversions (next).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93224 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index a7d4f372d1..26f8c8edda 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4263,42 +4263,62 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, return OR_Success; } -/// Notes the location of an overload candidate. -void Sema::NoteOverloadCandidate(FunctionDecl *Fn) { +namespace { - if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) { - // At least call it a 'constructor'. - if (!Ctor->isImplicit()) { - Diag(Ctor->getLocation(), diag::note_ovl_candidate_ctor); - return; - } +enum OverloadCandidateKind { + oc_function, + oc_method, + oc_constructor, + oc_implicit_default_constructor, + oc_implicit_copy_constructor, + oc_implicit_copy_assignment, + oc_template_specialization // function, constructor, or conversion template +}; - CXXRecordDecl *Record = Ctor->getParent(); - if (Ctor->isCopyConstructor()) { - Diag(Record->getLocation(), diag::note_ovl_candidate_implicit_copy_ctor); - return; - } +OverloadCandidateKind ClassifyOverloadCandidate(FunctionDecl *Fn) { + if (Fn->getPrimaryTemplate()) + return oc_template_specialization; - Diag(Record->getLocation(), diag::note_ovl_candidate_implicit_default_ctor); - return; + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) { + if (!Ctor->isImplicit()) + return oc_constructor; + + return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor + : oc_implicit_default_constructor; } if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) { // This actually gets spelled 'candidate function' for now, but // it doesn't hurt to split it out. - if (!Meth->isImplicit()) { - Diag(Meth->getLocation(), diag::note_ovl_candidate_meth); - return; - } + if (!Meth->isImplicit()) + return oc_method; assert(Meth->isCopyAssignment() && "implicit method is not copy assignment operator?"); - Diag(Meth->getParent()->getLocation(), - diag::note_ovl_candidate_implicit_copy_assign); + return oc_implicit_copy_assignment; + } + + return oc_function; +} + +std::string DescribeFunctionTemplate(Sema &S, FunctionDecl *Fn) { + FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate(); + return S.getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(), + *Fn->getTemplateSpecializationArgs()); +} + +} // end anonymous namespace + +// Notes the location of an overload candidate. +void Sema::NoteOverloadCandidate(FunctionDecl *Fn) { + OverloadCandidateKind K = ClassifyOverloadCandidate(Fn); + if (K == oc_template_specialization) { + Diag(Fn->getLocation(), diag::note_ovl_template_candidate) + << DescribeFunctionTemplate(*this, Fn); return; } - Diag(Fn->getLocation(), diag::note_ovl_candidate); + Diag(Fn->getLocation(), diag::note_ovl_candidate) << (unsigned) K; } /// Diagnoses an ambiguous conversion. The partial diagnostic is the @@ -4318,26 +4338,23 @@ void Sema::DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS, namespace { void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) { + FunctionDecl *Fn = Cand->Function; + // Note deleted candidates, but only if they're viable. - if (Cand->Viable && - (Cand->Function->isDeleted() || - Cand->Function->hasAttr<UnavailableAttr>())) { - S.Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted) - << Cand->Function->isDeleted(); - return; - } + if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) { + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(Fn); + + if (FnKind == oc_template_specialization) { + S.Diag(Fn->getLocation(), diag::note_ovl_template_candidate_deleted) + << DescribeFunctionTemplate(S, Fn) << Fn->isDeleted(); + return; + } - if (FunctionTemplateDecl *FunTmpl - = Cand->Function->getPrimaryTemplate()) { - // Function template specialization - // FIXME: Give a better reason! - S.Diag(Cand->Function->getLocation(), diag::note_ovl_template_candidate) - << S.getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(), - *Cand->Function->getTemplateSpecializationArgs()); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) + << FnKind << Fn->isDeleted(); return; } - // Normal function bool errReported = false; if (!Cand->Viable && Cand->Conversions.size() > 0) { for (int i = Cand->Conversions.size()-1; i >= 0; i--) { @@ -4347,14 +4364,14 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) { if (!Conversion.isAmbiguous()) continue; - S.DiagnoseAmbiguousConversion(Conversion, Cand->Function->getLocation(), + S.DiagnoseAmbiguousConversion(Conversion, Fn->getLocation(), PDiag(diag::note_ovl_candidate_not_viable) << (i+1)); errReported = true; } } if (!errReported) - S.NoteOverloadCandidate(Cand->Function); + S.NoteOverloadCandidate(Fn); } void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { |