aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaOverload.cpp21
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp6
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp4
-rw-r--r--test/SemaCXX/rval-references.cpp8
-rw-r--r--test/SemaTemplate/constructor-template.cpp8
7 files changed, 29 insertions, 22 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 78a3ae5d47..ddd7d9fff5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1811,6 +1811,8 @@ def err_typecheck_bool_condition : Error<
"value of type %0 is not contextually convertible to 'bool'">;
def err_typecheck_ambiguous_condition : Error<
"conversion from %0 to %1 is ambiguous">;
+def err_typecheck_nonviable_condition : Error<
+ "no viable conversion from %0 to %1 is possible">;
def err_expected_class_or_namespace : Error<"expected a class or namespace">;
def err_invalid_declarator_scope : Error<
"definition or redeclaration of %0 not in a namespace enclosing %1">;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ae5304de44..abef317d62 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -822,7 +822,7 @@ public:
bool AllowConversionFunctions,
bool AllowExplicit, bool ForceRValue,
bool UserCast = false);
- bool DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType);
+ bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
ImplicitConversionSequence::CompareKind
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index adcd977e62..c9c16aafc4 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1545,18 +1545,23 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
}
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;
}
@@ -2072,7 +2077,7 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
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();
@@ -2192,7 +2197,7 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
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();
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
index b32948b4a6..88bc813363 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
@@ -31,7 +31,7 @@ void test() {
}
namespace Numbers {
- struct Number {
+ struct Number { // expected-note 2 {{candidate}}
explicit Number(double d) : d(d) {}
double d;
};
@@ -57,9 +57,9 @@ void test3() {
int i = Ints::zero;
Numbers2::f(i);
- Numbers2::g(i); // expected-error {{incompatible type passing 'int'}}
+ Numbers2::g(i); // expected-error {{no viable conversion from 'int' to 'struct Numbers::Number' is possible}}
float f = Floats::zero;
Numbers2::f(f);
- Numbers2::g(f); // expected-error {{incompatible type passing 'float'}}
+ Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'struct Numbers::Number' is possible}}
}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
index 35e8c08a11..9528c4b99c 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
@@ -4,7 +4,7 @@
template <unsigned N> class test {};
-class foo {};
+class foo {}; // expected-note {{candidate}}
test<0> foo(foo); // expected-note {{candidate}}
namespace Test0 {
@@ -38,7 +38,7 @@ namespace Test0 {
test<2> _1 = (foo)(a);
class Test0::foo b;
- test<2> _2 = (foo)(b); // expected-error {{incompatible type passing}}
+ test<2> _2 = (foo)(b); // expected-error {{no viable conversion from 'class Test0::foo' to 'class foo' is possible}}
}
}
}
diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp
index a7d26bb4b0..5132c2a69b 100644
--- a/test/SemaCXX/rval-references.cpp
+++ b/test/SemaCXX/rval-references.cpp
@@ -65,9 +65,9 @@ int&& should_not_warn(int&& i) { // But GCC 4.4 does
// 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() {
@@ -87,5 +87,5 @@ MoveOnly returningNonEligible() {
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'}}
}
diff --git a/test/SemaTemplate/constructor-template.cpp b/test/SemaTemplate/constructor-template.cpp
index 12c6f8b9c1..203977e9ed 100644
--- a/test/SemaTemplate/constructor-template.cpp
+++ b/test/SemaTemplate/constructor-template.cpp
@@ -53,7 +53,7 @@ struct B { A<int> x; B(B& a) : x(a.x) {} };
struct X2 {
X2();
- X2(X2&);
+ X2(X2&); // expected-note {{candidate function}}
template<typename T> X2(T);
};
@@ -61,7 +61,7 @@ X2 test(bool Cond, X2 x2) {
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 {
@@ -73,12 +73,12 @@ template<> X3::X3(X3); // expected-error{{must pass its first argument by refere
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}}
}