Produce detailed diagnostics when overload

resolution failed to select a candidate due to
ambiguity in type conversion function selection.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82596 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2009-09-23 00:58:07 +00:00
Родитель d489cd06a1
Коммит b1663d0507
4 изменённых файлов: 48 добавлений и 8 удалений

Просмотреть файл

@ -763,6 +763,8 @@ def err_ovl_ambiguous_member_call : Error<
def err_ovl_deleted_member_call : Error<
"call to %select{unavailable|deleted}0 member function %1">;
def err_ovl_candidate : Note<"candidate function">;
def err_ovl_candidate_not_viable : Note<"function not viable because"
" of ambiguity in conversion of argument %0">;
def err_ovl_template_candidate : Note<
"candidate function template specialization %0">;
def err_ovl_candidate_deleted : Note<

Просмотреть файл

@ -411,13 +411,15 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
bool InOverloadResolution) {
ImplicitConversionSequence ICS;
OverloadCandidateSet Conversions;
OverloadingResult UserDefResult = OR_Success;
if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard))
ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
else if (getLangOptions().CPlusPlus &&
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
(UserDefResult = IsUserDefinedConversion(From, ToType,
ICS.UserDefined,
Conversions,
!SuppressUserConversions, AllowExplicit,
ForceRValue) == OR_Success) {
ForceRValue)) == OR_Success) {
ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
@ -454,8 +456,14 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
if (SuppressUserConversions &&
ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion)
ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
} else
} else {
ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
if (UserDefResult == OR_Ambiguous) {
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
ICS.ConversionFunctionSet.push_back(Cand->Function);
}
}
return ICS;
}
@ -3868,7 +3876,26 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
*Cand->Function->getTemplateSpecializationArgs());
} else {
// Normal function
// FIXME: Give a better reason!
bool errReported = false;
if (!Cand->Viable && Cand->Conversions.size() > 0) {
for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
const ImplicitConversionSequence &Conversion =
Cand->Conversions[i];
if ((Conversion.ConversionKind !=
ImplicitConversionSequence::BadConversion) ||
Conversion.ConversionFunctionSet.size() == 0)
continue;
Diag(Cand->Function->getLocation(),
diag::err_ovl_candidate_not_viable) << (i+1);
errReported = true;
for (int j = Conversion.ConversionFunctionSet.size()-1;
j >= 0; j--) {
FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
Diag(Func->getLocation(), diag::err_ovl_candidate);
}
}
}
if (!errReported)
Diag(Cand->Function->getLocation(), diag::err_ovl_candidate);
}
} else if (Cand->IsSurrogate) {

Просмотреть файл

@ -196,6 +196,10 @@ namespace clang {
UserDefinedConversionSequence UserDefined;
};
/// When ConversionKind == BadConversion due to multiple conversion
/// functions, this will list those functions.
llvm::SmallVector<FunctionDecl*, 4> ConversionFunctionSet;
// The result of a comparison between implicit conversion
// sequences. Use Sema::CompareImplicitConversionSequences to
// actually perform the comparison.

Просмотреть файл

@ -1,10 +1,10 @@
// RUN: clang-cc -fsyntax-only -verify %s
struct BASE {
operator int &(); // expected-note {{candidate function}}
operator int &(); // expected-note 4 {{candidate function}}
};
struct BASE1 {
operator int &(); // expected-note {{candidate function}}
operator int &(); // expected-note 4 {{candidate function}}
};
struct B : public BASE, BASE1 {
@ -13,7 +13,14 @@ struct B : public BASE, BASE1 {
extern B f();
B b1;
void func(const int ci, const char cc); // expected-note {{function not viable because of ambiguity in conversion of argument 1}}
void func(const char ci, const B b); // expected-note {{function not viable because of ambiguity in conversion of argument 1}}
void func(const B b, const int ci); // expected-note {{function not viable because of ambiguity in conversion of argument 2}}
const int main() {
func(b1, f()); // expected-error {{no matching function for call to 'func'}}
return f(); // expected-error {{conversion from 'struct B' to 'int const' is ambiguous}}
}