c++: Better diagnostic in converted const expr.

This improves the diagnostic from

error: could not convert ‘((A<>*)(void)0)->A<>::e’ from
       ‘<unresolved overloaded function type>’ to ‘bool’

to

error: cannot convert ‘A<>::e’ from type ‘void (A<>::)()’ to type ‘bool’

gcc/cp/ChangeLog
2020-05-11  Jason Merrill  <jason@redhat.com>

	* call.c (implicit_conversion_error): Split out from...
	(perform_implicit_conversion_flags): ...here.
	(build_converted_constant_expr_internal): Use it.
This commit is contained in:
Jason Merrill 2020-05-11 15:39:44 -04:00
parent f981395c22
commit 42e9f80bf4
6 changed files with 42 additions and 20 deletions

View File

@ -1,3 +1,9 @@
2020-05-11 Jason Merrill <jason@redhat.com>
* call.c (implicit_conversion_error): Split out from...
(perform_implicit_conversion_flags): ...here.
(build_converted_constant_expr_internal): Use it.
2020-05-11 Jason Merrill <jason@redhat.com>
PR c++/90748

View File

@ -4282,6 +4282,28 @@ build_user_type_conversion (tree totype, tree expr, int flags,
return ret;
}
/* Give a helpful diagnostic when implicit_conversion fails. */
static void
implicit_conversion_error (location_t loc, tree type, tree expr)
{
tsubst_flags_t complain = tf_warning_or_error;
/* If expr has unknown type, then it is an overloaded function.
Call instantiate_type to get good error messages. */
if (TREE_TYPE (expr) == unknown_type_node)
instantiate_type (type, expr, complain);
else if (invalid_nonstatic_memfn_p (loc, expr, complain))
/* We gave an error. */;
else
{
range_label_for_type_mismatch label (TREE_TYPE (expr), type);
gcc_rich_location rich_loc (loc, &label);
error_at (&rich_loc, "could not convert %qE from %qH to %qI",
expr, TREE_TYPE (expr), type);
}
}
/* Worker for build_converted_constant_expr. */
static tree
@ -4397,8 +4419,7 @@ build_converted_constant_expr_internal (tree type, tree expr,
else
{
if (complain & tf_error)
error_at (loc, "could not convert %qE from %qH to %qI", expr,
TREE_TYPE (expr), type);
implicit_conversion_error (loc, type, expr);
expr = error_mark_node;
}
@ -11845,21 +11866,7 @@ perform_implicit_conversion_flags (tree type, tree expr,
if (!conv)
{
if (complain & tf_error)
{
/* If expr has unknown type, then it is an overloaded function.
Call instantiate_type to get good error messages. */
if (TREE_TYPE (expr) == unknown_type_node)
instantiate_type (type, expr, complain);
else if (invalid_nonstatic_memfn_p (loc, expr, complain))
/* We gave an error. */;
else
{
range_label_for_type_mismatch label (TREE_TYPE (expr), type);
gcc_rich_location rich_loc (loc, &label);
error_at (&rich_loc, "could not convert %qE from %qH to %qI",
expr, TREE_TYPE (expr), type);
}
}
implicit_conversion_error (loc, type, expr);
expr = error_mark_node;
}
else if (processing_template_decl && conv->kind != ck_identity)

View File

@ -5,7 +5,7 @@
template<typename A>
struct F {
template<typename B>
void f() noexcept(&F::template f<B>) {} // { dg-error "exception specification|convert" }
void f() noexcept(&F::template f<B>) {} // { dg-error "exception specification|convert|resolve" }
};
int main () {

View File

@ -0,0 +1,9 @@
// PR c++/90748
// { dg-do compile { target c++11 } }
template <class ...> class A
{
void e ();
bool f (int() noexcept(e)); // { dg-error "::e" }
};
A<> b;

View File

@ -17,7 +17,7 @@ template <bool name>
class BUG2 : BUG
{
public:
typedef BUG1_5<name> ptr; // { dg-error "convert" }
typedef BUG1_5<name> ptr; // { dg-error "BUG::name" }
};
int main()

View File

@ -11,7 +11,7 @@ struct Dummy
template<bool B>
void tester()
{
bar<evil>()(); // { dg-error "constant|template|convert" }
bar<evil>()(); // { dg-error "constant|template|convert|member function" }
}
template<bool B>
struct bar