summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--clang/lib/Sema/SemaOverload.cpp20
-rw-r--r--clang/test/SemaCXX/overload-call.cpp6
-rw-r--r--clang/test/SemaObjCXX/objc-pointer-conv.mm2
4 files changed, 26 insertions, 10 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dce5929f39e..136dfb5ad06 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/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/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6335cc1fcb7..664c4f3c093 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/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<PointerType>()) {
if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) {
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<ObjCObjectPointerType>()) {
@@ -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<ReferenceType>()) {
+ 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/clang/test/SemaCXX/overload-call.cpp b/clang/test/SemaCXX/overload-call.cpp
index 8d12c9bd411..6bf6965e46b 100644
--- a/clang/test/SemaCXX/overload-call.cpp
+++ b/clang/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/clang/test/SemaObjCXX/objc-pointer-conv.mm b/clang/test/SemaObjCXX/objc-pointer-conv.mm
index d392ad48def..af239a8c5b8 100644
--- a/clang/test/SemaObjCXX/objc-pointer-conv.mm
+++ b/clang/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'}}
OpenPOWER on IntegriCloud