From 745e411d4fd4739118356662329a509a8b7d4ae8 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 21 Dec 2015 17:45:34 +0000 Subject: [PATCH] C and C++ FE: fix source ranges for binary ops gcc/c-family/ChangeLog: * c-common.c (binary_op_error): Convert first param from location_t to rich_location * and use it when emitting an error. * c-common.h (binary_op_error): Convert first param from location_t to rich_location *. gcc/c/ChangeLog: * c-typeck.c: Include "gcc-rich-location.h". (build_binary_op): In the two places that call binary_op_error, create a gcc_rich_location and populate it with the location of the binary op and its two operands. gcc/cp/ChangeLog: * typeck.c (cp_build_binary_op): Update for change in signature of build_binary_op. Use error_at to replace an implicit use of input_location with param "location" in "invalid operands" error. (cp_build_binary_op): Replace an error with an error_at, using "location", rather than implicitly using input_location. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/bad-binary-ops.C: New test case. * gcc.dg/bad-binary-ops.c: New test case. gcc.dg/plugin/diagnostic_plugin_show_trees.c (get_range_for_expr): Remove material copied from gcc-rich-location.c (gcc_rich_location::add_expr): Likewise. From-SVN: r231884 --- gcc/c-family/ChangeLog | 7 ++++ gcc/c-family/c-common.c | 21 +++++++--- gcc/c-family/c-common.h | 2 +- gcc/c/ChangeLog | 7 ++++ gcc/c/c-typeck.c | 11 ++++- gcc/cp/ChangeLog | 9 ++++ gcc/cp/typeck.c | 13 ++++-- gcc/testsuite/ChangeLog | 8 ++++ gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C | 44 ++++++++++++++++++++ gcc/testsuite/gcc.dg/bad-binary-ops.c | 48 ++++++++++++++++++++++ .../gcc.dg/plugin/diagnostic_plugin_show_trees.c | 44 -------------------- 11 files changed, 159 insertions(+), 55 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C create mode 100644 gcc/testsuite/gcc.dg/bad-binary-ops.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 3208ce5..fc2e19e 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2015-12-21 David Malcolm + + * c-common.c (binary_op_error): Convert first param from + location_t to rich_location * and use it when emitting an error. + * c-common.h (binary_op_error): Convert first param from + location_t to rich_location *. + 2015-12-16 David Malcolm * c-common.h (conflict_marker_get_final_tok_kind): New prototype. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 4250cdf..653d1dc1 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -3795,10 +3795,21 @@ c_register_builtin_type (tree type, const char* name) /* Print an error message for invalid operands to arith operation CODE with TYPE0 for operand 0, and TYPE1 for operand 1. - LOCATION is the location of the message. */ + RICHLOC is a rich location for the message, containing either + three separate locations for each of the operator and operands + + lhs op rhs + ~~~ ^~ ~~~ + + (C FE), or one location ranging over all over them + + lhs op rhs + ~~~~^~~~~~ + + (C++ FE). */ void -binary_op_error (location_t location, enum tree_code code, +binary_op_error (rich_location *richloc, enum tree_code code, tree type0, tree type1) { const char *opname; @@ -3850,9 +3861,9 @@ binary_op_error (location_t location, enum tree_code code, default: gcc_unreachable (); } - error_at (location, - "invalid operands to binary %s (have %qT and %qT)", opname, - type0, type1); + error_at_rich_loc (richloc, + "invalid operands to binary %s (have %qT and %qT)", + opname, type0, type1); } /* Given an expression as a tree, return its original type. Do this diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 2183565..eb63f1d 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -817,7 +817,7 @@ extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int); extern tree c_alignof_expr (location_t, tree); /* Print an error message for invalid operands to arith operation CODE. NOP_EXPR is used as a special case (see truthvalue_conversion). */ -extern void binary_op_error (location_t, enum tree_code, tree, tree); +extern void binary_op_error (rich_location *, enum tree_code, tree, tree); extern tree fix_string_type (tree); extern void constant_expression_warning (tree); extern void constant_expression_error (tree); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 7c1247d..fb9fda3 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2015-12-21 David Malcolm + + * c-typeck.c: Include "gcc-rich-location.h". + (build_binary_op): In the two places that call binary_op_error, + create a gcc_rich_location and populate it with the location of + the binary op and its two operands. + 2015-12-16 David Malcolm * c-parser.c (c_parser_statement_after_labels): When calling diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index b605f81..a97774f 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "cilk.h" #include "gomp-constants.h" #include "spellcheck.h" +#include "gcc-rich-location.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ @@ -11202,7 +11203,10 @@ build_binary_op (location_t location, enum tree_code code, && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1)) || !vector_types_compatible_elements_p (type0, type1))) { - binary_op_error (location, code, type0, type1); + gcc_rich_location richloc (location); + richloc.maybe_add_expr (orig_op0); + richloc.maybe_add_expr (orig_op1); + binary_op_error (&richloc, code, type0, type1); return error_mark_node; } @@ -11441,7 +11445,10 @@ build_binary_op (location_t location, enum tree_code code, if (!result_type) { - binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1)); + gcc_rich_location richloc (location); + richloc.maybe_add_expr (orig_op0); + richloc.maybe_add_expr (orig_op1); + binary_op_error (&richloc, code, TREE_TYPE (op0), TREE_TYPE (op1)); return error_mark_node; } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1dd533e..bba3973 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2015-12-21 David Malcolm + + * typeck.c (cp_build_binary_op): Update for change in signature + of build_binary_op. Use error_at to replace an implicit use + of input_location with param "location" in "invalid operands" + error. + (cp_build_binary_op): Replace an error with an error_at, using + "location", rather than implicitly using input_location. + 2015-12-20 Jason Merrill PR c++/67411 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a06ecf0..25e74e9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4908,7 +4908,13 @@ cp_build_binary_op (location_t location, || !vector_types_compatible_elements_p (type0, type1)) { if (complain & tf_error) - binary_op_error (location, code, type0, type1); + { + /* "location" already embeds the locations of the + operands, so we don't need to add them separately + to richloc. */ + rich_location richloc (line_table, location); + binary_op_error (&richloc, code, type0, type1); + } return error_mark_node; } arithmetic_types_p = 1; @@ -4931,8 +4937,9 @@ cp_build_binary_op (location_t location, if (!result_type) { if (complain & tf_error) - error ("invalid operands of types %qT and %qT to binary %qO", - TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); + error_at (location, + "invalid operands of types %qT and %qT to binary %qO", + TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); return error_mark_node; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bb2ed22..14f048d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-12-21 David Malcolm + + * g++.dg/diagnostic/bad-binary-ops.C: New test case. + * gcc.dg/bad-binary-ops.c: New test case. + gcc.dg/plugin/diagnostic_plugin_show_trees.c (get_range_for_expr): + Remove material copied from gcc-rich-location.c + (gcc_rich_location::add_expr): Likewise. + 2015-12-21 Claudiu Zissulescu * gcc.target/arc/builtin_general.c: New test. diff --git a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C new file mode 100644 index 0000000..4ab7656 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C @@ -0,0 +1,44 @@ +// { dg-options "-fdiagnostics-show-caret" } + +// Adapted from https://gcc.gnu.org/wiki/ClangDiagnosticsComparison + +typedef float __m128; +void test_1 () +{ + __m128 myvec[2]; + int const *ptr; + myvec[1] / ptr; // { dg-error "invalid operands" } + +/* { dg-begin-multiline-output "" } + myvec[1] / ptr; + ~~~~~~~~~^~~~~ + { dg-end-multiline-output "" } */ +} + +struct s {}; +struct t {}; +extern struct s some_function (void); +extern struct t some_other_function (void); + +int test_2 (void) +{ + return (some_function () + + some_other_function ()); // { dg-error "no match for .operator" } + +/* { dg-begin-multiline-output "" } + return (some_function () + ~~~~~~~~~~~~~~~~ + + some_other_function ()); + ^~~~~~~~~~~~~~~~~~~~~~~~ + { dg-end-multiline-output "" } */ +} + +int test_3 (struct s param_s, struct t param_t) +{ + return param_s && param_t; // { dg-error "no match for .operator" } + +/* { dg-begin-multiline-output "" } + return param_s && param_t; + ~~~~~~~~^~~~~~~~~~ + { dg-end-multiline-output "" } */ +} diff --git a/gcc/testsuite/gcc.dg/bad-binary-ops.c b/gcc/testsuite/gcc.dg/bad-binary-ops.c new file mode 100644 index 0000000..e1da4d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bad-binary-ops.c @@ -0,0 +1,48 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +/* Adapted from https://gcc.gnu.org/wiki/ClangDiagnosticsComparison */ + +typedef float __m128; +void test_1 () +{ + __m128 myvec[2]; + int const *ptr; + myvec[1]/ptr; /* { dg-error "invalid operands to binary /" } */ + +/* TODO: ideally we'd underline "ptr" as well. +{ dg-begin-multiline-output "" } + myvec[1]/ptr; + ~~~~~~~~^ +{ dg-end-multiline-output "" } */ + + +} + +struct s {}; +struct t {}; +extern struct s some_function (void); +extern struct t some_other_function (void); + +int test_2 (void) +{ + return (some_function () + + some_other_function ()); /* { dg-error "invalid operands to binary \+" } */ + +/* { dg-begin-multiline-output "" } + return (some_function () + ~~~~~~~~~~~~~~~~ + + some_other_function ()); + ^ ~~~~~~~~~~~~~~~~~~~~~~ + { dg-end-multiline-output "" } */ +} + +int test_3 (struct s param_s, struct t param_t) +{ + return param_s + param_t; // { dg-error "invalid operands to binary \+" } + +/* { dg-begin-multiline-output "" } + return param_s + param_t; + ^ + { dg-end-multiline-output "" } */ +/* TODO: ideally we'd underline both params here. */ +} diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c index 5a911c1..c98034f 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c @@ -32,50 +32,6 @@ #include "gcc-rich-location.h" #include "print-tree.h" -/* - Hack: fails with linker error: -./diagnostic_plugin_show_trees.so: undefined symbol: _ZN17gcc_rich_location8add_exprEP9tree_node - since nothing in the tree is using gcc_rich_location::add_expr yet. - - I've tried various workarounds (adding DEBUG_FUNCTION to the - method, taking its address), but can't seem to fix it that way. - So as a nasty workaround, the following material is copied&pasted - from gcc-rich-location.c: */ - -static bool -get_range_for_expr (tree expr, location_range *r) -{ - if (EXPR_HAS_RANGE (expr)) - { - source_range sr = EXPR_LOCATION_RANGE (expr); - - /* Do we have meaningful data? */ - if (sr.m_start && sr.m_finish) - { - r->m_start = expand_location (sr.m_start); - r->m_finish = expand_location (sr.m_finish); - return true; - } - } - - return false; -} - -/* Add a range to the rich_location, covering expression EXPR. */ - -void -gcc_rich_location::add_expr (tree expr) -{ - gcc_assert (expr); - - location_range r; - r.m_show_caret_p = false; - if (get_range_for_expr (expr, &r)) - add_range (&r); -} - -/* FIXME: end of material taken from gcc-rich-location.c */ - int plugin_is_GPL_compatible; static void -- 2.7.4