From bf7d9b5e42bd0dd15a26c8fbecfadf81fdba9b6a Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 11 Dec 2015 15:35:48 -0500
Subject: [PATCH 18/31] FIXME: experiment with rich_location for reporting C++
 FE operand issues

---
 gcc/cp/call.c               | 111 +++++++++++++++++++++++++++++---------------
 gcc/cp/typeck.c             |  12 +++--
 gcc/diagnostic-show-locus.c |   5 +-
 libcpp/include/line-map.h   |   2 +-
 4 files changed, 87 insertions(+), 43 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d77092b..d6c634d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "c-family/c-objc.h"
 #include "internal-fn.h"
+#include "gcc-rich-location.h"
 
 /* The various kinds of conversion.  */
 
@@ -157,7 +158,7 @@ static tree build_java_interface_fn_ref (tree, tree);
 		     /*c_cast_p=*/false, (COMPLAIN))
 static tree convert_like_real (conversion *, tree, tree, int, int, bool,
 			       bool, tsubst_flags_t);
-static void op_error (location_t, enum tree_code, enum tree_code, tree,
+static void op_error (rich_location *, enum tree_code, enum tree_code, tree,
 		      tree, tree, bool);
 static struct z_candidate *build_user_type_conversion_1 (tree, tree, int,
 							 tsubst_flags_t);
@@ -4451,7 +4452,7 @@ op_error_string (const char *errmsg, int ntypes, bool match)
 }
 
 static void
-op_error (location_t loc, enum tree_code code, enum tree_code code2,
+op_error (rich_location *richloc, enum tree_code code, enum tree_code code2,
 	  tree arg1, tree arg2, tree arg3, bool match)
 {
   const char *opname;
@@ -4465,65 +4466,80 @@ op_error (location_t loc, enum tree_code code, enum tree_code code2,
     {
     case COND_EXPR:
       if (flag_diagnostics_show_caret)
-	error_at (loc, op_error_string (G_("ternary %<operator?:%>"),
-					3, match),
-		  TREE_TYPE (arg1), TREE_TYPE (arg2), TREE_TYPE (arg3));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("ternary %<operator?:%>"),
+					    3, match),
+			   TREE_TYPE (arg1), TREE_TYPE (arg2),
+			   TREE_TYPE (arg3));
       else
-	error_at (loc, op_error_string (G_("ternary %<operator?:%> "
-					   "in %<%E ? %E : %E%>"), 3, match),
-		  arg1, arg2, arg3,
-		  TREE_TYPE (arg1), TREE_TYPE (arg2), TREE_TYPE (arg3));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("ternary %<operator?:%> "
+					       "in %<%E ? %E : %E%>"),
+					    3, match),
+			   arg1, arg2, arg3,
+			   TREE_TYPE (arg1), TREE_TYPE (arg2),
+			   TREE_TYPE (arg3));
       break;
+      /* FIXME: bump num ranges to 4? */
 
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
       if (flag_diagnostics_show_caret)
-	error_at (loc, op_error_string (G_("%<operator%s%>"), 1, match),
-		  opname, TREE_TYPE (arg1));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("%<operator%s%>"), 1, match),
+			   opname, TREE_TYPE (arg1));
       else
-	error_at (loc, op_error_string (G_("%<operator%s%> in %<%E%s%>"),
-					1, match),
-		  opname, arg1, opname, TREE_TYPE (arg1));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("%<operator%s%> in %<%E%s%>"),
+					    1, match),
+			   opname, arg1, opname, TREE_TYPE (arg1));
       break;
 
     case ARRAY_REF:
       if (flag_diagnostics_show_caret)
-	error_at (loc, op_error_string (G_("%<operator[]%>"), 2, match),
-		  TREE_TYPE (arg1), TREE_TYPE (arg2));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("%<operator[]%>"), 2, match),
+			   TREE_TYPE (arg1), TREE_TYPE (arg2));
       else
-	error_at (loc, op_error_string (G_("%<operator[]%> in %<%E[%E]%>"),
-					2, match),
-		  arg1, arg2, TREE_TYPE (arg1), TREE_TYPE (arg2));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("%<operator[]%> in %<%E[%E]%>"),
+					    2, match),
+			   arg1, arg2, TREE_TYPE (arg1), TREE_TYPE (arg2));
       break;
 
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       if (flag_diagnostics_show_caret)
-	error_at (loc, op_error_string (G_("%qs"), 1, match),
-		  opname, TREE_TYPE (arg1));
+	error_at_rich_loc (richloc, op_error_string (G_("%qs"), 1, match),
+			   opname, TREE_TYPE (arg1));
       else
-	error_at (loc, op_error_string (G_("%qs in %<%s %E%>"), 1, match),
-		  opname, opname, arg1, TREE_TYPE (arg1));
+	error_at_rich_loc (richloc,
+			   op_error_string (G_("%qs in %<%s %E%>"), 1, match),
+			   opname, opname, arg1, TREE_TYPE (arg1));
       break;
 
     default:
       if (arg2)
 	if (flag_diagnostics_show_caret)
