diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 21 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp | 6 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/rval-references.cpp | 8 | ||||
-rw-r--r-- | test/SemaTemplate/constructor-template.cpp | 8 |
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}} } |