From f5fbb982055046bb6e0de6661d4208ced3a1c11d Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 1 Sep 2015 16:03:21 -0400
Subject: [PATCH 37/63] C/C++/c-family: Update binary_op_error to report the
 tree ranges of LHS and RHS (compiles, has test cases, no ChangeLog)

(first test case was location hack gcc.dg/20150303-04.c, which is now gone)
---
 gcc/c-family/c-common.c                            |  9 +++++-
 gcc/c-family/c-common.h                            |  3 +-
 gcc/c/c-typeck.c                                   |  5 ++--
 gcc/cp/typeck.c                                    |  3 +-
 gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c | 35 ++++++++++++++++++++++
 5 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 12c840c..2e40707 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "wide-int-print.h"
 #include "gimple-expr.h"
+#include "gcc-rich-location.h"
 
 cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 
@@ -4334,6 +4335,7 @@ c_register_builtin_type (tree type, const char* name)
 
 void
 binary_op_error (location_t location, enum tree_code code,
+		 tree orig_op0, tree orig_op1,
 		 tree type0, tree type1)
 {
   const char *opname;
@@ -4385,7 +4387,12 @@ binary_op_error (location_t location, enum tree_code code,
     default:
       gcc_unreachable ();
     }
-  error_at (location,
+  gcc_rich_location richloc (location);
+  richloc.maybe_add_expr_with_caption (orig_op0, global_dc,
+				       "%qT", TREE_TYPE (orig_op0));
+  richloc.maybe_add_expr_with_caption (orig_op1, global_dc,
+				       "%qT", TREE_TYPE (orig_op1));
+  error_at_rich_loc (&richloc,
 	    "invalid operands to binary %s (have %qT and %qT)", opname,
 	    type0, type1);
 }
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bb7c3ed..4fbfa1e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -797,7 +797,8 @@ extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int);
 extern tree c_alignof_expr (source_range, 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 (location_t, enum tree_code, tree, tree,
+			     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/c-typeck.c b/gcc/c/c-typeck.c
index 1706867..df08181 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -11030,7 +11030,7 @@ 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);
+      binary_op_error (location, code, orig_op0, orig_op1, type0, type1);
       return error_mark_node;
     }
 
@@ -11269,7 +11269,8 @@ build_binary_op (location_t location, enum tree_code code,
 
   if (!result_type)
     {
-      binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
+      binary_op_error (location, code, orig_op0, orig_op1,
+		       TREE_TYPE (op0), TREE_TYPE (op1));
       return error_mark_node;
     }
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5d754f1..b450c08 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4820,7 +4820,8 @@ 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);
+		binary_op_error (location, code, orig_op0, orig_op1,
+				 type0, type1);
 	      return error_mark_node;
 	    }
 	  arithmetic_types_p = 1;
diff --git a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
index f6e564c..57e5fff 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
@@ -79,3 +79,38 @@ void call_of_non_function_ptr (char **argP, char **argQ)
                                        ^~~~
    { dg-end-multiline-output "" } */
 }
+
+/* Adapted from https://gcc.gnu.org/wiki/ClangDiagnosticsComparison */
+
+typedef float __m128;
+void bad_binary_op ()
+{
+  __m128 myvec[2];
+  int const *ptr;
+  myvec[1]/ptr; /* { dg-error "invalid operands to binary /" } */
+
+/*
+{ 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 another_bad_binary_op (void)
+{
+  return (some_function ()
+	  + some_other_function ()); /* { dg-error "invalid operands to binary +" } */
+
+/* { dg-begin-multiline-output "" }
+   return (some_function ()|
+           ~~~~~~~~~~~~~~~~+'struct s'
+    + some_other_function ());                                                  |
+    ^ ~~~~~~~~~~~~~~~~~~~~~~                                                    +'struct t'
+   { dg-end-multiline-output "" } */
+}
-- 
1.8.5.3

