C and C++ FE: fix source ranges for binary ops
authorDavid Malcolm <dmalcolm@redhat.com>
Mon, 21 Dec 2015 17:45:34 +0000 (17:45 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Mon, 21 Dec 2015 17:45:34 +0000 (17:45 +0000)
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
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/bad-binary-ops.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c

index 3208ce59ddadb8eda3a627dc5182ed6c4d2e4a0f..fc2e19ef92ef56e10a081e4cfed4e5d0fabc61d2 100644 (file)
@@ -1,3 +1,10 @@
+2015-12-21  David Malcolm  <dmalcolm@redhat.com>
+
+       * 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  <dmalcolm@redhat.com>
 
        * c-common.h (conflict_marker_get_final_tok_kind): New prototype.
index 4250cdf1ceedcf6dbae01668efa9ab15ddd0274a..653d1dc1a72df544f9636db7fdb4429284dd9dc1 100644 (file)
@@ -3795,10 +3795,21 @@ c_register_builtin_type (tree type, const char* name)
 \f
 /* 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);
 }
 \f
 /* Given an expression as a tree, return its original type.  Do this
index 2183565c0ddd09227043c8af44af06bd64eb7fd2..eb63f1d9ad104694a1783aebfa7a0684b02badd3 100644 (file)
@@ -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);
index 7c1247d120e25a2920bcbe15d4194fadbe6753f2..fb9fda3b21165fc84ea14dfb566d4c36fcafe6f4 100644 (file)
@@ -1,3 +1,10 @@
+2015-12-21  David Malcolm  <dmalcolm@redhat.com>
+
+       * 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  <dmalcolm@redhat.com>
 
        * c-parser.c (c_parser_statement_after_labels): When calling
index b605f81fb43b504c277e37802cd8a547708b229b..a97774fea92c493d024b204e6e6bb97cfd5759c8 100644 (file)
@@ -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;
     }
 
index 1dd533efa79cb503134a7a2dcf983e18586edce8..bba3973a0958165b2aa5e0c3f09b98eb3b80e4ad 100644 (file)
@@ -1,3 +1,12 @@
+2015-12-21  David Malcolm  <dmalcolm@redhat.com>
+
+       * 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  <jason@redhat.com>
 
        PR c++/67411
index a06ecf0732a38ae699aae454bfd8c7b21fa2781c..25e74e901933f4fb2d62c8f9e95646434bbd828b 100644 (file)
@@ -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;
     }
 
index bb2ed22edf6307877614785a812b72510b02cfac..14f048d1df908baa1a7e61039b707f479f31edbc 100644 (file)
@@ -1,3 +1,11 @@
+2015-12-21  David Malcolm  <dmalcolm@redhat.com>
+
+       * 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  <claziss@synopsys.com>
 
        * 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 (file)
index 0000000..4ab7656
--- /dev/null
@@ -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 (file)
index 0000000..e1da4d6
--- /dev/null
@@ -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.  */
+}
index 5a911c17a4e025dec4b700a44db7c3e258919467..c98034fb69564f3070d8e103356e8f2c3f4644c3 100644 (file)
 #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