forked from OSchip/llvm-project
Improve the error message when a function overload candidate is rejected
because it expects a reference and receives a non-l-value. For example, given: int foo(int &); template<int x> void b() { foo(x); } clang will now print "expects an l-value for 1st argument" instead of "no known conversion from 'int' to 'int &' for 1st argument". The change in wording (and associated code to detect the case) was prompted by comment #5 in PR3104, and should be the last bit of work needed for the bug. llvm-svn: 158691
This commit is contained in:
parent
9dcc0325de
commit
9ea8f7e6c5
|
@ -2163,6 +2163,17 @@ def note_ovl_candidate_bad_arc_conv : Note<"candidate "
|
|||
"constructor (inherited)}0%1"
|
||||
" not viable: cannot implicitly convert argument of type %2 to %3 for "
|
||||
"%select{%ordinal5 argument|object argument}4 under ARC">;
|
||||
def note_ovl_candidate_bad_lvalue : Note<"candidate "
|
||||
"%select{function|function|constructor|"
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1"
|
||||
" not viable: expects an l-value for "
|
||||
"%select{%ordinal3 argument|object argument}2">;
|
||||
def note_ovl_candidate_bad_addrspace : Note<"candidate "
|
||||
"%select{function|function|constructor|"
|
||||
"function |function |constructor |"
|
||||
|
|
|
@ -8153,12 +8153,27 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
|
|||
FromIface->isSuperClassOf(ToIface))
|
||||
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 (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
|
||||
!FromTy->isIncompleteType() &&
|
||||
!ToRefTy->getPointeeType()->isIncompleteType() &&
|
||||
S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) {
|
||||
BaseToDerivedConversion = 3;
|
||||
} else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() &&
|
||||
ToTy.getNonReferenceType().getCanonicalType() ==
|
||||
FromTy.getNonReferenceType().getCanonicalType()) {
|
||||
QualType T1 = ToTy.getCanonicalType();
|
||||
QualType T2 = ToTy.getNonReferenceType();
|
||||
QualType T3 = T2.getUnqualifiedType();
|
||||
QualType T4 = FromTy.getCanonicalType();
|
||||
(void)T1; (void)T2; (void)T3; (void)T4;
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
|
||||
<< (unsigned) FnKind << FnDesc
|
||||
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
|
||||
<< (unsigned) isObjectArgument << I + 1;
|
||||
MaybeEmitInheritedConstructorNote(S, Fn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (BaseToDerivedConversion) {
|
||||
S.Diag(Fn->getLocation(),
|
||||
|
|
|
@ -22,7 +22,7 @@ struct X3 {
|
|||
X3();
|
||||
|
||||
private:
|
||||
X3(X3&); // expected-note{{candidate constructor not viable: no known conversion from 'X3' to 'X3 &' for 1st argument}}
|
||||
X3(X3&); // expected-note{{candidate constructor not viable: expects an l-value for 1st argument}}
|
||||
};
|
||||
|
||||
// Check for instantiation of default arguments
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
// PR11179
|
||||
template <short T> class Type1 {};
|
||||
template <short T> void Function1(Type1<T>& x) {} // expected-note{{candidate function [with T = -42] not viable: no known conversion from 'Type1<-42>' to 'Type1<-42> &' for 1st argument;}}
|
||||
template <short T> void Function1(Type1<T>& x) {} // expected-note{{candidate function [with T = -42] not viable: expects an l-value for 1st argument}}
|
||||
|
||||
template <unsigned short T> class Type2 {};
|
||||
template <unsigned short T> void Function2(Type2<T>& x) {} // expected-note{{candidate function [with T = 42] not viable: no known conversion from 'Type2<42>' to 'Type2<42> &' for 1st argument;}}
|
||||
template <unsigned short T> void Function2(Type2<T>& x) {} // expected-note{{candidate function [with T = 42] not viable: expects an l-value for 1st argument}}
|
||||
|
||||
void Function() {
|
||||
Function1(Type1<-42>()); // expected-error{{no matching function for call to 'Function1'}}
|
||||
|
|
|
@ -69,7 +69,7 @@ void test_conversion(ConvertibleToBase ctb, ConvertibleToDerived ctd,
|
|||
}
|
||||
|
||||
struct X1 {
|
||||
X1(X1&); // expected-note{{candidate constructor not viable: no known conversion from 'X1' to 'X1 &' for 1st argument}}
|
||||
X1(X1&); // expected-note{{candidate constructor not viable: expects an l-value for 1st argument}}
|
||||
};
|
||||
|
||||
struct X2 {
|
||||
|
|
Loading…
Reference in New Issue