]> granicus.if.org Git - clang/commitdiff
Improve on diagnosing type mismatches because of
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 18 Nov 2009 18:26:29 +0000 (18:26 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 18 Nov 2009 18:26:29 +0000 (18:26 +0000)
lack of viable convesion functions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89216 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaOverload.cpp
test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
test/SemaCXX/rval-references.cpp
test/SemaTemplate/constructor-template.cpp

index 78a3ae5d47b720746c0948c6f18e435d631ed203..ddd7d9fff5e7f10f643d2b9130f33f5134186bb2 100644 (file)
@@ -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">;
index ae5304de44e88b72f86e975a0e27c60952972ccb..abef317d62a06c213623c3bfe609b7729691624d 100644 (file)
@@ -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
index adcd977e626d62181fada8dd532e3942bc630a1b..c9c16aafc4122d01ffed13a364ea3761672e02dd 100644 (file)
@@ -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();
index b32948b4a608f1edfdadeea03b01e4d74e38c9bf..88bc813363fa9af3a35fac265dd25b244e155d73 100644 (file)
@@ -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}}
 }
index 35e8c08a112f33454a873d6da0616d636c2b7472..9528c4b99cb891f1e616237ef0ad13d0fa3625fe 100644 (file)
@@ -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}}
     }
   }
 }
index a7d26bb4b0e11c6e6663a3fc8ef3ae76a888b274..5132c2a69bebfedf98765fe4c70d46600e4fa523 100644 (file)
@@ -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'}}
 }
index 12c6f8b9c10163807ea0e04e6e8faa4c80a34beb..203977e9edd703e3a1ecea78330666319ae2c2c1 100644 (file)
@@ -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}}
 }