mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 12:00:11 -05:00
c++: Improve diagnostic for implicit conversion errors [PR115163]
This patch adds a note to indicate if any viable explicit conversion functions were skipped if an implicit conversion failed to occur. Perhaps the base diagnostic in ocp_convert can be further improved for class types as well, as the current message is not very clear, but I've not looked into that for this patch. PR c++/115163 gcc/cp/ChangeLog: * call.cc (implicit_conversion_error): Add flags argument, call maybe_show_nonconverting_candidate. (build_converted_constant_expr_internal): Pass flags to implicit_conversion_error. (perform_implicit_conversion_flags): Likewise. * cvt.cc (ocp_convert): Call maybe_show_nonconverting_candidate on conversion error. gcc/testsuite/ChangeLog: * g++.dg/ext/is_convertible7.C: Add new testcases. * g++.dg/diagnostic/explicit2.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
@@ -4917,7 +4917,8 @@ build_user_type_conversion (tree totype, tree expr, int flags,
|
||||
/* Give a helpful diagnostic when implicit_conversion fails. */
|
||||
|
||||
static void
|
||||
implicit_conversion_error (location_t loc, tree type, tree expr)
|
||||
implicit_conversion_error (location_t loc, tree type, tree expr,
|
||||
int flags)
|
||||
{
|
||||
tsubst_flags_t complain = tf_warning_or_error;
|
||||
|
||||
@@ -4932,18 +4933,23 @@ implicit_conversion_error (location_t loc, tree type, tree expr)
|
||||
&& !CP_AGGREGATE_TYPE_P (type))
|
||||
error_at (loc, "designated initializers cannot be used with a "
|
||||
"non-aggregate type %qT", type);
|
||||
else if (is_stub_object (expr))
|
||||
/* The expression is generated by a trait check, we don't have
|
||||
a useful location to highlight the label. */
|
||||
error_at (loc, "could not convert %qH to %qI",
|
||||
TREE_TYPE (expr), type);
|
||||
else
|
||||
else
|
||||
{
|
||||
range_label_for_type_mismatch label (TREE_TYPE (expr), type);
|
||||
gcc_rich_location rich_loc (loc, &label,
|
||||
highlight_colors::percent_h);
|
||||
error_at (&rich_loc, "could not convert %qE from %qH to %qI",
|
||||
expr, TREE_TYPE (expr), type);
|
||||
auto_diagnostic_group d;
|
||||
if (is_stub_object (expr))
|
||||
/* The expression is generated by a trait check, we don't have
|
||||
a useful location to highlight the label. */
|
||||
error_at (loc, "could not convert %qH to %qI",
|
||||
TREE_TYPE (expr), type);
|
||||
else
|
||||
{
|
||||
range_label_for_type_mismatch label (TREE_TYPE (expr), type);
|
||||
gcc_rich_location rich_loc (loc, &label,
|
||||
highlight_colors::percent_h);
|
||||
error_at (&rich_loc, "could not convert %qE from %qH to %qI",
|
||||
expr, TREE_TYPE (expr), type);
|
||||
}
|
||||
maybe_show_nonconverting_candidate (type, TREE_TYPE (expr), expr, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5065,7 +5071,7 @@ build_converted_constant_expr_internal (tree type, tree expr,
|
||||
else
|
||||
{
|
||||
if (complain & tf_error)
|
||||
implicit_conversion_error (loc, type, expr);
|
||||
implicit_conversion_error (loc, type, expr, flags);
|
||||
expr = error_mark_node;
|
||||
}
|
||||
|
||||
@@ -14107,7 +14113,7 @@ perform_implicit_conversion_flags (tree type, tree expr,
|
||||
if (!conv)
|
||||
{
|
||||
if (complain & tf_error)
|
||||
implicit_conversion_error (loc, type, expr);
|
||||
implicit_conversion_error (loc, type, expr, flags);
|
||||
expr = error_mark_node;
|
||||
}
|
||||
else if (processing_template_decl && conv->kind != ck_identity)
|
||||
|
||||
@@ -994,8 +994,13 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
|
||||
if (invalid_nonstatic_memfn_p (loc, expr, complain))
|
||||
/* We displayed the error message. */;
|
||||
else
|
||||
error_at (loc, "conversion from %qH to non-scalar type %qI requested",
|
||||
TREE_TYPE (expr), type);
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
error_at (loc, "conversion from %qH to non-scalar type %qI requested",
|
||||
TREE_TYPE (expr), type);
|
||||
maybe_show_nonconverting_candidate (type, TREE_TYPE (expr), expr,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
14
gcc/testsuite/g++.dg/diagnostic/explicit2.C
Normal file
14
gcc/testsuite/g++.dg/diagnostic/explicit2.C
Normal file
@@ -0,0 +1,14 @@
|
||||
// PR c++/115163
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A {
|
||||
explicit A(int); // { dg-message "explicit conversion function was not considered" }
|
||||
};
|
||||
struct B {
|
||||
explicit operator int() const; // { dg-message "explicit conversion function was not considered" }
|
||||
};
|
||||
|
||||
int main() {
|
||||
A a = 42; // { dg-error "conversion from .int. to non-scalar type .A." }
|
||||
int x = B{}; // { dg-error "cannot convert .B. to .int. in initialization" }
|
||||
}
|
||||
@@ -27,3 +27,15 @@ struct B {
|
||||
};
|
||||
static_assert(is_nothrow_convertible<int, B>::value, ""); // { dg-error "assert" }
|
||||
// { dg-message "'int' is not nothrow convertible from 'B', because" "" { target *-*-* } .-1 }
|
||||
|
||||
struct C {
|
||||
explicit C(int); // { dg-message "not considered" }
|
||||
};
|
||||
static_assert(is_convertible<int, C>::value, ""); // { dg-error "assert" }
|
||||
// { dg-message "could not convert 'int' to 'C'" "" { target *-*-* } .-1 }
|
||||
|
||||
struct D {
|
||||
explicit operator int() const; // { dg-message "not considered" }
|
||||
};
|
||||
static_assert(is_convertible<D, int>::value, ""); // { dg-error "assert" }
|
||||
// { dg-message "could not convert 'D' to 'int'" "" { target *-*-* } .-1 }
|
||||
|
||||
Reference in New Issue
Block a user