aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-12-19 15:22:27 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-12-19 15:22:27 +0000
commit15c40a3b7ce64665f8b4552a45c0cdd9564598cc (patch)
tree19d7b2382480d268226940b03efa216e2a1a66a2 /gcc/cp
parent4c187162fa29f40746b8794bcbc0c4c52a497f31 (diff)
downloadgcc-15c40a3b7ce64665f8b4552a45c0cdd9564598cc.zip
gcc-15c40a3b7ce64665f8b4552a45c0cdd9564598cc.tar.gz
gcc-15c40a3b7ce64665f8b4552a45c0cdd9564598cc.tar.bz2
C++: better locations for bogus initializations (PR c++/88375)
PR c++/88375 reports that errors relating to invalid conversions in initializations are reported at unhelpfully vague locations, as in e.g.: enum struct a : int { one, two }; struct foo { int e1, e2; a e3; } arr[] = { { 1, 2, a::one }, { 3, a::two }, { 4, 5, a::two } }; for which g++ trunk emits the vague: pr88375.cc:12:1: error: cannot convert 'a' to 'int' in initialization 12 | }; | ^ with the error at the final closing brace. This patch uses location information for the initializers, converting the above to: pr88375.cc:10:11: error: cannot convert 'a' to 'int' in initialization 10 | { 3, a::two }, | ~~~^~~ | | | a highlighting which subexpression is problematic, and its type. Ideally we'd also issue a note showing the field decl being initialized, but that turned out to be more invasive. gcc/cp/ChangeLog: PR c++/88375 * typeck.c (convert_for_assignment): Capture location of rhs before stripping, and if available. Use the location when complaining about bad conversions, labelling it with the rhstype if the location was present. * typeck2.c (digest_init_r): Capture location of init before stripping. gcc/testsuite/ChangeLog: PR c++/88375 * g++.dg/init/pr88375-2.C: New test. * g++.dg/init/pr88375.C: New test. From-SVN: r267276
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/typeck.c43
-rw-r--r--gcc/cp/typeck2.c10
3 files changed, 41 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index beae265..7b79461 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,15 @@
2018-12-19 David Malcolm <dmalcolm@redhat.com>
+ PR c++/88375
+ * typeck.c (convert_for_assignment): Capture location of rhs
+ before stripping, and if available. Use the location when
+ complaining about bad conversions, labelling it with the
+ rhstype if the location was present.
+ * typeck2.c (digest_init_r): Capture location of init before
+ stripping.
+
+2018-12-19 David Malcolm <dmalcolm@redhat.com>
+
PR c++/87504
* call.c (op_error): Convert 1st param from location_t to
const op_location_t &. Use binary_op_rich_location for binary
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 94a33d4..ef317f5 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8852,6 +8852,7 @@ convert_for_assignment (tree type, tree rhs,
enum tree_code coder;
location_t rhs_loc = EXPR_LOC_OR_LOC (rhs, input_location);
+ bool has_loc = EXPR_LOCATION (rhs) != UNKNOWN_LOCATION;
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue,
but preserve location wrappers. */
if (TREE_CODE (rhs) == NON_LVALUE_EXPR
@@ -8892,7 +8893,7 @@ convert_for_assignment (tree type, tree rhs,
if (coder == VOID_TYPE)
{
if (complain & tf_error)
- error ("void value not ignored as it ought to be");
+ error_at (rhs_loc, "void value not ignored as it ought to be");
return error_mark_node;
}
@@ -8964,35 +8965,43 @@ convert_for_assignment (tree type, tree rhs,
rhstype, type,
fndecl, parmnum);
else
- switch (errtype)
- {
+ {
+ range_label_for_type_mismatch label (rhstype, type);
+ gcc_rich_location richloc (rhs_loc, has_loc ? &label : NULL);
+ switch (errtype)
+ {
case ICR_DEFAULT_ARGUMENT:
- error ("cannot convert %qH to %qI in default argument",
- rhstype, type);
+ error_at (&richloc,
+ "cannot convert %qH to %qI in default argument",
+ rhstype, type);
break;
case ICR_ARGPASS:
- error ("cannot convert %qH to %qI in argument passing",
- rhstype, type);
+ error_at (&richloc,
+ "cannot convert %qH to %qI in argument passing",
+ rhstype, type);
break;
case ICR_CONVERTING:
- error ("cannot convert %qH to %qI",
- rhstype, type);
+ error_at (&richloc, "cannot convert %qH to %qI",
+ rhstype, type);
break;
case ICR_INIT:
- error ("cannot convert %qH to %qI in initialization",
- rhstype, type);
+ error_at (&richloc,
+ "cannot convert %qH to %qI in initialization",
+ rhstype, type);
break;
case ICR_RETURN:
- error ("cannot convert %qH to %qI in return",
- rhstype, type);
+ error_at (&richloc, "cannot convert %qH to %qI in return",
+ rhstype, type);
break;
case ICR_ASSIGN:
- error ("cannot convert %qH to %qI in assignment",
- rhstype, type);
+ error_at (&richloc,
+ "cannot convert %qH to %qI in assignment",
+ rhstype, type);
break;
default:
gcc_unreachable();
}
+ }
if (TYPE_PTR_P (rhstype)
&& TYPE_PTR_P (type)
&& CLASS_TYPE_P (TREE_TYPE (rhstype))
@@ -9059,9 +9068,7 @@ convert_for_assignment (tree type, tree rhs,
&& TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
&& (complain & tf_warning))
{
- location_t loc = cp_expr_loc_or_loc (rhs, input_location);
-
- warning_at (loc, OPT_Wparentheses,
+ warning_at (rhs_loc, OPT_Wparentheses,
"suggest parentheses around assignment used as truth value");
TREE_NO_WARNING (rhs) = 1;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index c1fa4a9..209832b 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1050,14 +1050,16 @@ digest_init_r (tree type, tree init, int nested, int flags,
complain))
return error_mark_node;
+ location_t loc = cp_expr_loc_or_loc (init, input_location);
+
+ tree stripped_init = init;
+
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue
(g++.old-deja/g++.law/casts2.C). */
if (TREE_CODE (init) == NON_LVALUE_EXPR)
- init = TREE_OPERAND (init, 0);
-
- location_t loc = cp_expr_loc_or_loc (init, input_location);
+ stripped_init = TREE_OPERAND (init, 0);
- tree stripped_init = tree_strip_any_location_wrapper (init);
+ stripped_init = tree_strip_any_location_wrapper (stripped_init);
/* Initialization of an array of chars from a string constant. The initializer
can be optionally enclosed in braces, but reshape_init has already removed