-	  error_at (loc, op_error_string (G_("%<operator%s%>"), 2, match),
-		    opname, TREE_TYPE (arg1), TREE_TYPE (arg2));
+	  error_at_rich_loc (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%>"),
-					  2, match),
-		    opname, arg1, opname, arg2,
-		    TREE_TYPE (arg1), TREE_TYPE (arg2));
+	  error_at_rich_loc
+	    (richloc, op_error_string (G_("%<operator%s%> in %<%E %s %E%>"),
+				       2, match),
+	     opname, arg1, opname, arg2,
+	     TREE_TYPE (arg1), TREE_TYPE (arg2));
       else
 	if (flag_diagnostics_show_caret)
-	  error_at (loc, op_error_string (G_("%<operator%s%>"), 1, match),
-		    opname, TREE_TYPE (arg1));
+	  error_at_rich_loc (richloc, op_error_string (G_("%<operator%s%>"),
+						       1, match),
+			     opname, TREE_TYPE (arg1));
 	else
-	  error_at (loc, op_error_string (G_("%<operator%s%> in %<%s%E%>"),
-					  1, match),
-		    opname, opname, arg1, TREE_TYPE (arg1));
+	  error_at_rich_loc (richloc,
+			     op_error_string (G_("%<operator%s%> in %<%s%E%>"),
+					      1, match),
+			     opname, opname, arg1, TREE_TYPE (arg1));
       break;
     }
 }
@@ -4605,6 +4621,20 @@ conditional_conversion (tree e1, tree e2, tsubst_flags_t complain)
 				LOOKUP_IMPLICIT, complain);
 }
 
+/* FIXME.  */
+
+static void
+add_args (gcc_rich_location *richloc, tree arg1, tree arg2, tree arg3)
+{
+  gcc_assert (richloc);
+  if (arg1)
+    richloc->maybe_add_expr (arg1);
+  if (arg2)
+    richloc->maybe_add_expr (arg2);
+  if (arg3)
+    richloc->maybe_add_expr (arg3);
+}
+
 /* Implement [expr.cond].  ARG1, ARG2, and ARG3 are the three
    arguments to the conditional expression.  */
 
@@ -5037,7 +5067,10 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 	{
           if (complain & tf_error)
             {
-              op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE);
+	      gcc_rich_location richloc (loc);
+	      add_args (&richloc, arg1, arg2, arg3);
+	      op_error (&richloc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3,
+			FALSE);
               print_z_candidates (loc, candidates);
             }
 	  return error_mark_node;
@@ -5664,7 +5697,9 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
 		  {
 		    /* ... Otherwise, report the more generic
 		       "no matching operator found" error */
-		    op_error (loc, code, code2, arg1, arg2, arg3, FALSE);
+		    gcc_rich_location richloc (loc);
+		    add_args (&richloc, arg1, arg2, arg3);
+		    op_error (&richloc, code, code2, arg1, arg2, arg3, FALSE);
 		    print_z_candidates (loc, candidates);
 		  }
 	    }
@@ -5679,7 +5714,9 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
 	{
 	  if (complain & tf_error)
 	    {
-	      op_error (loc, code, code2, arg1, arg2, arg3, TRUE);
+	      gcc_rich_location richloc (loc);
+	      add_args (&richloc, arg1, arg2, arg3);
+	      op_error (&richloc, code, code2, arg1, arg2, arg3, TRUE);
 	      print_z_candidates (loc, candidates);
 	    }
 	  result = error_mark_node;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3704b88..19ce385 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4970,9 +4970,15 @@ cp_build_binary_op (location_t location,
   if (!result_type)
     {
       if (complain & tf_error)
-	error_at (location,
-		  "invalid operands of types %qT and %qT to binary %qO",
-		  TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
+	{
+	  gcc_rich_location richloc (location);
+	  richloc.maybe_add_expr (orig_op0);
+	  richloc.maybe_add_expr (orig_op1);
+	  error_at_rich_loc
+	    (&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/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 11588b0..8271eb1 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -1135,7 +1135,8 @@ layout::print_newline ()
 /* Return true if (ROW/COLUMN) is within a range of the layout.
    If it returns true, OUT_STATE is written to, with the
    range index, and whether we should draw the caret at
-   (ROW/COLUMN) (as opposed to an underline).  */
+   (ROW/COLUMN) (as opposed to an underline).
+   In the case of overlapping ranges, use the final range.  */
 
 bool
 layout::get_state_at_point (/* Inputs.  */
@@ -1146,7 +1147,7 @@ layout::get_state_at_point (/* Inputs.  */
 {
   layout_range *range;
   int i;
-  FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+  FOR_EACH_VEC_ELT_REVERSE (m_layout_ranges, i, range)
     {
       if (range->contains_point (row, column))
 	{
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index da7a5fa..b73d5d4 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1400,7 +1400,7 @@ class rich_location
   fixit_hint *get_fixit_hint (int idx) const { return m_fixit_hints[idx]; }
 
 public:
-  static const int MAX_RANGES = 3;
+  static const int MAX_RANGES = 4;
   static const int MAX_FIXIT_HINTS = 2;
 
 protected:
-- 
1.8.5.3

