diff mbox

[C++] PR 44516

Message ID 4FB2C307.6090509@oracle.com
State New
Headers show

Commit Message

Paolo Carlini May 15, 2012, 8:56 p.m. UTC
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.

Comments

Jason Merrill May 15, 2012, 10:11 p.m. UTC | #1
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. UTC | #2
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. UTC | #3
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
diff mbox

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);