diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index dce5929f39..136dfb5ad0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1203,14 +1203,16 @@ def note_ovl_candidate_bad_cvr : Note<"candidate " "%select{const|volatile|const and volatile|restrict|const and restrict|" "volatile and restrict|const, volatile, and restrict}3 qualifier" "%select{||s||s|s|s}3">; -def note_ovl_candidate_bad_base_to_derived_ptr_conv : Note<"candidate " +def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" "function (the implicit copy assignment operator)}0%1" - " not viable: cannot convert from base class pointer %2 to derived class " - "pointer %3 for %ordinal4 argument">; + " not viable: cannot %select{convert from|convert from|bind}2 " + "%select{base class pointer|superclass|base class object of type}2 %3 to " + "%select{derived class pointer|subclass|derived class reference}2 %4 for " + "%ordinal5 argument">; def note_ambiguous_type_conversion: Note< "because of ambiguity in conversion of %0 to %1">; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6335cc1fcb..664c4f3c09 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5486,7 +5486,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { } // Diagnose base -> derived pointer conversions. - bool IsBaseToDerivedConversion = false; + unsigned BaseToDerivedConversion = 0; if (const PointerType *FromPtrTy = FromTy->getAs()) { if (const PointerType *ToPtrTy = ToTy->getAs()) { if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( @@ -5495,7 +5495,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { !ToPtrTy->getPointeeType()->isIncompleteType() && S.IsDerivedFrom(ToPtrTy->getPointeeType(), FromPtrTy->getPointeeType())) - IsBaseToDerivedConversion = true; + BaseToDerivedConversion = 1; } } else if (const ObjCObjectPointerType *FromPtrTy = FromTy->getAs()) { @@ -5506,13 +5506,21 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( FromPtrTy->getPointeeType()) && FromIface->isSuperClassOf(ToIface)) - IsBaseToDerivedConversion = true; - } - if (IsBaseToDerivedConversion) { + BaseToDerivedConversion = 2; + } else if (const ReferenceType *ToRefTy = ToTy->getAs()) { + if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && + !FromTy->isIncompleteType() && + !ToRefTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) + BaseToDerivedConversion = 3; + } + + if (BaseToDerivedConversion) { S.Diag(Fn->getLocation(), - diag::note_ovl_candidate_bad_base_to_derived_ptr_conv) + diag::note_ovl_candidate_bad_base_to_derived_conv) << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << (BaseToDerivedConversion - 1) << FromTy << ToTy << I+1; return; } diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 8d12c9bd41..6bf6965e46 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -236,6 +236,12 @@ void intref_test() { float* ir2 = intref(5.5); } +void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}} + +void test_base(A& a) { + derived5(a); // expected-error{{no matching function for call to 'derived5}} +} + // Test reference binding vs. standard conversions. int& bind_vs_conv(const double&); float& bind_vs_conv(int); diff --git a/test/SemaObjCXX/objc-pointer-conv.mm b/test/SemaObjCXX/objc-pointer-conv.mm index d392ad48de..af239a8c5b 100644 --- a/test/SemaObjCXX/objc-pointer-conv.mm +++ b/test/SemaObjCXX/objc-pointer-conv.mm @@ -39,7 +39,7 @@ void foo(const I *p, I* sel) { @interface DerivedFromI : I @end -void accept_derived(DerivedFromI*); // expected-note{{candidate function not viable: cannot convert from base class pointer 'I *' to derived class pointer 'DerivedFromI *' for 1st argument}} +void accept_derived(DerivedFromI*); // expected-note{{candidate function not viable: cannot convert from superclass 'I *' to subclass 'DerivedFromI *' for 1st argument}} void test_base_to_derived(I* i) { accept_derived(i); // expected-error{{no matching function for call to 'accept_derived'}}