From be95ef8a8d8b7e9df84b04d8608d05697b5ecebb Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 30 Nov 2015 14:47:39 -0500
Subject: [PATCH 07/20] FIXME: fixups for creating v4 (has rough ChangeLog)

gcc/cp/ChangeLog:
	* parser.c (cp_parser_string_literal): Use get_finish; whitespace fix.
	(cp_parser_postfix_dot_deref_expression): Generate and set a location.
	(cp_parser_unary_expression): Call set_location in two places.
	(cp_parser_new_expression): Use get_finish.
	(cp_parser_assignment_expression): Call set_location.
	* semantics.c (finish_increment_expr): Build a location; call
	set_location.
	(finish_unary_op_expr): Build a location; call set_location.
	Convert local "result" to a cp_expr.
	* typeck.c (build_class_member_access_expr): Revert changes?
	(build_nop): Preserve the location of EXPR.

gcc/ChangeLog:
	* tree.h (get_finish): New function.
---
 gcc/cp/parser.c    | 30 +++++++++++++++++++++---------
 gcc/cp/semantics.c | 32 ++++++++++++++++++++++++--------
 gcc/cp/typeck.c    |  9 ++-------
 gcc/tree.h         |  9 +++++++++
 4 files changed, 56 insertions(+), 24 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1703ad3..71fc4db 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3823,9 +3823,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
       /* A string literal built by concatenation has its caret=start at
 	 the start of the initial string, and its finish at the finish of
 	 the final string literal.  */
-      loc = make_location (loc, loc,
-			   get_range_from_loc (line_table,
-					       last_tok_loc).m_finish);
+      loc = make_location (loc, loc, get_finish (last_tok_loc));
 
       strs = (cpp_string *) obstack_finish (&str_ob);
     }
@@ -6968,6 +6966,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
   bool dependent_p;
   bool pseudo_destructor_p;
   tree scope = NULL_TREE;
+  location_t start_loc = postfix_expression.get_start ();
 
   /* If this is a `->' operator, dereference the pointer.  */
   if (token_type == CPP_DEREF)
@@ -7110,10 +7109,19 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	  if (parser->scope && name && BASELINK_P (name))
 	    adjust_result_of_qualified_name_lookup
 	      (name, parser->scope, scope);
+	  /* Build a location e.g.:
+	       ptr->field
+	       ~~~^~~~~~~
+	     where the caret is at the deref token, ranging from
+	     the start of postfix_expression to the end of the field name.  */
+	  location_t combined_loc
+	    = make_location (input_location, start_loc,
+			     get_finish (token->location));
 	  postfix_expression
 	    = finish_class_member_access_expr (postfix_expression, name,
 					       template_p, 
 					       tf_warning_or_error);
+	  protected_set_expr_location (postfix_expression, combined_loc);
 	}
     }
 
@@ -7686,6 +7694,9 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 	  expression = build_x_indirect_ref (loc, cast_expression,
 					     RO_UNARY_STAR,
                                              complain);
+          /* TODO: build_x_indirect_ref does not always honor the
+             location, so ensure it is set.  */
+          expression.set_location (loc);
 	  break;
 
 	case ADDR_EXPR:
@@ -7695,6 +7706,9 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 	  expression = build_x_unary_op (loc, unary_operator,
 					 cast_expression,
                                          complain);
+          /* TODO: build_x_unary_op does not always honor the location,
+             so ensure it is set.  */
+          expression.set_location (loc);
 	  break;
 
 	case PREINCREMENT_EXPR:
@@ -7885,8 +7899,7 @@ cp_parser_new_expression (cp_parser* parser)
          with caret == start at the start of the "new" token, and the end
          at the end of the final token we consumed.  */
       cp_token *end_tok = cp_lexer_previous_token (parser->lexer);
-      location_t end_loc = get_range_from_loc (line_table,
-                                               end_tok->location).m_finish;
+      location_t end_loc = get_finish (end_tok->location);
       location_t combined_loc = make_location (start_loc, start_loc, end_loc);
 
       /* Create a representation of the new-expression.  */
