]> granicus.if.org Git - clang/commitdiff
Improve diagnostic when we fail to pick an overload because it would
authorDouglas Gregor <dgregor@apple.com>
Wed, 30 Jun 2010 23:01:39 +0000 (23:01 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 30 Jun 2010 23:01:39 +0000 (23:01 +0000)
require a base-to-derived pointer conversion.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107349 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
www/compatibility.html

index 9771245fd63b8080beb4b6173a64a9d576967877..dce5929f39e4408373f447523bc8682b0c603f06 100644 (file)
@@ -1203,6 +1203,15 @@ 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 "
+    "%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">;
+
 def note_ambiguous_type_conversion: Note<
     "because of ambiguity in conversion of %0 to %1">;
 def note_ovl_builtin_binary_candidate : Note<
index 4f841b065188c634439bcbb3fa669d582de8298a..6335cc1fcb7e457cbbcb976127b33c2748445cf3 100644 (file)
@@ -5485,6 +5485,38 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
     return;
   }
 
+  // Diagnose base -> derived pointer conversions.
+  bool IsBaseToDerivedConversion = false;
+  if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) {
+    if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) {
+      if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+                                               FromPtrTy->getPointeeType()) &&
+          !FromPtrTy->getPointeeType()->isIncompleteType() &&
+          !ToPtrTy->getPointeeType()->isIncompleteType() &&
+          S.IsDerivedFrom(ToPtrTy->getPointeeType(), 
+                          FromPtrTy->getPointeeType()))
+        IsBaseToDerivedConversion = true;
+    }
+  } else if (const ObjCObjectPointerType *FromPtrTy
+                                    = FromTy->getAs<ObjCObjectPointerType>()) {
+    if (const ObjCObjectPointerType *ToPtrTy
+                                        = ToTy->getAs<ObjCObjectPointerType>())
+      if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl())
+        if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl())
+          if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+                                                FromPtrTy->getPointeeType()) &&
+              FromIface->isSuperClassOf(ToIface))
+            IsBaseToDerivedConversion = true;
+  }
+  if (IsBaseToDerivedConversion) {
+    S.Diag(Fn->getLocation(), 
+           diag::note_ovl_candidate_bad_base_to_derived_ptr_conv)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << FromTy << ToTy << I+1;    
+    return;
+  }
+      
   // TODO: specialize more based on the kind of mismatch
   S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
     << (unsigned) FnKind << FnDesc
index 37974ef929e7a52ae33b7c58f90001614023f446..8d12c9bd4114c8a8ba30ca854212170deb6b5d6a 100644 (file)
@@ -219,6 +219,12 @@ void test_derived(B* b, B const* bc, C* c, const C* cc, void* v, D* d) {
   char* d8 = derived3(d);
 }
 
+void derived4(C*); // expected-note{{candidate function not viable: cannot convert from base class pointer 'A *' to derived class pointer 'C *' for 1st argument}}
+
+void test_base(A* a) {
+  derived4(a); // expected-error{{no matching function for call to 'derived4}}
+}
+
 // Test overloading of references. 
 // (FIXME: tests binding to determine candidate sets, not overload 
 //  resolution per se).
index cc3264fcc4623dae4ef14a2b79e77cdef5f5c751..d392ad48def7f613cbbe37a08daf564888827ec2 100644 (file)
@@ -36,3 +36,11 @@ void foo(const I *p, I* sel) {
   Func(p);             // expected-error {{no matching function for call to 'Func'}}
 }
 
+@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 test_base_to_derived(I* i) {
+  accept_derived(i); // expected-error{{no matching function for call to 'accept_derived'}}
+}
index 11f9f659a2d98cc77993950f21ff6923ad770756..85133fbca2f6ff2d539a35e7ec9328f1d0c87d6f 100644 (file)
@@ -590,8 +590,9 @@ void g(Base *base) {
 downcast.mm:6:3: error: no matching function for call to 'f'
   f(base);
   ^
-downcast.mm:4:6: note: candidate function not viable: no known conversion from
-      'Base *' to 'Derived *' for 1st argument
+downcast.mm:4:6: note: candidate function not viable: cannot convert from base
+      class pointer 'Base *' to derived class pointer 'Derived *' for 1st
+      argument
 void f(Derived *);
      ^
 </pre>