From 5ac9d833d585acaa68786cd6e0df8b48fbc42000 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 30 Oct 2018 12:50:23 -0400
Subject: [PATCH 32/83] FIXME: use op_location_t in -Wtautological-compare

---
 gcc/c-family/c-common.h                            |  3 ++-
 gcc/c-family/c-warn.c                              |  8 ++++---
 gcc/c/c-typeck.c                                   |  3 +--
 gcc/cp/call.c                                      | 17 ++++---------
 gcc/cp/cp-tree.h                                   | 25 +------------------
 gcc/cp/typeck.c                                    | 20 +++++-----------
 gcc/gcc-rich-location.c                            | 20 ++++++++++++----
 gcc/gcc-rich-location.h                            |  6 ++++-
 .../c-c++-common/Wtautological-compare-ranges.c    | 28 ++++++++++++++++++++++
 gcc/tree.h                                         | 23 ++++++++++++++++++
 10 files changed, 90 insertions(+), 63 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wtautological-compare-ranges.c

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 641fe57..1e7ebb9 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1263,7 +1263,8 @@ extern void constant_expression_error (tree);
 extern void overflow_warning (location_t, tree, tree = NULL_TREE);
 extern void warn_logical_operator (location_t, enum tree_code, tree,
 				   enum tree_code, tree, enum tree_code, tree);
-extern void warn_tautological_cmp (location_t, enum tree_code, tree, tree);
+extern void warn_tautological_cmp (const op_location_t &, enum tree_code,
+				   tree, tree);
 extern void warn_logical_not_parentheses (location_t, enum tree_code, tree,
 					  tree);
 extern bool warn_if_unused_value (const_tree, location_t);
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 65e2f99..0528bb8 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -396,7 +396,8 @@ warn_tautological_bitwise_comparison (location_t loc, tree_code code,
    operands of the comparison.  */
 
 void
-warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs)
+warn_tautological_cmp (const op_location_t &loc, enum tree_code code,
+		       tree lhs, tree rhs)
 {
   if (TREE_CODE_CLASS (code) != tcc_comparison)
     return;
@@ -440,11 +441,12 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs)
       const bool always_true = (code == EQ_EXPR || code == LE_EXPR
 				|| code == GE_EXPR || code == UNLE_EXPR
 				|| code == UNGE_EXPR || code == UNEQ_EXPR);
+      binary_op_rich_location richloc (loc, lhs, rhs, false);
       if (always_true)
