On 11/19/19 11:38 PM, Jakub Jelinek wrote:
Hi!
The following patch is a minimal fix to avoid
cannot convert ‘‘addr_expr’ not supported by dump_type<type error>’ to ‘X*’
and similar messages. The recently added complain_about_bad_argument
function expects a from_type argument, but conv->from isn't necessarily a
type, it can be an expression too.
With this patch one gets error like:
cannot convert ‘const X*’ to ‘X*’
and note like
initializing argument 'this' of ‘void X::foo()’
Still, perhaps what GCC 8 and earlier used to emit might be clearer:
pr90767-1.C: In member function ‘X::operator T() const’:
pr90767-1.C:12:7: error: no matching function for call to ‘X::foo() const’
pr90767-1.C:6:8: note: candidate: ‘void X::foo()’ <near match>
pr90767-1.C:6:8: note: passing ‘const X*’ as ‘this’ argument discards
qualifiers
There is the print_conversion_rejection function that handles the various
cases, like this vs. other arguments, conv->from with expr type vs. type
etc.
Though, I must say I don't understand the reasons why
complain_about_bad_argument
has been added and whether we'd want to emit there what
print_conversion_rejection prints as notes with 2 leading spaces instead as
errors with no leading spaces.
Historically, when we have a single candidate we assume it's chosen by
overload resolution and try to call it, so we often get different
diagnostics. Sometimes better, sometimes worse. In this case it seems
about even. I'm surprised this case was different in GCC 8.
In any case, I think the patch below is a step in the right direction.
Agreed, the patch is OK.
2019-11-19 Jakub Jelinek <ja...@redhat.com>
PR c++/90767
* call.c (complain_about_no_candidates_for_method_call): If
conv->from is not a type, pass to complain_about_bad_argument
lvalue_type of conv->from.
* g++.dg/diagnostic/pr90767-1.C: New test.
* g++.dg/diagnostic/pr90767-2.C: New test.
--- gcc/cp/call.c.jj 2019-11-18 18:49:14.461880924 +0100
+++ gcc/cp/call.c 2019-11-19 14:40:19.121937148 +0100
@@ -9861,8 +9861,11 @@ complain_about_no_candidates_for_method_
if (const conversion_info *conv
= maybe_get_bad_conversion_for_unmatched_call (candidate))
{
+ tree from_type = conv->from;
+ if (!TYPE_P (conv->from))
+ from_type = lvalue_type (conv->from);
complain_about_bad_argument (conv->loc,
- conv->from, conv->to_type,
+ from_type, conv->to_type,
candidate->fn, conv->n_arg);
return;
}
--- gcc/testsuite/g++.dg/diagnostic/pr90767-1.C.jj 2019-11-19
14:48:00.386041586 +0100
+++ gcc/testsuite/g++.dg/diagnostic/pr90767-1.C 2019-11-19 14:46:53.395043036
+0100
@@ -0,0 +1,15 @@
+// PR c++/90767
+// { dg-do compile }
+
+struct X {
+ int n;
+ void foo (); // { dg-message "initializing argument 'this'" }
+
+ template<typename T>
+ operator T () const
+ {
+ if (n == 0)
+ foo (); // { dg-error "cannot convert 'const X\\*' to 'X\\*'" }
+ return n;
+ }
+};
--- gcc/testsuite/g++.dg/diagnostic/pr90767-2.C.jj 2019-11-19
14:50:48.923522136 +0100
+++ gcc/testsuite/g++.dg/diagnostic/pr90767-2.C 2019-11-19 14:52:27.324051149
+0100
@@ -0,0 +1,15 @@
+// PR c++/90767
+// { dg-do compile }
+
+struct A {
+ struct B { B (int) {} };
+
+ template <typename T>
+ void foo ()
+ {
+ int x = 0;
+ bar (x); // { dg-error "cannot convert 'int' to 'A::B&'" }
+ }
+
+ void bar (B &arg) {} // { dg-message "initializing argument 1" }
+};
Jakub