From 7d3bac41caf5fb6cc58d6cff5c979225830ffb95 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 27 Jan 2016 17:16:36 -0500
Subject: [PATCH 03/22] PR c++/22238

(has not been bootstrapped or regrtested)

gcc/cp/ChangeLog:
	PR c++/22238
	* call.c (perform_implicit_conversion_flags): Rewrite error_at to
	eliminate usage of %qE.

gcc/testsuite/ChangeLog:
	PR c++/22238
	* g++.dg/warn/pr22238-1.C: New test.
---
 gcc/cp/call.c                                     |  5 +++--
 gcc/testsuite/g++.dg/cpp0x/enum28.C               |  4 ++--
 gcc/testsuite/g++.dg/cpp0x/inh-ctor8.C            |  2 +-
 gcc/testsuite/g++.dg/cpp0x/initlist24.C           |  2 +-
 gcc/testsuite/g++.dg/cpp0x/initlist38.C           |  2 +-
 gcc/testsuite/g++.dg/cpp0x/initlist62.C           |  2 +-
 gcc/testsuite/g++.dg/cpp0x/pr66243.C              |  2 +-
 gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C |  2 +-
 gcc/testsuite/g++.dg/cpp1y/pr59629.C              |  2 +-
 gcc/testsuite/g++.dg/diagnostic/expr1.C           |  2 +-
 gcc/testsuite/g++.dg/ext/pr59706.C                |  4 ++--
 gcc/testsuite/g++.dg/other/error19.C              |  2 +-
 gcc/testsuite/g++.dg/warn/pr22238-1.C             | 17 +++++++++++++++++
 13 files changed, 33 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/pr22238-1.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 729b7eb..c06aadb 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9648,8 +9648,9 @@ perform_implicit_conversion_flags (tree type, tree expr,
 	  else if (invalid_nonstatic_memfn_p (loc, expr, complain))
 	    /* We gave an error.  */;
 	  else
-	    error_at (loc, "could not convert %qE from %qT to %qT", expr,
-		      TREE_TYPE (expr), type);
+	    error_at
+	      (loc, "value of type %qT is not contextually convertible to %qT",
+	       TREE_TYPE (expr), type);
 	}
       expr = error_mark_node;
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum28.C b/gcc/testsuite/g++.dg/cpp0x/enum28.C
index 3967699..4f4caef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum28.C
@@ -7,11 +7,11 @@ void f(int i)
 {
   switch (i)
     {
-    case 1.0:;    // { dg-error "could not convert" }
+    case 1.0:;    // { dg-error "is not contextually convertible" }
     }
 
   switch (i)
     {
-    case g():;    // { dg-error "could not convert" }
+    case g():;    // { dg-error "is not contextually convertible" }
     }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor8.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor8.C
index 74c9496..6e5f680 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor8.C
@@ -16,5 +16,5 @@ void f(B);
 int main()
 {
   f(B(42));			// OK
-  f(42);			// { dg-error "could not convert" }
+  f(42);			// { dg-error "is not contextually convertible" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist24.C b/gcc/testsuite/g++.dg/cpp0x/initlist24.C
index d885744..c38422b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist24.C
@@ -5,5 +5,5 @@
 
 void test3()
 {
-  std::initializer_list<int> list{move}; // { dg-error "not declared|could not convert" }
+  std::initializer_list<int> list{move}; // { dg-error "not declared|is not contextually convertible" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist38.C b/gcc/testsuite/g++.dg/cpp0x/initlist38.C
index 816f94c..653a667 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist38.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist38.C
@@ -17,5 +17,5 @@ int main()
   f({});
   B b0 = { };
   B b1 { };    // OK, uses #1
-  B b2 { 1 };  // { dg-error "could not convert" }
+  B b2 { 1 };  // { dg-error "is not contextually convertible" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist62.C b/gcc/testsuite/g++.dg/cpp0x/initlist62.C
index d739ea3..ae1b416 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist62.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist62.C
@@ -5,6 +5,6 @@
 
 struct A
 {
-  std::initializer_list<int> x[1] = { 0 };  // { dg-error "could not convert" }
+  std::initializer_list<int> x[1] = { 0 };  // { dg-error "is not contextually convertible" }
   A() {}
 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr66243.C b/gcc/testsuite/g++.dg/cpp0x/pr66243.C
index 41465a0..75ace7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr66243.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr66243.C
@@ -7,6 +7,6 @@ enum class A
 
 enum class B
 {
-  X = A::X // { dg-error "could not convert" }
+  X = A::X // { dg-error "is not contextually convertible" }
 };
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C
index 8dc2fa6..a07a88f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C
@@ -6,7 +6,7 @@ Col y = Col::red;
            
 void f()
 {                     
-  if (y) { } // { dg-error "could not convert" }
+  if (y) { } // { dg-error "6: is not contextually convertible" }
 }
 
 enum direction { left='l', right='r' };
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59629.C b/gcc/testsuite/g++.dg/cpp1y/pr59629.C
index f66e64e..e32f11b 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr59629.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59629.C
@@ -1,4 +1,4 @@
 // PR c++/59629
 // { dg-do compile { target c++14 } }
 
-void foo(int i = []{ auto 0; }()); // { dg-error "expected|could not convert" }
+void foo(int i = []{ auto 0; }()); // { dg-error "expected|is not contextually convertible" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/expr1.C b/gcc/testsuite/g++.dg/diagnostic/expr1.C
index 5651030..0d2f10f 100644
--- a/gcc/testsuite/g++.dg/diagnostic/expr1.C
+++ b/gcc/testsuite/g++.dg/diagnostic/expr1.C
@@ -5,5 +5,5 @@ struct A { };
 void f(A);
 void g()
 {
-  f(i = 0);			// { dg-error "i = 0" }
+  f(i = 0); // { dg-error "value of type .int. is not contextually convertible to .A." }
 }
diff --git a/gcc/testsuite/g++.dg/ext/pr59706.C b/gcc/testsuite/g++.dg/ext/pr59706.C
index b82b45e..6ff3974 100644
--- a/gcc/testsuite/g++.dg/ext/pr59706.C
+++ b/gcc/testsuite/g++.dg/ext/pr59706.C
@@ -8,7 +8,7 @@ void
 foo ()
 {
   #pragma GCC ivdep
-  while (s)	// { dg-error "could not convert" }
+  while (s)	// { dg-error "10: is not contextually convertible to .bool." }
     ;
 }
 
@@ -16,6 +16,6 @@ void
 bar ()
 {
   #pragma GCC ivdep
-  while (t)	// { dg-error "could not convert" }
+  while (t)	// { dg-error "10: is not contextually convertible to .bool." }
     ;
 }
diff --git a/gcc/testsuite/g++.dg/other/error19.C b/gcc/testsuite/g++.dg/other/error19.C
index 9389dc1..4e89086 100644
--- a/gcc/testsuite/g++.dg/other/error19.C
+++ b/gcc/testsuite/g++.dg/other/error19.C
@@ -2,6 +2,6 @@
 
 void foo()
 {
-  if (({while(true);})) // { dg-error "forbids|<statement>" }
+  if (({while(true);})) // { dg-error "forbids|value of type .void. is not contextually convertible to .bool." }
     ;
 }
diff --git a/gcc/testsuite/g++.dg/warn/pr22238-1.C b/gcc/testsuite/g++.dg/warn/pr22238-1.C
new file mode 100644
index 0000000..3b4759b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr22238-1.C
@@ -0,0 +1,17 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+struct A
+{
+  void foo();
+};
+
+struct B : virtual A
+{
+  void bar() { if (foo ()) ; } // { dg-error "value of type .void. is not contextually convertible to .bool." }
+};
+
+/* { dg-begin-multiline-output "" }
+   void bar() { if (foo ()) ; }
+                    ~~~~^~
+   { dg-end-multiline-output "" } */
+
-- 
1.8.5.3

