This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add extra location information - PR43486


This is a relatively large patch which tackles the difficult issue of
generating more sloc information in front-ends (in particular C and C++
front-ends), so that "static analyzers" based on GCC can get more useful
and detailed information.

This happens to be related/similar to the need mentioned in PR43486, hence
the mention of this PR in the subject line.

In my work, as I mentioned a few times in the past, this patch is the
first foundation for another patch, which will provide source navigation
capabilities in IDEs/editors, by generating source cross reference information
based on the C and C++ front-ends (introducing a new switch -fdump-xref).
Ideally I'd like to submit both patches.

Since this issue is more general, I have split my changes and introduced a new
tentative switch called -fextra-slocs, which is the subject of this email.

In order to provide more sloc info attached to nodes (and in particular
VAR_DECLs), there are basically two possibilities:

- the one mentioned in comment 4 of PR43486:
  << Jason Merrill 2010-03-23 01:51:34 UTC

  I suppose we could wrap rvalue uses in NOP_EXPR and lvalue uses in
  VIEW_CONVERT_EXPR.
  >>

  I investigated this option, and unfortunately this does not work
  because of folding occurring all over the place in the C and
  C++ front-ends, removing these extra EXPRs very early.

  So I opted for the second approach:
- Keep another data structure which will associate extra slocs with some
  node expressions. The idea is that since you can't associate slocs with
  VAR_DECLs in an expr, instead we store extra slocs in the containing
  expression node. For instance, all binary expressions (add ADD, MINUS, ...)
  will contain two extra slocs: one for the left hand side, and one for the
  right hand side of the expression. One extra sloc for unary operators,
  etc...
  I've used a hash table which associates an array of location_t to some
  expr nodes, which could then be used by static analysis passes (as done
  by my patch to implement a -fdump-xref switch).

I have attached the various patches, split in directories:
- difs.common contains the common parts, introducing the -fextra-slocs
  switch and the generic data structure/API to store/retrieve extra slocs
  (in tree.[hc])
- difs.c contains the C front-end specific parts and add lots of source
  location information, add some extra loc parameters to various parser
  functions, and store these extra slocs when -fextra-slocs is enabled
- difs.cp does the same thing for the C++ front-end and includes testsuite
  updates which are triggered by this patch, showing some of the immediate
  benefits/side effects of generating more accurate "primary" slocs in 
  some cases (the case of Class::Method () references, where we now want to
  reference the sloc pointing to Method rather than Class)

OK on principle? Or is the whole approach not suitable/doomed?

If OK on principle, I'd appreciate a C, C++ front-end maintainers, and
a general maintainer (for the common/general part) to review my patches in
more details, and hopefully give their review/OK.

Here is the ChangeLog (which will be split into the various directories of
course), patches are in attachment.

2012-09-18  Arnaud Charlet  <charlet@adacore.com>

	* tree.h, tree.c (stabilize_reference): Copy source locations.
	(sloc_struct, extra_slocs): New.
	(node_hash, node_eq): Implement extra_slocs hash table.
	(expr_locations, set_expr_locations, set_expr_location2,
	duplicate_expr_locations, expr_location_n): New functions.
	(EXPR_LOCATIONS, SET_EXPR_LOCATION2, SET_EXPR_LOCATIONS): New macros.
	* common.opt: New switch -fextra-slocs.

c/
	* c-parser.c (c_parser_expr_list): New parameter locs, num_locs.
	Set extra locations.
	(c_parser_attributes): Adjust calls to c_parser_expr_list.
	(c_parser_statement_after_labels): Adjust calls to c_finish_return with
	extra expr location.
	(c_parser_expr_no_commas, c_parser_conditional_expression,
	c_parser_binary_expression, c_parser_cast_expression,
	c_parser_unary_expression, c_parser_postfix_expression_after_primary,
	c_parser_expr_list): Set extra locations.
	(c_parser_postfix_expression): Remove extra semicolon.
	(c_parser_objc_keywordexpr): Adjust call to c_parser_expr_list.
	* c-typeck.c (c_finish_return): New parameter loc_expr.
	* c-tree.h (c_finish_return): Add location_t parameter.
	* c-decl.c (finish_function): Update call to c_finish_return.
	(build_function_declarator): Set ret->id_loc.
