Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
-- >8 --
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 <[email protected]>
---
gcc/cp/call.cc | 34 ++++++++++++---------
gcc/cp/cvt.cc | 9 ++++--
gcc/testsuite/g++.dg/diagnostic/explicit2.C | 14 +++++++++
gcc/testsuite/g++.dg/ext/is_convertible7.C | 12 ++++++++
4 files changed, 53 insertions(+), 16 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/diagnostic/explicit2.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 608fb9b69d0..34d23e99849 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -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)
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index 3dfa0529b9b..771f72106cd 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -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;
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/explicit2.C
b/gcc/testsuite/g++.dg/diagnostic/explicit2.C
new file mode 100644
index 00000000000..46fea3cc20b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/explicit2.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_convertible7.C
b/gcc/testsuite/g++.dg/ext/is_convertible7.C
index b38fc042de9..2bdc07bad06 100644
--- a/gcc/testsuite/g++.dg/ext/is_convertible7.C
+++ b/gcc/testsuite/g++.dg/ext/is_convertible7.C
@@ -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 }
--
2.51.0