From c5647c9bf44a3de7c28bcd1a6d5f1d1c2502ac05 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 25 Oct 2018 21:31:40 -0400
Subject: [PATCH 29/35] FIXME: WIP on binary ops

---
 gcc/cp/call.c                                    | 25 +++++++++++--------
 gcc/cp/cp-tree.h                                 | 31 +++++++++++++++++++++---
 gcc/cp/parser.c                                  |  3 ++-
 gcc/cp/typeck.c                                  |  2 +-
 gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C |  7 ++++--
 5 files changed, 51 insertions(+), 17 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 641ae55..d0e54b2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -166,8 +166,8 @@ static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
 		     /*c_cast_p=*/false, (COMPLAIN))
 static tree convert_like_real (conversion *, tree, tree, int, bool,
 			       bool, tsubst_flags_t);
-static void op_error (location_t, enum tree_code, enum tree_code, tree,
-		      tree, tree, bool);
+static void op_error (const op_location_t &, 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);
 static void print_z_candidate (location_t, const char *, struct z_candidate *);
@@ -4707,7 +4707,8 @@ 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 (const op_location_t &loc,
+	  enum tree_code code, enum tree_code code2,
 	  tree arg1, tree arg2, tree arg3, bool match)
 {
   bool assop = code == MODIFY_EXPR;
@@ -4763,9 +4764,10 @@ op_error (location_t loc, enum tree_code code, enum tree_code code2,
 	if (flag_diagnostics_show_caret)
 	  {
 	    if (EXPR_HAS_LOCATION (arg1)
-		&& EXPR_HAS_LOCATION (arg2))
+		&& EXPR_HAS_LOCATION (arg2)
+		&& loc.m_operator_loc != UNKNOWN_LOCATION)
 	      {
-		binary_op_rich_location richloc (get_pure_location (loc), //FIXME
+		binary_op_rich_location richloc (loc.m_operator_loc,
 						 arg1, arg2);
 		error_at (&richloc,
 			  op_error_string (G_("%<operator%s%>"), 2, match),
@@ -4873,7 +4875,8 @@ conditional_conversion (tree e1, tree e2, tsubst_flags_t complain)
    arguments to the conditional expression.  */
 
 static tree
-build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
+build_conditional_expr_1 (const op_location_t &loc,
+			  tree arg1, tree arg2, tree arg3,
                           tsubst_flags_t complain)
 {
   tree arg2_type;
@@ -5467,7 +5470,8 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 /* Wrapper for above.  */
 
 tree
-build_conditional_expr (location_t loc, tree arg1, tree arg2, tree arg3,
+build_conditional_expr (const op_location_t &loc,
+			tree arg1, tree arg2, tree arg3,
                         tsubst_flags_t complain)
 {
   tree ret;
@@ -5656,8 +5660,9 @@ op_is_ordered (tree_code code)
 }
 
 static tree
-build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
-		tree arg2, tree arg3, tree *overload, tsubst_flags_t complain)
+build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
+		tree arg1, tree arg2, tree arg3, tree *overload,
+		tsubst_flags_t complain)
 {
   struct z_candidate *candidates = 0, *cand;
   vec<tree, va_gc> *arglist;
@@ -6136,7 +6141,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
 /* Wrapper for above.  */
 
 tree
-build_new_op (location_t loc, enum tree_code code, int flags,
+build_new_op (const op_location_t &loc, enum tree_code code, int flags,
 	      tree arg1, tree arg2, tree arg3,
 	      tree *overload, tsubst_flags_t complain)
 {
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 26ded3a..3242a81 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -109,6 +109,29 @@ 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
 {
@@ -6046,7 +6069,8 @@ extern int raw_dump_id;
 extern bool check_dtor_name			(tree, tree);
 int magic_varargs_p				(tree);
 
-extern tree build_conditional_expr		(location_t, tree, tree, tree, 
+extern tree build_conditional_expr		(const op_location_t &,
+						 tree, tree, tree,
                                                  tsubst_flags_t);
 extern tree build_addr_func			(tree, tsubst_flags_t);
 extern void set_flags_from_callee		(tree);
@@ -6071,7 +6095,8 @@ extern tree build_new_method_call		(tree, tree,
 extern tree build_special_member_call		(tree, tree,
 						 vec<tree, va_gc> **,
 						 tree, int, tsubst_flags_t);
-extern tree build_new_op			(location_t, enum tree_code,
+extern tree build_new_op			(const op_location_t &,
+						 enum tree_code,
 						 int, tree, tree, tree, tree *,
 						 tsubst_flags_t);
 extern tree build_op_call			(tree, vec<tree, va_gc> **,
@@ -7273,7 +7298,7 @@ extern tree cp_build_function_call_nary         (tree, tsubst_flags_t, ...)
 						ATTRIBUTE_SENTINEL;
 extern tree cp_build_function_call_vec		(tree, vec<tree, va_gc> **,
 						 tsubst_flags_t);
-extern tree build_x_binary_op			(location_t,
+extern tree build_x_binary_op			(const op_location_t &,
 						 enum tree_code, tree,
 						 enum tree_code, tree,
 						 enum tree_code, tree *,
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5d5c330..04a5180 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9375,7 +9375,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 	}
       else
         {
-          current.lhs = build_x_binary_op (combined_loc, current.tree_type,
+	  op_location_t op_loc (current.loc, combined_loc);
+	  current.lhs = build_x_binary_op (op_loc, current.tree_type,
                                            current.lhs, current.lhs_type,
                                            rhs, rhs_type, &overload,
                                            complain_flags (decltype_p));
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 50d1976..4643e18 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4101,7 +4101,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
    ARG2_CODE as ERROR_MARK.  */
 
 tree
-build_x_binary_op (location_t loc, enum tree_code code, tree arg1,
+build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1,
 		   enum tree_code arg1_code, tree arg2,
 		   enum tree_code arg2_code, tree *overload_p,
 		   tsubst_flags_t complain)
diff --git a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C
index 643f842..4a1059b 100644
--- a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C
+++ b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C
@@ -44,11 +44,14 @@ int test_3 (struct s param_s, struct t param_t)
 {
   return param_s && param_t; // { dg-error "no match for .operator" }
 
-  // FIXME: use correct underline for operator here:
 /* { dg-begin-multiline-output "" }
    return param_s && param_t;
-          ~~~~~~~ ^  ~~~~~~~
+          ~~~~~~~ ^~ ~~~~~~~
           |          |
           s          t
    { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   return param_s && param_t;
+          ~~~~~~~~^~~~~~~~~~
+   { dg-end-multiline-output "" } */
 }
-- 
1.8.5.3