c-family/
	* c-common.c (c_fully_fold_internal): Copy extra locations on new node.
objc/
	* objc-act.c (objc_synthesize_getter): Update call to c_finish_return.
cp/
	* parser.c (cp_parser_unary_expression, cp_parser_binary_expression,
	cp_parser_question_colon_clause, cp_parser_assignment_expression,
	cp_parser_enumerator_definition): Set extra locations.
	(cp_parser_parenthesized_expression_list): Ditto. New parameters
	locs, num_locs.
	(cp_parser_parse_and_diagnose_invalid_typ): Adjust call to
	cp_parser_id_location.
	(cp_parser_userdef_char_literal, cp_parser_userdef_numeric_literal,
	cp_parser_userdef_string_literal, cp_parser_perform_range_for_lookup,
	cp_parser_range_for_member_function): Adjust calls to finish_call_expr.
	(cp_parser_primary_expression, cp_parser_postfix_dot_deref_expression,
	cp_parser_decltype, cp_parser_type_parameter,
	cp_parser_template_argument, cp_parser_omp_var_list_no_open): Adjust
	calls to cp_parser_id_expression.
	(cp_parser_id_expression, cp_parser_declarator_id): New parameter
	location_t *. Set location to proper sloc for class::method
	declarations.
	(cp_parser_postfix_expression): Set extra locations.
	Update calls to cp_parser_parenthesized_expression_list,
	build_new_method_call and finish_call_expr.
	(cp_parser_postfix_open_square_expression): Add extra locations for
	array refs (e.g. a[i]).
	(cp_parser_direct_declarator): Adjust call to cp_parser_declarator_id
	and adjust sloc of declarator.
	(cp_parser_new_placement, cp_parser_new_initializer,
	cp_parser_mem_initializer, cp_parser_initializer,
	cp_parser_attribute_list, cp_parser_functional_cast): Adjust call to
	cp_parser_parenthesized_expression_list.
	* typeck.c (build_c_cast): Ensure extra sloc information is preserved
	over this function.
	* call.c (build_over_call): New parameter loc.
	(build_new_function_call, build_operator_new_call, build_op_call_1,
	build_new_op_1, convert_like_real): Update call to build_over_call.
	(build_new_method_call, build_new_method_call_1, finish_call_expr):
	New parameter loc.
	(build_special_member_call): Update call to build_new_method_call.
	(perform_implicit_conversion_flags): Ensure line number
	information is preserved over this function.
	* method.c (locate_fn_flags): Update call to build_new_method_call.
	* class.c (build_self_reference): Update decl location of internal type.
	* cp-tree.h (build_new_method_call, finish_call_expr): New parameter
	loc.
	* pt.c (tsubst_copy_and_build): Update call to build_new_method_call
	and finish_call_expr.
	* init.c (build_new_1, build_dtor_call): Ditto.
	* semantics.c (finish_omp_barrier, finish_omp_flush,
	finish_omp_taskyield, finish_omp_taskwait): Ditto.
	(finish_call_expr): Ditto. New parameter loc.
	(finish_id_expression): Add sloc on decl.
testsuite/
	* g++.dg/warn/pr26785.C, g++.old-deja/g++.brendan/crash16.C: Update
	column numbers.
	* g++.dg/tc1/dr52.C: Update baseline.

Attachment: difs.common
Description: Text document

Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 190939)
+++ c-family/c-common.c	(working copy)
@@ -1440,7 +1440,10 @@ c_fully_fold_internal (tree expr, bool i
       TREE_NO_WARNING (ret) = 1;
     }
   if (ret != expr)
-    protected_set_expr_location (ret, loc);
+    {
+      protected_set_expr_location (ret, loc);
+      duplicate_expr_locations (ret, expr);
+    }
   return ret;
 }
 
