diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 9 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 32 | ||||
-rw-r--r-- | test/SemaCXX/overload-call.cpp | 6 | ||||
-rw-r--r-- | test/SemaObjCXX/objc-pointer-conv.mm | 8 | ||||
-rw-r--r-- | www/compatibility.html | 5 |
5 files changed, 58 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9771245fd6..dce5929f39 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 4f841b0651..6335cc1fcb 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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 diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 37974ef929..8d12c9bd41 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -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). diff --git a/test/SemaObjCXX/objc-pointer-conv.mm b/test/SemaObjCXX/objc-pointer-conv.mm index cc3264fcc4..d392ad48de 100644 --- a/test/SemaObjCXX/objc-pointer-conv.mm +++ b/test/SemaObjCXX/objc-pointer-conv.mm @@ -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'}} +} diff --git a/www/compatibility.html b/www/compatibility.html index 11f9f659a2..85133fbca2 100644 --- a/www/compatibility.html +++ b/www/compatibility.html @@ -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> |