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

llvm-svn: 262752
This commit is contained in:
David Blaikie 2016-03-04 22:29:11 +00:00
parent a0c9f6e736
commit ac92893a93
3 changed files with 26 additions and 10 deletions

View File

@ -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 |"

View File

@ -9131,10 +9131,13 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
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;
}

View File

@ -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'}}
}
}