Index: c/c-parser.c
===================================================================
--- c/c-parser.c	(revision 190939)
+++ c/c-parser.c	(working copy)
@@ -1186,7 +1186,8 @@ static struct c_expr c_parser_expression
 static struct c_expr c_parser_expression_conv (c_parser *);
 static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
 					 VEC(tree,gc) **,
-					 struct c_tree_loc_pair *);
+					 struct c_tree_loc_pair *, location_t *,
+					 int *);
 static void c_parser_omp_construct (c_parser *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
@@ -3586,7 +3587,7 @@ c_parser_attributes (c_parser *parser)
 		  tree tree_list;
 		  c_parser_consume_token (parser);
 		  expr_list = c_parser_expr_list (parser, false, true,
-						  NULL, NULL);
+						  NULL, NULL, NULL, NULL);
 		  tree_list = build_tree_list_vec (expr_list);
 		  attr_args = tree_cons (NULL_TREE, arg1, tree_list);
 		  release_tree_vector (expr_list);
@@ -3599,7 +3600,7 @@ c_parser_attributes (c_parser *parser)
 	      else
 		{
 		  expr_list = c_parser_expr_list (parser, false, true,
-						  NULL, NULL);
+						  NULL, NULL, NULL, NULL);
 		  attr_args = build_tree_list_vec (expr_list);
 		  release_tree_vector (expr_list);
 		}
