]> granicus.if.org Git - clang/commitdiff
Extend the "cannot convert from base class pointer to derived class
authorDouglas Gregor <dgregor@apple.com>
Thu, 1 Jul 2010 02:14:45 +0000 (02:14 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 1 Jul 2010 02:14:45 +0000 (02:14 +0000)
pointer" diagnostic to handle references, too.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107372 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
test/SemaCXX/overload-call.cpp
test/SemaObjCXX/objc-pointer-conv.mm

index dce5929f39e4408373f447523bc8682b0c603f06..136dfb5ad06f61bd43230f4bce0e47f7c05aee27 100644 (file)
@@ -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">;
index 6335cc1fcb7e457cbbcb976127b33c2748445cf3..664c4f3c093b863bea605a47cc24c3899c220505 100644 (file)
@@ -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;
   }
index 8d12c9bd4114c8a8ba30ca854212170deb6b5d6a..6bf6965e46bfe777466302fcc7963939f7c245cf 100644 (file)
@@ -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);
index d392ad48def7f613cbbe37a08daf564888827ec2..af239a8c5b89437ebd2ee33948493d51b57ebbe2 100644 (file)
@@ -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'}}