-	warning_at (loc, OPT_Wtautological_compare,
+	warning_at (&richloc, OPT_Wtautological_compare,
 		    "self-comparison always evaluates to true");
       else
-	warning_at (loc, OPT_Wtautological_compare,
+	warning_at (&richloc, OPT_Wtautological_compare,
 		    "self-comparison always evaluates to false");
     }
 }
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index f2a5fc0..6e58093 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -12174,8 +12174,7 @@ build_binary_op (location_t location, enum tree_code code,
 
   if (!result_type)
     {
-      binary_op_rich_location richloc (location, // FIXME
-				       orig_op0, orig_op1);
+      binary_op_rich_location richloc (location, orig_op0, orig_op1, true);
       binary_op_error (&richloc, code, TREE_TYPE (op0), TREE_TYPE (op1));
       return error_mark_node;
     }
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d0e54b2..145ba8f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4763,19 +4763,10 @@ op_error (const op_location_t &loc,
       if (arg2)
 	if (flag_diagnostics_show_caret)
 	  {
-	    if (EXPR_HAS_LOCATION (arg1)
-		&& EXPR_HAS_LOCATION (arg2)
-		&& loc.m_operator_loc != UNKNOWN_LOCATION)
-	      {
-		binary_op_rich_location richloc (loc.m_operator_loc,
-						 arg1, arg2);
-		error_at (&richloc,
-			  op_error_string (G_("%<operator%s%>"), 2, match),
-			  opname, TREE_TYPE (arg1), TREE_TYPE (arg2));
-	      }
-	    else
-	      error_at (loc, op_error_string (G_("%<operator%s%>"), 2, match),
-			opname, TREE_TYPE (arg1), TREE_TYPE (arg2));
+	    binary_op_rich_location richloc (loc, arg1, arg2, true);
+	    error_at (&richloc,
+		      op_error_string (G_("%<operator%s%>"), 2, match),
+		      opname, TREE_TYPE (arg1), TREE_TYPE (arg2));
 	  }
 	else
 	  error_at (loc, op_error_string (G_("%<operator%s%> in %<%E %s %E%>"),
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3242a81..8bd8078 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -109,29 +109,6 @@ operator == (const cp_expr &lhs, tree rhs)
   return lhs.get_value () == rhs;
 }
 
-// FIXME: where to put this?
-/* FIXME:
-   OPERATOR_LOC is the location of the operator
-   COMBINED_LOC is the location of the compound expression.  */
-
-struct op_location_t
-{
-  // FIXME: eliminate this eventually:
-  op_location_t (location_t combined_loc)
-  : m_operator_loc (UNKNOWN_LOCATION), m_combined_loc (combined_loc)
-  {}
-
-  op_location_t (location_t operator_loc, location_t combined_loc)
-  : m_operator_loc (operator_loc), m_combined_loc (combined_loc)
-  {}
-
-  location_t m_operator_loc;
-  location_t m_combined_loc;
-
-  // FIXME
-  operator location_t () const { return m_combined_loc; }
-};
-
 
 enum cp_tree_index
 {
@@ -7365,7 +7342,7 @@ extern tree composite_pointer_type		(tree, tree, tree, tree,
 extern tree merge_types				(tree, tree);
 extern tree strip_array_domain			(tree);
 extern tree check_return_expr			(tree, bool *);
-extern tree cp_build_binary_op                  (location_t,
+extern tree cp_build_binary_op                  (const op_location_t &,
 						 enum tree_code, tree, tree,
 						 tsubst_flags_t);
 extern tree build_x_vec_perm_expr               (location_t,
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4643e18..fec8030 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4290,7 +4290,7 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
    multiple inheritance, and deal with pointer to member functions.  */
 
 tree
-cp_build_binary_op (location_t location,
+cp_build_binary_op (const op_location_t &location,
 		    enum tree_code code, tree orig_op0, tree orig_op1,
 		    tsubst_flags_t complain)
 {
@@ -5288,19 +5288,11 @@ cp_build_binary_op (location_t location,
     {
       if (complain & tf_error)
 	{
-	  if (EXPR_HAS_LOCATION (orig_op0)
-	      && EXPR_HAS_LOCATION (orig_op1))
-	    {
-	      binary_op_rich_location richloc (get_pure_location (location), // FIXME
-					       orig_op0, orig_op1);
-	      error_at (&richloc,
-			"invalid operands of types %qT and %qT to binary %qO",
-			TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
-	    }
-	  else
-	    error_at (location,
-		      "invalid operands of types %qT and %qT to binary %qO",
-		      TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
+	  binary_op_rich_location richloc (location,
+					   orig_op0, orig_op1, true);
+	  error_at (&richloc,
+		    "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/gcc-rich-location.c b/gcc/gcc-rich-location.c
index 9335569..5857cf4 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -203,12 +203,22 @@ maybe_range_label_for_tree_type_mismatch::get_text (unsigned range_idx) const
 
 /* FIXME.  */
 
-binary_op_rich_location::binary_op_rich_location (location_t loc,
-						  tree arg0, tree arg1)
-: gcc_rich_location (loc),
+binary_op_rich_location::binary_op_rich_location (const op_location_t &loc,
+						  tree arg0, tree arg1,
+						  bool show_types)
+: gcc_rich_location (loc.m_combined_loc),
   m_label_for_arg0 (arg0, arg1),
   m_label_for_arg1 (arg1, arg0)
 {
-  maybe_add_expr (arg0, &m_label_for_arg0);
-  maybe_add_expr (arg1, &m_label_for_arg1);
+  /* Default (above) to using the combined loc.
+     If we location information for the operator and for both arguments,
+     then split them all out.  */
+  if (EXPR_HAS_LOCATION (arg0)
+      && EXPR_HAS_LOCATION (arg1)
+      && loc.m_operator_loc != UNKNOWN_LOCATION)
+    {
+      set_range (0, loc.m_operator_loc, SHOW_RANGE_WITH_CARET);
+      maybe_add_expr (arg0, show_types ? &m_label_for_arg0 : NULL);
+      maybe_add_expr (arg1, show_types ? &m_label_for_arg1 : NULL);
+    }
 }
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 03cfe42..7423dc6 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -181,12 +181,16 @@ class maybe_range_label_for_tree_type_mismatch : public range_label
   tree m_other_expr;
 };
 
+struct op_location_t;
+
 /* FIXME.  Highlights the types of the arguments.  */
 
 class binary_op_rich_location : public gcc_rich_location
 {
  public:
-  binary_op_rich_location (location_t loc, tree arg0, tree arg1);
+  binary_op_rich_location (const op_location_t &loc,
+			   tree arg0, tree arg1,
+			   bool show_types);
 
  private:
   maybe_range_label_for_tree_type_mismatch m_label_for_arg0;
diff --git a/gcc/testsuite/c-c++-common/Wtautological-compare-ranges.c b/gcc/testsuite/c-c++-common/Wtautological-compare-ranges.c
new file mode 100644
index 0000000..7c3c02b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wtautological-compare-ranges.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-Wtautological-compare -fdiagnostics-show-caret" } */
+
+#define FOO foo
+
+void
+fn1 (int foo)
+{
+  if (foo == foo); /* { dg-warning "self-comparison always evaluates to true" } */
+  /* { dg-begin-multiline-output "" }
+   if (foo == foo);
+           ^~
+     { dg-end-multiline-output "" { target c } } */
+  /* { dg-begin-multiline-output "" }
+   if (foo == foo);
+       ~~~ ^~ ~~~
+     { dg-end-multiline-output "" { target c++ } } */
+}
+
+void
+fn2 (int foo)
+{
+  if (FOO == FOO); /* { dg-warning "self-comparison always evaluates to true" } */
+  /* { dg-begin-multiline-output "" }
+   if (FOO == FOO);
+           ^~
+     { dg-end-multiline-output "" } */
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index af5c63f..6dce26c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5907,4 +5907,27 @@ fndecl_built_in_p (const_tree node, built_in_function name)
 	  && DECL_FUNCTION_CODE (node) == name);
 }
 
+// FIXME: where to put this?
+/* FIXME:
+   OPERATOR_LOC is the location of the operator
+   COMBINED_LOC is the location of the compound expression.  */
+
+struct op_location_t
+{
+  // FIXME: eliminate this eventually:
+  op_location_t (location_t combined_loc)
+  : m_operator_loc (UNKNOWN_LOCATION), m_combined_loc (combined_loc)
+  {}
+
+  op_location_t (location_t operator_loc, location_t combined_loc)
+  : m_operator_loc (operator_loc), m_combined_loc (combined_loc)
+  {}
+
+  location_t m_operator_loc;
+  location_t m_combined_loc;
+
+  // FIXME
+  operator location_t () const { return m_combined_loc; }
+};
+
 #endif  /* GCC_TREE_H  */
-- 
1.8.5.3