@@ -8818,7 +8831,6 @@ cp_parser_assignment_expression (cp_parser* parser, cp_id_kind * pidk,
 	  if (assignment_operator != ERROR_MARK)
 	    {
 	      bool non_constant_p;
-	      location_t saved_input_location;
 
 	      /* Parse the right-hand side of the assignment.  */
 	      cp_expr rhs = cp_parser_initializer_clause (parser,
@@ -8842,13 +8854,13 @@ cp_parser_assignment_expression (cp_parser* parser, cp_id_kind * pidk,
 	      loc = make_location (loc,
 				   expr.get_start (),
 				   rhs.get_finish ());
-	      saved_input_location = input_location;
-	      input_location = loc;
 	      expr = build_x_modify_expr (loc, expr,
 					  assignment_operator,
 					  rhs,
 					  complain_flags (decltype_p));
-	      input_location = saved_input_location;
+              /* TODO: build_x_modify_expr doesn't honor the location,
+                 so we must set it here.  */
+              expr.set_location (loc);
 	    }
 	}
     }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 57d3458..d2db52f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2463,11 +2463,19 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 cp_expr
 finish_increment_expr (cp_expr expr, enum tree_code code)
 {
-  /* input_location holds the location of the trailing operator token.  */
-  cp_expr result = build_x_unary_op (input_location, code, expr,
+  /* input_location holds the location of the trailing operator token.
+     Build a location of the form:
+       expr++
+       ~~~~^~
+     with the caret at the operator token, ranging from the start
+     of EXPR to the end of the operator token.  */
+  location_t combined_loc = make_location (input_location,
+					   expr.get_start (),
+					   get_finish (input_location));
+  cp_expr result = build_x_unary_op (combined_loc, code, expr,
 				     tf_warning_or_error);
-  result.set_range (expr.get_start (),
-		    get_range_from_loc (line_table, input_location).m_finish);
+  /* TODO: build_x_unary_op doesn't honor the location, so set it here.  */
+  result.set_location (combined_loc);
   return result;
 }
 
@@ -2566,13 +2574,21 @@ cp_expr
 finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
 		      tsubst_flags_t complain)
 {
+  /* Build a location of the form:
+       ++expr
+       ^~~~~~
+     with the caret at the operator token, ranging from the start
+     of the operator token to the end of EXPR.  */
   location_t combined_loc = make_location (op_loc,
 					   op_loc, expr.get_finish ());
-  tree result = build_x_unary_op (combined_loc, code, expr, complain);
+  cp_expr result = build_x_unary_op (combined_loc, code, expr, complain);
+  /* TODO: build_x_unary_op doesn't always honor the location.  */
+  result.set_location (combined_loc);
+
   tree result_ovl, expr_ovl;
 
   if (!(complain & tf_warning))
-    return cp_expr (result, combined_loc);
+    return result;
 
   result_ovl = result;
   expr_ovl = expr;
@@ -2582,7 +2598,7 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
 
   if (!CONSTANT_CLASS_P (expr_ovl)
       || TREE_OVERFLOW_P (expr_ovl))
-    return cp_expr (result, combined_loc);
+    return result;
 
   if (!processing_template_decl)
     result_ovl = cp_fully_fold (result_ovl);
@@ -2590,7 +2606,7 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
   if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl))
     overflow_warning (combined_loc, result_ovl);
 
-  return cp_expr (result, combined_loc);
+  return result;
 }
 
 /* Finish a compound-literal expression.  TYPE is the type to which
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0708c6f..f3a3f90 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2435,12 +2435,7 @@ build_class_member_access_expr (cp_expr object, tree member,
 	  member_type = cp_build_qualified_type (member_type, type_quals);
 	}
 
-      location_t combined_loc =
-	make_location (input_location,
-		       object.get_start (),
-		       get_range_from_loc (line_table,
-					   input_location).m_finish);
-      result = build3_loc (combined_loc, COMPONENT_REF, member_type,
+      result = build3_loc (input_location, COMPONENT_REF, member_type,
 			   object, member, NULL_TREE);
 
       /* Mark the expression const or volatile, as appropriate.  Even
@@ -5434,7 +5429,7 @@ build_nop (tree type, tree expr)
 {
   if (type == error_mark_node || error_operand_p (expr))
     return expr;
-  return build1 (NOP_EXPR, type, expr);
+  return build1_loc (EXPR_LOCATION (expr), NOP_EXPR, type, expr);
 }
 
 /* Take the address of ARG, whatever that means under C++ semantics.
diff --git a/gcc/tree.h b/gcc/tree.h
index 7919860..1b3442a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5338,6 +5338,15 @@ type_with_alias_set_p (const_tree t)
 }
 
 extern location_t get_pure_location (location_t loc);
+
+/* Get the endpoint of any range encoded within location LOC.  */
+
+static inline location_t
+get_finish (location_t loc)
+{
+  return get_range_from_loc (line_table, loc).m_finish;
+}
+
 extern location_t set_block (location_t loc, tree block);
 
 extern void gt_ggc_mx (tree &);
-- 
1.8.5.3