@@ -4509,19 +4510,28 @@ c_parser_statement_after_labels (c_parse
 	  stmt = c_finish_bc_stmt (loc, &c_break_label, true);
 	  goto expect_semicolon;
 	case RID_RETURN:
-	  c_parser_consume_token (parser);
-	  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-	    {
-	      stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
-	      c_parser_consume_token (parser);
-	    }
-	  else
-	    {
-	      struct c_expr expr = c_parser_expression_conv (parser);
-	      mark_exp_read (expr.value);
-	      stmt = c_finish_return (loc, expr.value, expr.original_type);
-	      goto expect_semicolon;
-	    }
+	  {
+	    location_t ret_loc;
+	    c_parser_consume_token (parser);
+	    ret_loc = c_parser_peek_token (parser)->location;
+
+	    if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	      {
+	        stmt = c_finish_return (loc,
+				        ret_loc,
+				        NULL_TREE, NULL_TREE);
+	        c_parser_consume_token (parser);
+	      }
+	    else
+	      {
+		struct c_expr expr = c_parser_expression_conv (parser);
+		mark_exp_read (expr.value);
+		stmt = c_finish_return (loc,
+					ret_loc,
+					expr.value, expr.original_type);
+		goto expect_semicolon;
+	      }
+	  }
 	  break;
 	case RID_ASM:
 	  stmt = c_parser_asm_statement (parser);
@@ -5357,8 +5367,9 @@ c_parser_expr_no_commas (c_parser *parse
 {
   struct c_expr lhs, rhs, ret;
   enum tree_code code;
-  location_t op_location, exp_location;
+  location_t op_location, exp_location, locs[2];
   gcc_assert (!after || c_dialect_objc ());
+  locs[0] = c_parser_peek_token (parser)->location;
   lhs = c_parser_conditional_expression (parser, after);
   op_location = c_parser_peek_token (parser)->location;
   switch (c_parser_peek_token (parser)->type)
@@ -5406,6 +5417,8 @@ c_parser_expr_no_commas (c_parser *parse
   ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
 				 code, exp_location, rhs.value,
 				 rhs.original_type);
+  locs[1] = exp_location;
+  SET_EXPR_LOCATIONS (ret.value, locs, 2);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
@@ -5435,10 +5448,11 @@ static struct c_expr
 c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 {
   struct c_expr cond, exp1, exp2, ret;
-  location_t cond_loc, colon_loc, middle_loc;
+  location_t cond_loc, colon_loc, middle_loc, locs[3];
 
   gcc_assert (!after || c_dialect_objc ());
 
+  locs[0] = c_parser_peek_token (parser)->location;
   cond = c_parser_binary_expression (parser, after, PREC_NONE);
 
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
@@ -5446,6 +5460,7 @@ c_parser_conditional_expression (c_parse
   cond_loc = c_parser_peek_token (parser)->location;
   cond = default_function_array_read_conversion (cond_loc, cond);
   c_parser_consume_token (parser);
+  locs[1] = c_parser_peek_token (parser)->location;
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       tree eptype = NULL_TREE;
@@ -5466,12 +5481,14 @@ c_parser_conditional_expression (c_parse
       exp1.original_type = NULL;
       cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
       c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
+      locs[1] = UNKNOWN_LOCATION;
     }
   else
     {
       cond.value
 	= c_objc_common_truthvalue_conversion
 	(cond_loc, default_conversion (cond.value));
+      SET_EXPR_LOCATION2 (cond.value, locs[0]);
       c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
       mark_exp_read (exp1.value);
@@ -5491,6 +5508,7 @@ c_parser_conditional_expression (c_parse
     }
   {
     location_t exp2_loc = c_parser_peek_token (parser)->location;
+    locs[2] = exp2_loc;
     exp2 = c_parser_conditional_expression (parser, NULL);
     exp2 = default_function_array_read_conversion (exp2_loc, exp2);
   }
@@ -5506,6 +5524,7 @@ c_parser_conditional_expression (c_parse
     {
       tree t1, t2;
 
+      SET_EXPR_LOCATIONS (ret.value, locs, 3);
       /* If both sides are enum type, the default conversion will have
 	 made the type of the result be an integer type.  We want to
 	 remember the enum types we started with.  */
@@ -5610,9 +5629,10 @@ c_parser_binary_expression (c_parser *pa
     /* The operation on its left.  */
     enum tree_code op;
     /* The source location of this operation.  */
-    location_t loc;
+    location_t loc, loc2;
   } stack[NUM_PRECS];
   int sp;
+  location_t *locs;
   /* Location of the binary operator.  */
   location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
 #define POP								      \
@@ -5641,12 +5661,27 @@ c_parser_binary_expression (c_parser *pa
 						 stack[sp - 1].expr,	      \
 						 stack[sp].expr);	      \
     sp--;								      \
+    if (EXPR_P (stack[sp].expr.value))					      \
+      {									      \
+	location_t locs[2];                                                   \
+	if (stack[sp].expr.original_code == TREE_CODE (stack[sp].expr.value)) \
+	  locs[0] = stack[sp].loc2, locs[1] = stack[sp + 1].loc2;	      \
+	else                                                                  \
+	  locs[1] = stack[sp].loc2, locs[0] = stack[sp + 1].loc2;	      \
+	SET_EXPR_LOCATIONS (stack[sp].expr.value, locs, 2);                   \
+      }									      \
   } while (0)
   gcc_assert (!after || c_dialect_objc ());
-  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].loc2 = stack[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
   stack[0].prec = prec;
   sp = 0;
+  if (EXPR_P (stack[sp].expr.value))
+    {
+      locs = EXPR_LOCATIONS (stack[sp].expr.value);
+      if (locs) stack [sp].loc2 = *locs;
+    }
+
   while (true)
     {
       enum c_parser_prec oprec;
@@ -5765,10 +5800,16 @@ c_parser_binary_expression (c_parser *pa
 	}
       sp++;
       stack[sp].loc = binary_loc;
+      stack[sp].loc2 = c_parser_peek_token (parser)->location;
       stack[sp].expr = c_parser_cast_expression (parser, NULL);
       stack[sp].prec = oprec;
       stack[sp].op = ocode;
       stack[sp].loc = binary_loc;
+      if (EXPR_P (stack[sp].expr.value))
+	{
+	  locs = EXPR_LOCATIONS (stack[sp].expr.value);
+	  if (locs) stack [sp].loc2 = *locs;
+	}
     }
  out:
   while (sp > 0)
@@ -5826,11 +5867,12 @@ c_parser_cast_expression (c_parser *pars
 	location_t expr_loc = c_parser_peek_token (parser)->location;
 	expr = c_parser_cast_expression (parser, NULL);
 	expr = default_function_array_read_conversion (expr_loc, expr);
+	ret.value = c_cast_expr (cast_loc, type_name, expr.value);
+	SET_EXPR_LOCATION2 (ret.value, expr_loc);
+	ret.original_code = ERROR_MARK;
+	ret.original_type = NULL;
+	return ret;
       }
-      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      return ret;
     }
   else
     return c_parser_unary_expression (parser);
@@ -5886,24 +5928,32 @@ c_parser_unary_expression (c_parser *par
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+      ret = parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
+      return ret;
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+      ret = parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
+      return ret;
     case CPP_AND:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       mark_exp_read (op.value);
-      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+      ret = parser_build_unary_op (op_loc, ADDR_EXPR, op);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
+      return ret;
     case CPP_MULT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
       ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
       return ret;
     case CPP_PLUS:
       if (!c_dialect_objc () && !in_system_header)
@@ -5914,25 +5964,32 @@ c_parser_unary_expression (c_parser *par
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+      ret = parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
+      return ret;
     case CPP_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+      ret = parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
+      return ret;
     case CPP_COMPL:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+      ret = parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+      return ret;
     case CPP_NOT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+      ret = parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+      SET_EXPR_LOCATION2 (ret.value, exp_loc);
+      return ret;
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
       c_parser_consume_token (parser);
@@ -6232,7 +6289,7 @@ c_parser_postfix_expression (c_parser *p
 {
   struct c_expr expr, e1;
   struct c_type_name *t1, *t2;
-  location_t loc = c_parser_peek_token (parser)->location;;
+  location_t loc = c_parser_peek_token (parser)->location;
   expr.original_code = ERROR_MARK;
   expr.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
@@ -6875,9 +6932,14 @@ c_parser_postfix_expression_after_primar
 {
   struct c_expr orig_expr;
   tree ident, idx;
+  location_t locs [64];
+  location_t op2_loc;
+  int length = 63;
   struct c_tree_loc_pair sizeof_arg;
   VEC(tree,gc) *exprlist;
   VEC(tree,gc) *origtypes;
+
+  locs [0] = expr_loc;
   while (true)
     {
       location_t op_loc = c_parser_peek_token (parser)->location;
@@ -6886,10 +6948,20 @@ c_parser_postfix_expression_after_primar
 	case CPP_OPEN_SQUARE:
 	  /* Array reference.  */
 	  c_parser_consume_token (parser);
+	  locs [1] = c_parser_peek_token (parser)->location;
 	  idx = c_parser_expression (parser).value;
 	  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
 				     "expected %<]%>");
 	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  if (CAN_HAVE_LOCATION_P (expr.value))
+	    {
+	      if (TREE_CODE (expr.value) == ARRAY_REF)
+	        SET_EXPR_LOCATIONS (expr.value, locs, 2);
+	      else if (TREE_CODE (expr.value) == INDIRECT_REF
+		       && TREE_CODE (TREE_OPERAND (expr.value, 0))
+			    == POINTER_PLUS_EXPR)
+		SET_EXPR_LOCATIONS (TREE_OPERAND (expr.value, 0), locs, 2);
+	    }
 	  expr.original_code = ERROR_MARK;
 	  expr.original_type = NULL;
 	  break;
@@ -6898,10 +6970,13 @@ c_parser_postfix_expression_after_primar
 	  c_parser_consume_token (parser);
 	  sizeof_arg.expr = NULL_TREE;
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-	    exprlist = NULL;
+	    {
+	      exprlist = NULL;
+	      length = 0;
+	    }
 	  else
 	    exprlist = c_parser_expr_list (parser, true, false, &origtypes,
-					   &sizeof_arg);
+					   &sizeof_arg, locs + 1, &length);
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				     "expected %<)%>");
 	  orig_expr = expr;
@@ -6916,6 +6991,9 @@ c_parser_postfix_expression_after_primar
 	     "(" after the FUNCNAME, which is what we have now.    */
 	  expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
 						origtypes);
+	  if (CAN_HAVE_LOCATION_P (expr.value))
+	    SET_EXPR_LOCATIONS (expr.value, locs, length + 1);
+
 	  expr.original_code = ERROR_MARK;
 	  if (TREE_CODE (expr.value) == INTEGER_CST
 	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
@@ -6943,9 +7021,15 @@ c_parser_postfix_expression_after_primar
               expr.original_type = NULL;
 	      return expr;
 	    }
+	  op2_loc = c_parser_peek_token (parser)->location;
 	  c_parser_consume_token (parser);
 	  expr.value = build_component_ref (op_loc, expr.value, ident);
 	  expr.original_code = ERROR_MARK;
+	  if (CAN_HAVE_LOCATION_P (expr.value))
+	    {
+	      locs[1] = op2_loc;
+	      SET_EXPR_LOCATIONS (expr.value, locs, 2);
+	    }
 	  if (TREE_CODE (expr.value) != COMPONENT_REF)
 	    expr.original_type = NULL;
 	  else
@@ -6972,13 +7056,17 @@ c_parser_postfix_expression_after_primar
 	      expr.original_type = NULL;
 	      return expr;
 	    }
+	  op2_loc = c_parser_peek_token (parser)->location;
 	  c_parser_consume_token (parser);
-	  expr.value = build_component_ref (op_loc,
-					    build_indirect_ref (op_loc,
-								expr.value,
-								RO_ARROW),
-					    ident);
+          expr.value = build_indirect_ref (op_loc, expr.value, RO_ARROW),
+	  SET_EXPR_LOCATION2 (expr.value, locs[0]);
+	  expr.value = build_component_ref (op_loc, expr.value, ident);
 	  expr.original_code = ERROR_MARK;
+	  if (CAN_HAVE_LOCATION_P (expr.value))
+	    {
+	      locs[1] = op2_loc;
+	      SET_EXPR_LOCATIONS (expr.value, locs, 2);
+	    }
 	  if (TREE_CODE (expr.value) != COMPONENT_REF)
 	    expr.original_type = NULL;
 	  else
@@ -6997,6 +7085,7 @@ c_parser_postfix_expression_after_primar
 	  expr = default_function_array_read_conversion (expr_loc, expr);
 	  expr.value = build_unary_op (op_loc,
 				       POSTINCREMENT_EXPR, expr.value, 0);
+	  SET_EXPR_LOCATION2 (expr.value, expr_loc);
 	  expr.original_code = ERROR_MARK;
 	  expr.original_type = NULL;
 	  break;
@@ -7006,6 +7095,7 @@ c_parser_postfix_expression_after_primar
 	  expr = default_function_array_read_conversion (expr_loc, expr);
 	  expr.value = build_unary_op (op_loc,
 				       POSTDECREMENT_EXPR, expr.value, 0);
+	  SET_EXPR_LOCATION2 (expr.value, expr_loc);
 	  expr.original_code = ERROR_MARK;
 	  expr.original_type = NULL;
 	  break;
@@ -7073,11 +7163,13 @@ c_parser_expression_conv (c_parser *pars
 static VEC(tree,gc) *
 c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
 		    VEC(tree,gc) **p_orig_types,
-		    struct c_tree_loc_pair *sizeof_arg)
+		    struct c_tree_loc_pair *sizeof_arg,
+		    location_t *locs, int *num_locs)
 {
   VEC(tree,gc) *ret;
   VEC(tree,gc) *orig_types;
   struct c_expr expr;
+  int i = 0;
   location_t loc = c_parser_peek_token (parser)->location;
   location_t sizeof_arg_loc = UNKNOWN_LOCATION;
 
@@ -7095,6 +7187,9 @@ c_parser_expr_list (c_parser *parser, bo
     expr = default_function_array_read_conversion (loc, expr);
   if (fold_p)
     expr.value = c_fully_fold (expr.value, false, NULL);
+  if (locs && i < *num_locs)
+    locs [i++] = loc;
+
   VEC_quick_push (tree, ret, expr.value);
   if (orig_types != NULL)
     VEC_quick_push (tree, orig_types, expr.original_type);
@@ -7115,6 +7210,8 @@ c_parser_expr_list (c_parser *parser, bo
       VEC_safe_push (tree, gc, ret, expr.value);
       if (orig_types != NULL)
 	VEC_safe_push (tree, gc, orig_types, expr.original_type);
+      if (locs && i < *num_locs)
+	locs [i++] = loc;
     }
   if (sizeof_arg != NULL)
     {
@@ -7132,6 +7229,8 @@ c_parser_expr_list (c_parser *parser, bo
     }
   if (orig_types != NULL)
     *p_orig_types = orig_types;
+  if (locs)
+    *num_locs = i;
   return ret;
 }
 
@@ -8209,7 +8308,7 @@ c_parser_objc_keywordexpr (c_parser *par
 {
   tree ret;
   VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true,
-						NULL, NULL);
+						NULL, NULL, NULL, NULL);
   if (VEC_length (tree, expr_list) == 1)
     {
       /* Just return the expression, remove a level of
Index: c/c-typeck.c
===================================================================
--- c/c-typeck.c	(revision 190939)
+++ c/c-typeck.c	(working copy)
@@ -8627,11 +8627,13 @@ c_finish_goto_ptr (location_t loc, tree
 
 /* Generate a C `return' statement.  RETVAL is the expression for what
    to return, or a null pointer for `return;' with no value.  LOC is
-   the location of the return statement.  If ORIGTYPE is not NULL_TREE, it
+   the location of the return statement.  LOC_EXPR is the location of the
+   return expression, if any.  If ORIGTYPE is not NULL_TREE, it
    is the original type of RETVAL.  */
 
 tree
-c_finish_return (location_t loc, tree retval, tree origtype)
+c_finish_return (location_t loc, location_t loc_expr, tree retval,
+		 tree origtype)
 {
   tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
   bool no_warning = false;
@@ -8747,6 +8749,12 @@ c_finish_return (location_t loc, tree re
 
       retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
       SET_EXPR_LOCATION (retval, loc);
+      {
+	location_t locs[2];
+	locs[0] = loc;
+	locs[1] = loc_expr;
+	SET_EXPR_LOCATIONS (retval, locs, 2);
+      }
 
       if (warn_sequence_point)
 	verify_sequence_points (retval);
Index: c/c-tree.h
===================================================================
--- c/c-tree.h	(revision 190939)
+++ c/c-tree.h	(working copy)
@@ -635,7 +635,7 @@ extern tree c_begin_stmt_expr (void);
 extern tree c_finish_stmt_expr (location_t, tree);
 extern tree c_process_expr_stmt (location_t, tree);
 extern tree c_finish_expr_stmt (location_t, tree);
-extern tree c_finish_return (location_t, tree, tree);
+extern tree c_finish_return (location_t, location_t, tree, tree);
 extern tree c_finish_bc_stmt (location_t, tree *, bool);
 extern tree c_finish_goto_label (location_t, tree);
 extern tree c_finish_goto_ptr (location_t, tree);
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(revision 190939)
+++ c/c-decl.c	(working copy)
@@ -8365,7 +8365,8 @@ finish_function (void)
 	 annotate_one_with_locus.  A cleaner solution might be to
 	 ensure ! should_carry_locus_p (stmt), but that needs a flag.
       */
-      c_finish_return (BUILTINS_LOCATION, integer_zero_node, NULL_TREE);
+      c_finish_return (BUILTINS_LOCATION, BUILTINS_LOCATION,
+		       integer_zero_node, NULL_TREE);
     }
 
   /* Tie off the statement tree for this function.  */
@@ -8738,6 +8739,7 @@ build_function_declarator (struct c_arg_
   ret->kind = cdk_function;
   ret->declarator = target;
   ret->u.arg_info = args;
+  ret->id_loc = target->id_loc;
   return ret;
 }
 
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 190939)
+++ objc/objc-act.c	(working copy)
@@ -7314,7 +7314,7 @@ objc_synthesize_getter (tree klass, tree
 #ifdef OBJCPLUS
   finish_return_stmt (ret_val);
 #else
-  c_finish_return (location, ret_val, NULL_TREE);
+  c_finish_return (location, location, ret_val, NULL_TREE);
 #endif
 
   add_stmt (c_end_compound_stmt (location, body, true));

Attachment: difs.cp
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]