}
bool
-Sema::DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType) {
+Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet;
OverloadingResult OvResult =
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
CandidateSet, true, false, false);
- if (OvResult != OR_Ambiguous)
+ if (OvResult == OR_Ambiguous)
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_ambiguous_condition)
+ << From->getType() << ToType << From->getSourceRange();
+ else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty())
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_nonviable_condition)
+ << From->getType() << ToType << From->getSourceRange();
+ else
return false;
- Diag(From->getSourceRange().getBegin(),
- diag::err_typecheck_ambiguous_condition)
- << From->getType() << ToType << From->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
return true;
}
if (!PerformImplicitConversion(From, ToType, Flavor,
/*AllowExplicit=*/false, Elidable))
return false;
- if (!DiagnoseAmbiguousUserDefinedConversion(From, ToType))
+ if (!DiagnoseMultipleUserDefinedConversion(From, ToType))
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
<< ToType << From->getType() << Flavor << From->getSourceRange();
if (!PerformImplicitConversion(From, Context.BoolTy, ICS, "converting"))
return false;
- if (!DiagnoseAmbiguousUserDefinedConversion(From, Context.BoolTy))
+ if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
// Test the return dance. This also tests IsReturnCopyElidable.
struct MoveOnly {
MoveOnly();
- MoveOnly(const MoveOnly&) = delete;
- MoveOnly(MoveOnly&&);
- MoveOnly(int&&);
+ MoveOnly(const MoveOnly&) = delete; // expected-note {{candidate function}}
+ MoveOnly(MoveOnly&&); // expected-note {{candidate function}}
+ MoveOnly(int&&); // expected-note {{candidate function}}
};
MoveOnly returning() {
else if (0) // Copy from reference can't be elided
return r; // expected-error {{incompatible type returning}}
else // Construction from different type can't be elided
- return i; // expected-error {{incompatible type returning}}
+ return i; // expected-error {{no viable conversion from 'int' to 'struct MoveOnly'}}
}
struct X2 {
X2();
- X2(X2&);
+ X2(X2&); // expected-note {{candidate function}}
template<typename T> X2(T);
};
if (Cond)
return x2; // okay, uses copy constructor
- return X2(); // expected-error{{incompatible type}}
+ return X2(); // expected-error{{no viable conversion from 'struct X2' to 'struct X2' is possible}}
}
struct X3 {
struct X4 {
X4();
~X4();
- X4(X4&);
+ X4(X4&); // expected-note {{candidate function}}
template<typename T> X4(const T&, int = 17);
};
X4 test_X4(bool Cond, X4 x4) {
X4 a(x4, 17); // okay, constructor template
X4 b(x4); // okay, copy constructor
- return X4(); // expected-error{{incompatible type}}
+ return X4(); // expected-error{{no viable conversion}}
}