@@ -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
@@ -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);
@@ -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. */
@@ -11190,7 +11191,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;
}
@@ -11429,7 +11433,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;
}
@@ -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;
}
new file mode 100644
@@ -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 "" } */
+}
new file mode 100644
@@ -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. */
+}
@@ -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