From 700204189d7171b725f95238c7dda55e12840ab3 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Fri, 4 Mar 2016 22:29:11 +0000 Subject: [PATCH] PR5941 - improve diagnostic for * vs & confusion when choosing overload candidate with a parameter of incomplete (ref or pointer) type Reviewers: dblaikie Differential Revision: http://reviews.llvm.org/D16949 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262752 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 7 ++++++- lib/Sema/SemaOverload.cpp | 5 ++++- test/SemaCXX/overload-call.cpp | 24 ++++++++++++++-------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a3a60fb270..c5faa6eb74 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3219,7 +3219,12 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate " "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 " "not viable: cannot convert argument of incomplete type " - "%diff{$ to $|to parameter type}2,3">; + "%diff{$ to $|to parameter type}2,3 for " + "%select{%ordinal5 argument|object argument}4" + "%select{|; dereference the argument with *|" + "; take the address of the argument with &|" + "; remove *|" + "; remove &}6">; def note_ovl_candidate_bad_list_argument : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 2ad49933d4..1765db6734 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -9131,10 +9131,13 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (const PointerType *PTy = TempFromTy->getAs()) TempFromTy = PTy->getPointeeType(); if (TempFromTy->isIncompleteType()) { + // Emit the generic diagnostic and, optionally, add the hints to it. S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete) << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + << FromTy << ToTy << (unsigned) isObjectArgument << I+1 + << (unsigned) (Cand->Fix.Kind); + MaybeEmitInheritedConstructorNote(S, Fn); return; } diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 3d286a94a0..7eaf98b601 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -375,16 +375,24 @@ namespace test2 { } // PR 6117 -namespace test3 { - struct Base {}; +namespace IncompleteConversion { + struct Complete {}; struct Incomplete; - void foo(Base *); // expected-note 2 {{cannot convert argument of incomplete type}} - void foo(Base &); // expected-note 2 {{cannot convert argument of incomplete type}} - - void test(Incomplete *P) { - foo(P); // expected-error {{no matching function for call to 'foo'}} - foo(*P); // expected-error {{no matching function for call to 'foo'}} + void completeFunction(Complete *); // expected-note 2 {{cannot convert argument of incomplete type}} + void completeFunction(Complete &); // expected-note 2 {{cannot convert argument of incomplete type}} + + void testTypeConversion(Incomplete *P) { + completeFunction(P); // expected-error {{no matching function for call to 'completeFunction'}} + completeFunction(*P); // expected-error {{no matching function for call to 'completeFunction'}} + } + + void incompletePointerFunction(Incomplete *); // expected-note {{candidate function not viable: cannot convert argument of incomplete type 'IncompleteConversion::Incomplete' to 'IncompleteConversion::Incomplete *' for 1st argument; take the address of the argument with &}} + void incompleteReferenceFunction(Incomplete &); // expected-note {{candidate function not viable: cannot convert argument of incomplete type 'IncompleteConversion::Incomplete *' to 'IncompleteConversion::Incomplete &' for 1st argument; dereference the argument with *}} + + void testPointerReferenceConversion(Incomplete &reference, Incomplete *pointer) { + incompletePointerFunction(reference); // expected-error {{no matching function for call to 'incompletePointerFunction'}} + incompleteReferenceFunction(pointer); // expected-error {{no matching function for call to 'incompleteReferenceFunction'}} } } -- 2.40.0