Patchwork [C++] PR 44516

login
register
mail settings
Submitter Paolo Carlini
Date May 15, 2012, 8:56 p.m.
Message ID <4FB2C307.6090509@oracle.com>
Download mbox | patch
Permalink /patch/159450/
State New
Headers show

Comments

Paolo Carlini - May 15, 2012, 8:56 p.m.
Hi,

On 05/15/2012 08:53 PM, Jason Merrill wrote:
> On 05/14/2012 07:17 PM, Paolo Carlini wrote:
>> @@ -5670,7 +5672,8 @@ build_x_compound_expr_from_list (tree list, expr_l
>>       return error_mark_node;
>>
>>         for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list))
>> -    expr = build_x_compound_expr (expr, TREE_VALUE (list),
>> +    expr = build_x_compound_expr (EXPR_LOC_OR_HERE (expr), expr,
>> +                      TREE_VALUE (list),
>>                                         complain);
>
> For a COMPOUND_EXPR, I think the relevant location is that of the 
> comma, and since we don't have that location I think the location of 
> the second expression is a closer approximation.
Ok, should be fixed now. I think I got the location of the comma right 
in the parser, but then was indeed unsure about the best thing to do 
here. Should have asked explicitly.
> Note that when copying the location from one expression to another, 
> EXPR_LOC_OR_HERE will change UNKNOWN_LOCATION to input_location, 
> whereas EXPR_LOCATION will leave it alone.
Thanks for the useful clarification.

I'm trying to put it to good use in the new patch below, which 
additionally takes care of build_min_non_dep: if I understand correctly, 
for all the uses of those, similarly to the build_x_compound_expr 
callers above, when copying the location we want EXPR_LOCATION (indeed, 
in my experiments, the source expr turns out to not have a location 
quite a few times and trying to use EXPR_LOC_OR_HERE leads to diagnostic 
regressions: concrete example, build_x_binary_op vs 
libstdc++-v3/testsuite/20_util/bind/ref_neg.cc)

Tested x86_64-linux.

Thanks!
Paolo.

/////////////////////////
gcc/cp
2012-05-15  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44516
	* typeck.c (build_x_array_ref, build_x_conditional_expr,
	build_x_compound_expr, build_x_modify_expr): Add location_t parameter.
	(finish_class_member_access_expr, build_x_indirect_ref,
	build_x_binary_op, build_x_compound_expr_from_list,
	build_x_compound_expr_from_vec): Adjust callers.
	* tree.c (build_min_nt_loc, build_min_non_dep_loc): New.
	(build_min_nt, build_min_non_dep): Remove.
	* typeck2.c (build_x_arrow): Adjust callers.
	* pt.c (tsubst_qualified_id, tsubst_omp_for_iterator,
	tsubst_copy_and_build): Likewise.
	* semantics.c (finish_mem_initializers, handle_omp_for_class_iterator,
	 finish_omp_atomic): Likewise.
	* decl2.c (grok_array_decl, build_anon_union_vars): Adjust.
	* parser.c (cp_parser_question_colon_clause,
	cp_parser_assignment_expression, cp_parser_expression,
	cp_parser_template_id, cp_parser_omp_for_loop): Likewise.
	* cp-tree.h: Update.

gcc/testsuite
2012-05-15  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44516
	* g++.dg/parse/error48.C: New.
	* g++.dg/template/crash89.C: Adjust dg-error line numbers.

libstdc++
2012-05-15  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44516
	* testsuite/20_util/ratio/cons/cons_overflow_neg.cc: Adjust
	dg-error line number.
Jason Merrill - May 15, 2012, 10:11 p.m.
On 05/15/2012 04:56 PM, Paolo Carlini wrote:
> @@ -2753,7 +2754,8 @@ build_x_indirect_ref (location_t loc, tree expr, r
>       rval = cp_build_indirect_ref (expr, errorstring, complain);
>
>     if (processing_template_decl&&  rval != error_mark_node)
> -    return build_min_non_dep (INDIRECT_REF, rval, orig_expr);
> +    return build_min_non_dep_loc (EXPR_LOCATION (rval), INDIRECT_REF,

Shouldn't this use loc?  If rval comes from cp_build_indirect_ref, it 
might not have the right location.

> @@ -3621,15 +3623,16 @@ build_x_binary_op (location_t loc, enum tree_code
>      warn_about_parentheses (code, arg1_code, orig_arg1, arg2_code, orig_arg2);
>
>    if (processing_template_decl && expr != error_mark_node)
> -    return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
> -
> +    return build_min_non_dep_loc (EXPR_LOCATION (expr), code, expr,

Likewise.  Similarly in build_x_array_ref, build_x_unary_op, 
build_x_conditional_expr, build_x_compound_expr.

I still see a lot of EXPR_LOC_OR_HERE in the patch, is that deliberate?

Jason
Paolo Carlini - May 15, 2012, 10:44 p.m.
Hi,

On 05/16/2012 12:11 AM, Jason Merrill wrote:
> On 05/15/2012 04:56 PM, Paolo Carlini wrote:
>> @@ -2753,7 +2754,8 @@ build_x_indirect_ref (location_t loc, tree expr, r
>>       rval = cp_build_indirect_ref (expr, errorstring, complain);
>>
>>     if (processing_template_decl&&  rval != error_mark_node)
>> -    return build_min_non_dep (INDIRECT_REF, rval, orig_expr);
>> +    return build_min_non_dep_loc (EXPR_LOCATION (rval), INDIRECT_REF,
>
> Shouldn't this use loc?  If rval comes from cp_build_indirect_ref, it 
> might not have the right location.
>
>> @@ -3621,15 +3623,16 @@ build_x_binary_op (location_t loc, enum 
>> tree_code
>>      warn_about_parentheses (code, arg1_code, orig_arg1, arg2_code, 
>> orig_arg2);
>>
>>    if (processing_template_decl && expr != error_mark_node)
>> -    return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
>> -
>> +    return build_min_non_dep_loc (EXPR_LOCATION (expr), code, expr,
>
> Likewise.  Similarly in build_x_array_ref, build_x_unary_op, 
> build_x_conditional_expr, build_x_compound_expr.
I can't change the build_min_non_dep_loc call in build_x_binary_op to 
simply use loc, that causes the diagnostic regression I mentioned 
before. Sorry, I wasn't clear in my previous message, it happens when 
one "naturally" just passes loc, not the EXPR_LOCATION from the 
intermediate expr. Indeed, in all the calls you mentioned I naturally 
passed a couple of days ago loc in my local tree, then when I saw that 
library testcase with the wrong location in some error messages I 
stopped. Today, I fooled myself into believing that I should have passes 
the location via EXPR_LOCATION from the intermediate expr and tried 
quickly to prepare something.

This requires more analysis.

Is it Ok with you if we return to a patch only touching the 
build_min_nt_locs?

> I still see a lot of EXPR_LOC_OR_HERE in the patch, is that deliberate?

Now that you are asking, I can re-analyze those which I added a couple 
of days ago.

Paolo.
Jason Merrill - May 15, 2012, 11:36 p.m.
On 05/15/2012 06:44 PM, Paolo Carlini wrote:
> I can't change the build_min_non_dep_loc call in build_x_binary_op to
> simply use loc, that causes the diagnostic regression I mentioned
> before. Sorry, I wasn't clear in my previous message, it happens when
> one "naturally" just passes loc, not the EXPR_LOCATION from the
> intermediate expr.

Because loc is wrong?

> Is it Ok with you if we return to a patch only touching the
> build_min_nt_locs?

It seems like as long as we're messing with this area we ought to finish 
the job, but if you want to split up the patch that's fine.

Jason

Patch

Index: libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc	(revision 187550)
+++ libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow_neg.cc	(working copy)
@@ -2,7 +2,7 @@ 
 // { dg-options "-std=gnu++0x" }
 // { dg-require-cstdint "" }
 
-// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation
+// Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -51,5 +51,5 @@  test04()
 // { dg-error "required from here" "" { target *-*-* } 46 }
 // { dg-error "denominator cannot be zero" "" { target *-*-* } 265 }
 // { dg-error "out of range" "" { target *-*-* } 266 }
-// { dg-error "overflow in constant expression" "" { target *-*-* } 61 }
+// { dg-error "overflow in constant expression" "" { target *-*-* } 62 }
 // { dg-prune-output "not a member" }
Index: gcc/testsuite/g++.dg/parse/error48.C
===================================================================
--- gcc/testsuite/g++.dg/parse/error48.C	(revision 0)
+++ gcc/testsuite/g++.dg/parse/error48.C	(revision 0)
@@ -0,0 +1,10 @@ 
+// PR c++/44516
+
+struct WebService {  };
+struct Server {  };
+
+void addHTTPService(Server const &server,
+		    WebService const *http)
+{
+  server += http; // { dg-error "10:no match for 'operator\\+='" }
+}
Index: gcc/testsuite/g++.dg/template/crash89.C
===================================================================
--- gcc/testsuite/g++.dg/template/crash89.C	(revision 187551)
+++ gcc/testsuite/g++.dg/template/crash89.C	(working copy)
@@ -1,8 +1,8 @@ 
 // PR c++/34397
 
-template<typename T, int = T()[0]> struct A
+template<typename T, int = T()[0]> struct A // { dg-error "subscripted|template" }
 {
   typedef A<T> B;
 };
 
-A<int> a; // { dg-error "subscripted|template|declaration" }
+A<int> a; // { dg-error "declaration" }
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 187551)
+++ gcc/cp/typeck.c	(working copy)
@@ -2536,7 +2536,8 @@  finish_class_member_access_expr (tree object, tree
 	  || (TREE_CODE (name) == SCOPE_REF
 	      && TYPE_P (TREE_OPERAND (name, 0))
 	      && dependent_type_p (TREE_OPERAND (name, 0))))
-	return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
+	return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,
+				 object, name, NULL_TREE);
       object = build_non_dependent_expr (object);
     }
   else if (c_dialect_objc ()
@@ -2686,9 +2687,9 @@  finish_class_member_access_expr (tree object, tree
 	    BASELINK_QUALIFIED_P (member) = 1;
 	  orig_name = member;
 	}
-      return build_min_non_dep (COMPONENT_REF, expr,
-				orig_object, orig_name,
-				NULL_TREE);
+      return build_min_non_dep_loc (EXPR_LOCATION (expr), COMPONENT_REF,
+				    expr, orig_object, orig_name,
+				    NULL_TREE);
     }
 
   return expr;
@@ -2743,7 +2744,7 @@  build_x_indirect_ref (location_t loc, tree expr, r
       if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr)))
 	return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
       if (type_dependent_expression_p (expr))
-	return build_min_nt (INDIRECT_REF, expr);
+	return build_min_nt_loc (loc, INDIRECT_REF, expr);
       expr = build_non_dependent_expr (expr);
     }
 
@@ -2753,7 +2754,8 @@  build_x_indirect_ref (location_t loc, tree expr, r
     rval = cp_build_indirect_ref (expr, errorstring, complain);
 
   if (processing_template_decl && rval != error_mark_node)
-    return build_min_non_dep (INDIRECT_REF, rval, orig_expr);
+    return build_min_non_dep_loc (EXPR_LOCATION (rval), INDIRECT_REF,
+				  rval, orig_expr);
   else
     return rval;
 }
@@ -3597,7 +3599,7 @@  build_x_binary_op (location_t loc, enum tree_code
     {
       if (type_dependent_expression_p (arg1)
 	  || type_dependent_expression_p (arg2))
-	return build_min_nt (code, arg1, arg2);
+	return build_min_nt_loc (loc, code, arg1, arg2);
       arg1 = build_non_dependent_expr (arg1);
       arg2 = build_non_dependent_expr (arg2);
     }
@@ -3621,15 +3623,16 @@  build_x_binary_op (location_t loc, enum tree_code
     warn_about_parentheses (code, arg1_code, orig_arg1, arg2_code, orig_arg2);
 
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
-
+    return build_min_non_dep_loc (EXPR_LOCATION (expr), code, expr,
+				  orig_arg1, orig_arg2);
   return expr;
 }
 
 /* Build and return an ARRAY_REF expression.  */
 
 tree
-build_x_array_ref (tree arg1, tree arg2, tsubst_flags_t complain)
+build_x_array_ref (location_t loc, tree arg1, tree arg2,
+		   tsubst_flags_t complain)
 {
   tree orig_arg1 = arg1;
   tree orig_arg2 = arg2;
@@ -3639,18 +3642,19 @@  tree
     {
       if (type_dependent_expression_p (arg1)
 	  || type_dependent_expression_p (arg2))
-	return build_min_nt (ARRAY_REF, arg1, arg2,
-			     NULL_TREE, NULL_TREE);
+	return build_min_nt_loc (loc, ARRAY_REF, arg1, arg2,
+				 NULL_TREE, NULL_TREE);
       arg1 = build_non_dependent_expr (arg1);
       arg2 = build_non_dependent_expr (arg2);
     }
 
-  expr = build_new_op (input_location, ARRAY_REF, LOOKUP_NORMAL, arg1,
+  expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, arg1,
 		       arg2, NULL_TREE, /*overload=*/NULL, complain);
 
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (ARRAY_REF, expr, orig_arg1, orig_arg2,
-			      NULL_TREE, NULL_TREE);
+    return build_min_non_dep_loc (EXPR_LOCATION (expr), ARRAY_REF,
+				  expr, orig_arg1, orig_arg2,
+				  NULL_TREE, NULL_TREE);
   return expr;
 }
 
@@ -4671,7 +4675,7 @@  build_x_unary_op (location_t loc, enum tree_code c
   if (processing_template_decl)
     {
       if (type_dependent_expression_p (xarg))
-	return build_min_nt (code, xarg, NULL_TREE);
+	return build_min_nt_loc (loc, code, xarg, NULL_TREE);
 
       xarg = build_non_dependent_expr (xarg);
     }
@@ -4753,8 +4757,10 @@  build_x_unary_op (location_t loc, enum tree_code c
     }
 
   if (processing_template_decl && exp != error_mark_node)
-    exp = build_min_non_dep (code, exp, orig_expr,
-			     /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
+    exp = build_min_non_dep_loc (EXPR_LOCATION (exp), code,
+				 exp, orig_expr,
+				 /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/
+				 NULL_TREE);
   if (TREE_CODE (exp) == ADDR_EXPR)
     PTRMEM_OK_P (exp) = ptrmem;
   return exp;
@@ -5586,7 +5592,7 @@  cxx_mark_addressable (tree exp)
 /* Build and return a conditional expression IFEXP ? OP1 : OP2.  */
 
 tree
-build_x_conditional_expr (tree ifexp, tree op1, tree op2, 
+build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2, 
                           tsubst_flags_t complain)
 {
   tree orig_ifexp = ifexp;
@@ -5603,7 +5609,7 @@  tree
 	  /* As a GNU extension, the middle operand may be omitted.  */
 	  || (op1 && type_dependent_expression_p (op1))
 	  || type_dependent_expression_p (op2))
-	return build_min_nt (COND_EXPR, ifexp, op1, op2);
+	return build_min_nt_loc (loc, COND_EXPR, ifexp, op1, op2);
       ifexp = build_non_dependent_expr (ifexp);
       if (op1)
 	op1 = build_non_dependent_expr (op1);
@@ -5613,8 +5619,8 @@  tree
   expr = build_conditional_expr (ifexp, op1, op2, complain);
   if (processing_template_decl && expr != error_mark_node)
     {
-      tree min = build_min_non_dep (COND_EXPR, expr,
-				    orig_ifexp, orig_op1, orig_op2);
+      tree min = build_min_non_dep_loc (EXPR_LOCATION (expr), COND_EXPR,
+					expr, orig_ifexp, orig_op1, orig_op2);
       /* In C++11, remember that the result is an lvalue or xvalue.
          In C++98, lvalue_kind can just assume lvalue in a template.  */
       if (cxx_dialect >= cxx0x
@@ -5670,8 +5676,8 @@  build_x_compound_expr_from_list (tree list, expr_l
 	return error_mark_node;
 
       for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list))
-	expr = build_x_compound_expr (expr, TREE_VALUE (list), 
-                                      complain);
+	expr = build_x_compound_expr (EXPR_LOCATION (TREE_VALUE (list)),
+				      expr, TREE_VALUE (list), complain);
     }
 
   return expr;
@@ -5699,7 +5705,8 @@  build_x_compound_expr_from_vec (VEC(tree,gc) *vec,
 
       expr = VEC_index (tree, vec, 0);
       for (ix = 1; VEC_iterate (tree, vec, ix, t); ++ix)
-	expr = build_x_compound_expr (expr, t, tf_warning_or_error);
+	expr = build_x_compound_expr (EXPR_LOCATION (t), expr,
+				      t, tf_warning_or_error);
 
       return expr;
     }
@@ -5708,7 +5715,8 @@  build_x_compound_expr_from_vec (VEC(tree,gc) *vec,
 /* Handle overloading of the ',' operator when needed.  */
 
 tree
-build_x_compound_expr (tree op1, tree op2, tsubst_flags_t complain)
+build_x_compound_expr (location_t loc, tree op1, tree op2,
+		       tsubst_flags_t complain)
 {
   tree result;
   tree orig_op1 = op1;
@@ -5718,19 +5726,19 @@  tree
     {
       if (type_dependent_expression_p (op1)
 	  || type_dependent_expression_p (op2))
-	return build_min_nt (COMPOUND_EXPR, op1, op2);
+	return build_min_nt_loc (loc, COMPOUND_EXPR, op1, op2);
       op1 = build_non_dependent_expr (op1);
       op2 = build_non_dependent_expr (op2);
     }
 
-  result = build_new_op (input_location, COMPOUND_EXPR, LOOKUP_NORMAL,
+  result = build_new_op (loc, COMPOUND_EXPR, LOOKUP_NORMAL,
 			 op1, op2, NULL_TREE, /*overload=*/NULL, complain);
   if (!result)
     result = cp_build_compound_expr (op1, op2, complain);
 
   if (processing_template_decl && result != error_mark_node)
-    return build_min_non_dep (COMPOUND_EXPR, result, orig_op1, orig_op2);
-
+    return build_min_non_dep_loc (EXPR_LOCATION (result), COMPOUND_EXPR,
+				  result, orig_op1, orig_op2);
   return result;
 }
 
@@ -7105,16 +7113,17 @@  cp_build_modify_expr (tree lhs, enum tree_code mod
 }
 
 tree
-build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
-		     tsubst_flags_t complain)
+build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
+		     tree rhs, tsubst_flags_t complain)
 {
   if (processing_template_decl)
-    return build_min_nt (MODOP_EXPR, lhs,
-			 build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
+    return build_min_nt_loc (loc, MODOP_EXPR, lhs,
+			     build_min_nt_loc (loc, modifycode, NULL_TREE,
+					       NULL_TREE), rhs);
 
   if (modifycode != NOP_EXPR)
     {
-      tree rval = build_new_op (input_location, MODIFY_EXPR, LOOKUP_NORMAL,
+      tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL,
 				lhs, rhs, make_node (modifycode),
 				/*overload=*/NULL, complain);
       if (rval)
Index: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c	(revision 187551)
+++ gcc/cp/tree.c	(working copy)
@@ -2025,7 +2025,7 @@  break_out_target_exprs (tree t)
    expressions  */
 
 tree
-build_min_nt (enum tree_code code, ...)
+build_min_nt_loc (location_t loc, enum tree_code code, ...)
 {
   tree t;
   int length;
@@ -2037,6 +2037,7 @@  tree
   va_start (p, code);
 
   t = make_node (code);
+  SET_EXPR_LOCATION (t, loc);
   length = TREE_CODE_LENGTH (code);
 
   for (i = 0; i < length; i++)
@@ -2085,7 +2086,7 @@  build_min (enum tree_code code, tree tt, ...)
    built.  */
 
 tree
-build_min_non_dep (enum tree_code code, tree non_dep, ...)
+build_min_non_dep_loc (location_t loc, enum tree_code code, tree non_dep, ...)
 {
   tree t;
   int length;
@@ -2100,6 +2101,7 @@  tree
     non_dep = TREE_OPERAND (non_dep, 0);
 
   t = make_node (code);
+  SET_EXPR_LOCATION (t, loc);
   length = TREE_CODE_LENGTH (code);
   TREE_TYPE (t) = TREE_TYPE (non_dep);
   TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c	(revision 187551)
+++ gcc/cp/typeck2.c	(working copy)
@@ -1484,7 +1484,7 @@  build_x_arrow (location_t loc, tree expr, tsubst_f
   if (processing_template_decl)
     {
       if (type_dependent_expression_p (expr))
-	return build_min_nt (ARROW_EXPR, expr);
+	return build_min_nt_loc (loc, ARROW_EXPR, expr);
       expr = build_non_dependent_expr (expr);
     }
 
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 187551)
+++ gcc/cp/pt.c	(working copy)
@@ -11968,7 +11968,8 @@  tsubst_qualified_id (tree qualified_id, tree args,
   if (dependent_scope_p (scope))
     {
       if (is_template)
-	expr = build_min_nt (TEMPLATE_ID_EXPR, expr, template_args);
+	expr = build_min_nt_loc (UNKNOWN_LOCATION, TEMPLATE_ID_EXPR,
+				 expr, template_args);
       return build_qualified_name (NULL_TREE, scope, expr,
 				   QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
     }
@@ -12672,7 +12673,8 @@  tsubst_omp_for_iterator (tree t, int i, tree declv
       cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
       incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
       if (TREE_CODE (incr) == MODIFY_EXPR)
-	incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
+	incr = build_x_modify_expr (EXPR_LOC_OR_HERE (incr),
+				    RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
 				    RECUR (TREE_OPERAND (incr, 1)),
 				    complain);
       else
@@ -13638,7 +13640,8 @@  tsubst_copy_and_build (tree t,
     case ARRAY_REF:
       op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
 						args, complain, in_decl);
-      return build_x_array_ref (op1, RECUR (TREE_OPERAND (t, 1)), complain);
+      return build_x_array_ref (EXPR_LOC_OR_HERE (t), op1,
+				RECUR (TREE_OPERAND (t, 1)), complain);
 
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
@@ -13699,7 +13702,8 @@  tsubst_copy_and_build (tree t,
     case MODOP_EXPR:
       {
 	tree r = build_x_modify_expr
-	  (RECUR (TREE_OPERAND (t, 0)),
+	  (EXPR_LOC_OR_HERE (t),
+	   RECUR (TREE_OPERAND (t, 0)),
 	   TREE_CODE (TREE_OPERAND (t, 1)),
 	   RECUR (TREE_OPERAND (t, 2)),
 	   complain);
@@ -13783,7 +13787,8 @@  tsubst_copy_and_build (tree t,
 	complain);
 
     case COMPOUND_EXPR:
-      return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
+      return build_x_compound_expr (EXPR_LOC_OR_HERE (t),
+				    RECUR (TREE_OPERAND (t, 0)),
 				    RECUR (TREE_OPERAND (t, 1)),
                                     complain);
 
@@ -14023,7 +14028,8 @@  tsubst_copy_and_build (tree t,
 	    exp2 = RECUR (TREE_OPERAND (t, 2));
 	  }
 
-	return build_x_conditional_expr (cond, exp1, exp2, complain);
+	return build_x_conditional_expr (EXPR_LOC_OR_HERE (t),
+					 cond, exp1, exp2, complain);
       }
 
     case PSEUDO_DTOR_EXPR:
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 187551)
+++ gcc/cp/semantics.c	(working copy)
@@ -1498,7 +1498,8 @@  finish_mem_initializers (tree mem_inits)
             TREE_VALUE (mem) = error_mark_node;
         }
 
-      add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
+      add_stmt (build_min_nt_loc (UNKNOWN_LOCATION,
+				  CTOR_INITIALIZER, mem_inits));
     }
   else
     emit_mem_initializers (mem_inits);
@@ -4456,7 +4457,8 @@  handle_omp_for_class_iterator (int i, location_t l
 	cond = error_mark_node;
       else
 	{
-	  tree tem = build_x_binary_op (input_location, TREE_CODE (cond),
+	  tree tem = build_x_binary_op (EXPR_LOC_OR_HERE (cond),
+					TREE_CODE (cond),
 					iter, ERROR_MARK,
 					TREE_OPERAND (cond, 1), ERROR_MARK,
 					NULL, tf_warning_or_error);
@@ -4473,7 +4475,7 @@  handle_omp_for_class_iterator (int i, location_t l
       error_at (elocus, "invalid controlling predicate");
       return true;
     }
-  diff = build_x_binary_op (input_location, MINUS_EXPR, TREE_OPERAND (cond, 1),
+  diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1),
 			    ERROR_MARK, iter, ERROR_MARK, NULL,
 			    tf_warning_or_error);
   if (error_operand_p (diff))
@@ -4496,7 +4498,8 @@  handle_omp_for_class_iterator (int i, location_t l
 	  incr = error_mark_node;
 	  break;
 	}
-      iter_incr = build_x_unary_op (input_location, TREE_CODE (incr), iter,
+      iter_incr = build_x_unary_op (EXPR_LOC_OR_HERE (incr),
+				    TREE_CODE (incr), iter,
 				    tf_warning_or_error);
       if (error_operand_p (iter_incr))
 	return true;
@@ -4520,7 +4523,8 @@  handle_omp_for_class_iterator (int i, location_t l
 		incr = error_mark_node;
 	      else
 		{
-		  iter_incr = build_x_modify_expr (iter, TREE_CODE (rhs),
+		  iter_incr = build_x_modify_expr (EXPR_LOC_OR_HERE (rhs),
+						   iter, TREE_CODE (rhs),
 						   TREE_OPERAND (rhs, 1),
 						   tf_warning_or_error);
 		  if (error_operand_p (iter_incr))
@@ -4546,14 +4550,16 @@  handle_omp_for_class_iterator (int i, location_t l
 		incr = error_mark_node;
 	      else
 		{
-		  iter_incr = build_x_binary_op (input_location, PLUS_EXPR,
+		  iter_incr = build_x_binary_op (EXPR_LOC_OR_HERE (rhs),
+						 PLUS_EXPR,
 						 TREE_OPERAND (rhs, 0),
 						 ERROR_MARK, iter,
 						 ERROR_MARK, NULL,
 						 tf_warning_or_error);
 		  if (error_operand_p (iter_incr))
 		    return true;
-		  iter_incr = build_x_modify_expr (iter, NOP_EXPR,
+		  iter_incr = build_x_modify_expr (EXPR_LOC_OR_HERE (rhs),
+						   iter, NOP_EXPR,
 						   iter_incr,
 						   tf_warning_or_error);
 		  if (error_operand_p (iter_incr))
@@ -4604,18 +4610,22 @@  handle_omp_for_class_iterator (int i, location_t l
   if (orig_pre_body)
     add_stmt (orig_pre_body);
   if (init != NULL)
-    finish_expr_stmt (build_x_modify_expr (iter, NOP_EXPR, init,
+    finish_expr_stmt (build_x_modify_expr (elocus,
+					   iter, NOP_EXPR, init,
 					   tf_warning_or_error));
   init = build_int_cst (TREE_TYPE (diff), 0);
   if (c && iter_incr == NULL)
     {
-      finish_expr_stmt (build_x_modify_expr (incr_var, NOP_EXPR,
+      finish_expr_stmt (build_x_modify_expr (elocus,
+					     incr_var, NOP_EXPR,
 					     incr, tf_warning_or_error));
       incr = incr_var;
-      iter_incr = build_x_modify_expr (iter, PLUS_EXPR, incr,
+      iter_incr = build_x_modify_expr (elocus,
+				       iter, PLUS_EXPR, incr,
 				       tf_warning_or_error);
     }
-  finish_expr_stmt (build_x_modify_expr (last, NOP_EXPR, init,
+  finish_expr_stmt (build_x_modify_expr (elocus,
+					 last, NOP_EXPR, init,
 					 tf_warning_or_error));
   *pre_body = pop_stmt_list (*pre_body);
 
@@ -4628,11 +4638,13 @@  handle_omp_for_class_iterator (int i, location_t l
   orig_body = *body;
   *body = push_stmt_list ();
   iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), decl, last);
-  iter_init = build_x_modify_expr (iter, PLUS_EXPR, iter_init,
+  iter_init = build_x_modify_expr (elocus,
+				   iter, PLUS_EXPR, iter_init,
 				   tf_warning_or_error);
   iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
   finish_expr_stmt (iter_init);
-  finish_expr_stmt (build_x_modify_expr (last, NOP_EXPR, decl,
+  finish_expr_stmt (build_x_modify_expr (elocus,
+					 last, NOP_EXPR, decl,
 					 tf_warning_or_error));
   add_stmt (orig_body);
   *body = pop_stmt_list (*body);
@@ -4939,7 +4951,8 @@  finish_omp_atomic (enum tree_code code, enum tree_
     {
       if (code == OMP_ATOMIC_READ)
 	{
-	  stmt = build_min_nt (OMP_ATOMIC_READ, orig_lhs);
+	  stmt = build_min_nt_loc (EXPR_LOC_OR_HERE (orig_lhs),
+				   OMP_ATOMIC_READ, orig_lhs);
 	  stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
 	}
       else
@@ -4949,10 +4962,12 @@  finish_omp_atomic (enum tree_code code, enum tree_
 	  else 
 	    stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
 	  if (orig_rhs1)
-	    stmt = build_min_nt (COMPOUND_EXPR, orig_rhs1, stmt);
+	    stmt = build_min_nt_loc (EXPR_LOC_OR_HERE (orig_rhs1),
+				     COMPOUND_EXPR, orig_rhs1, stmt);
 	  if (code != OMP_ATOMIC)
 	    {
-	      stmt = build_min_nt (code, orig_lhs1, stmt);
+	      stmt = build_min_nt_loc (EXPR_LOC_OR_HERE (orig_lhs1),
+				       code, orig_lhs1, stmt);
 	      stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
 	    }
 	}
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 187551)
+++ gcc/cp/decl2.c	(working copy)
@@ -350,8 +350,8 @@  grok_array_decl (location_t loc, tree array_expr,
     {
       if (type_dependent_expression_p (array_expr)
 	  || type_dependent_expression_p (index_exp))
-	return build_min_nt (ARRAY_REF, array_expr, index_exp,
-			     NULL_TREE, NULL_TREE);
+	return build_min_nt_loc (loc, ARRAY_REF, array_expr, index_exp,
+				 NULL_TREE, NULL_TREE);
       array_expr = build_non_dependent_expr (array_expr);
       index_exp = build_non_dependent_expr (index_exp);
     }
@@ -408,8 +408,9 @@  grok_array_decl (location_t loc, tree array_expr,
       expr = build_array_ref (input_location, array_expr, index_exp);
     }
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
-			      NULL_TREE, NULL_TREE);
+    return build_min_non_dep_loc (loc, ARRAY_REF, expr,
+				  orig_array_expr, orig_index_exp,
+				  NULL_TREE, NULL_TREE);
   return expr;
 }
 
@@ -1370,8 +1371,8 @@  build_anon_union_vars (tree type, tree object)
 	permerror (input_location, "protected member %q+#D in anonymous union", field);
 
       if (processing_template_decl)
-	ref = build_min_nt (COMPONENT_REF, object,
-			    DECL_NAME (field), NULL_TREE);
+	ref = build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF, object,
+				DECL_NAME (field), NULL_TREE);
       else
 	ref = build_class_member_access_expr (object, field, NULL_TREE,
 					      false, tf_warning_or_error);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 187551)
+++ gcc/cp/parser.c	(working copy)
@@ -7438,6 +7438,7 @@  cp_parser_question_colon_clause (cp_parser* parser
   tree expr;
   tree assignment_expr;
   struct cp_token *token;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Consume the `?' token.  */
   cp_lexer_consume_token (parser->lexer);
@@ -7472,7 +7473,7 @@  cp_parser_question_colon_clause (cp_parser* parser
   c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
 
   /* Build the conditional-expression.  */
-  return build_x_conditional_expr (logical_or_expr,
+  return build_x_conditional_expr (loc, logical_or_expr,
 				   expr,
 				   assignment_expr,
                                    tf_warning_or_error);
@@ -7512,11 +7513,11 @@  cp_parser_assignment_expression (cp_parser* parser
 	return cp_parser_question_colon_clause (parser, expr);
       else
 	{
-	  enum tree_code assignment_operator;
+	  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
 	  /* If it's an assignment-operator, we're using the second
 	     production.  */
-	  assignment_operator
+	  enum tree_code assignment_operator
 	    = cp_parser_assignment_operator_opt (parser);
 	  if (assignment_operator != ERROR_MARK)
 	    {
@@ -7534,7 +7535,7 @@  cp_parser_assignment_expression (cp_parser* parser
 							      NIC_ASSIGNMENT))
 		return error_mark_node;
 	      /* Build the assignment expression.  */
-	      expr = build_x_modify_expr (expr,
+	      expr = build_x_modify_expr (loc, expr,
 					  assignment_operator,
 					  rhs,
 					  tf_warning_or_error);
@@ -7643,6 +7644,7 @@  static tree
 cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
 {
   tree expression = NULL_TREE;
+  location_t loc = UNKNOWN_LOCATION;
 
   while (true)
     {
@@ -7656,7 +7658,7 @@  cp_parser_expression (cp_parser* parser, bool cast
       if (!expression)
 	expression = assignment_expression;
       else
-	expression = build_x_compound_expr (expression,
+	expression = build_x_compound_expr (loc, expression,
 					    assignment_expression,
                                             tf_warning_or_error);
       /* If the next token is not a comma, then we are done with the
@@ -7664,6 +7666,7 @@  cp_parser_expression (cp_parser* parser, bool cast
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
 	break;
       /* Consume the `,'.  */
+      loc = cp_lexer_peek_token (parser->lexer)->location;
       cp_lexer_consume_token (parser->lexer);
       /* A comma operator cannot appear in a constant-expression.  */
       if (cp_parser_non_integral_constant_expression (parser, NIC_COMMA))
@@ -12499,7 +12502,9 @@  cp_parser_template_id (cp_parser *parser,
 
   /* Build a representation of the specialization.  */
   if (TREE_CODE (templ) == IDENTIFIER_NODE)
-    template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments);
+    template_id = build_min_nt_loc (next_token->location,
+				    TEMPLATE_ID_EXPR,
+				    templ, arguments);
   else if (DECL_TYPE_TEMPLATE_P (templ)
 	   || DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
     {
@@ -26350,7 +26355,8 @@  cp_parser_omp_for_loop (cp_parser *parser, tree cl
 		  cp_parser_parse_definitely (parser);
 		  cp_parser_require (parser, CPP_EQ, RT_EQ);
 		  rhs = cp_parser_assignment_expression (parser, false, NULL);
-		  finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
+		  finish_expr_stmt (build_x_modify_expr (EXPR_LOC_OR_HERE (rhs),
+							 decl, NOP_EXPR,
 							 rhs,
 							 tf_warning_or_error));
 		  add_private_clause = true;
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 187551)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -5684,8 +5684,10 @@  extern bool lvalue_or_rvalue_with_address_p	(const
 extern bool xvalue_p	                        (const_tree);
 extern bool builtin_valid_in_constant_expr_p    (const_tree);
 extern tree build_min				(enum tree_code, tree, ...);
-extern tree build_min_nt			(enum tree_code, ...);
-extern tree build_min_non_dep			(enum tree_code, tree, ...);
+extern tree build_min_nt_loc			(location_t, enum tree_code,
+						 ...);
+extern tree build_min_non_dep_loc		(location_t, enum tree_code,
+						 tree, ...);
 extern tree build_min_non_dep_call_vec		(tree, tree, VEC(tree,gc) *);
 extern tree build_cplus_new			(tree, tree, tsubst_flags_t);
 extern tree build_aggr_init_expr		(tree, tree, tsubst_flags_t);
@@ -5813,7 +5815,8 @@  extern tree build_x_binary_op			(location_t,
 						 enum tree_code, tree,
 						 enum tree_code, tree *,
 						 tsubst_flags_t);
-extern tree build_x_array_ref			(tree, tree, tsubst_flags_t);
+extern tree build_x_array_ref			(location_t, tree, tree,
+						 tsubst_flags_t);
 extern tree build_x_unary_op			(location_t,
 						 enum tree_code, tree,
                                                  tsubst_flags_t);
@@ -5822,12 +5825,13 @@  extern tree cp_build_addr_expr_strict		(tree, tsub
 extern tree cp_build_unary_op                   (enum tree_code, tree, int, 
                                                  tsubst_flags_t);
 extern tree unary_complex_lvalue		(enum tree_code, tree);
-extern tree build_x_conditional_expr		(tree, tree, tree, 
+extern tree build_x_conditional_expr		(location_t, tree, tree, tree, 
                                                  tsubst_flags_t);
 extern tree build_x_compound_expr_from_list	(tree, expr_list_kind,
 						 tsubst_flags_t);
 extern tree build_x_compound_expr_from_vec	(VEC(tree,gc) *, const char *);
-extern tree build_x_compound_expr		(tree, tree, tsubst_flags_t);
+extern tree build_x_compound_expr		(location_t, tree, tree,
+						 tsubst_flags_t);
 extern tree build_compound_expr                 (location_t, tree, tree);
 extern tree cp_build_compound_expr		(tree, tree, tsubst_flags_t);
 extern tree build_static_cast			(tree, tree, tsubst_flags_t);
@@ -5835,7 +5839,8 @@  extern tree build_reinterpret_cast		(tree, tree, t
 extern tree build_const_cast			(tree, tree, tsubst_flags_t);
 extern tree build_c_cast			(location_t, tree, tree);
 extern tree cp_build_c_cast			(tree, tree, tsubst_flags_t);
-extern tree build_x_modify_expr			(tree, enum tree_code, tree,
+extern tree build_x_modify_expr			(location_t, tree,
+						 enum tree_code, tree,
 						 tsubst_flags_t);
 extern tree cp_build_modify_expr		(tree, enum tree_code, tree,
 						 tsubst_flags_t);