From 59e98ab51ef675d74a0786a133a34774fcd7909e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 9 Nov 2017 17:06:48 -0500
Subject: [PATCH 28/46] C++: handle location wrappers

gcc/cp/ChangeLog:
	* call.c (build_conditional_expr_1): Handle location wrappers.
	(build_new_op_1): Likewise.
	* class.c (mark_or_check_attr_tags): Likewise.
	* constexpr.c (cxx_eval_constant_expression): Likewise.
	* cvt.c (ocp_convert): Likewise.
	* decl.c (reshape_init_r): Likewise.
	(cp_complete_array_type): Likewise.
	* expr.c (mark_discarded_use): Likewise.
	* lambda.c (build_capture_proxy): Likewise.
	* name-lookup.c (handle_namespace_attrs): Likewise.
	* parser.c (cp_parser_postfix_expression): Likewise when checking
	for calls to memset and for component lookups.
	(cp_parser_unary_expression): Likewise for immediate folding of
	negated constants.
	(cp_parser_template_argument): Likewise.
	(cp_parser_omp_for_incr): Likewise.
	(cp_parser_omp_for_loop_init): Likewise.
	(cp_parser_omp_declare_reduction_exprs): Likewise.
	(cp_parser_cilk_simd_linear): Likewise.
	* pt.c (convert_nontype_argument_function): Likewise.
	(convert_nontype_argument): Likewise.
	* semantics.c (finish_asm_stmt): Likewise.
	(perform_koenig_lookup): Likewise.
	(handle_omp_array_sections_1): Likewise.
	(handle_omp_array_sections): Likewise.
	(omp_reduction_lookup): Likewise.
	(finish_omp_for): Likewise.
	* tree.c (cp_stabilize_reference): Likewise.
	(builtin_valid_in_constant_expr_p): Likewise.
	(is_overloaded_fn): Likewise.
	(get_fns): Likewise.
	(check_abi_tag_args): Likewise.
	* typeck.c (cxx_sizeof_expr): Likewise.
	(cp_build_binary_op): Likewise.
	(cp_build_modify_expr): Likewise.
	(maybe_warn_about_returning_address_of_local): Likewise.
	* typeck2.c (cxx_incomplete_type_diagnostic): Likewise.
	(digest_init_r): Likewise.
---
 gcc/cp/call.c        |  7 ++++++
 gcc/cp/class.c       |  1 +
 gcc/cp/constexpr.c   |  1 +
 gcc/cp/cvt.c         |  1 +
 gcc/cp/decl.c        |  4 ++++
 gcc/cp/expr.c        |  2 ++
 gcc/cp/lambda.c      |  3 +++
 gcc/cp/name-lookup.c |  1 +
 gcc/cp/parser.c      | 65 +++++++++++++++++++++++++++++++++-------------------
 gcc/cp/pt.c          | 10 +++++++-
 gcc/cp/semantics.c   | 44 ++++++++++++++++++++++-------------
 gcc/cp/tree.c        |  8 +++++++
 gcc/cp/typeck.c      | 25 +++++++++++++++++---
 gcc/cp/typeck2.c     |  4 ++++
 14 files changed, 133 insertions(+), 43 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c1b662f..82302b5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4816,6 +4816,9 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
   orig_arg2 = arg2;
   orig_arg3 = arg3;
 
+  STRIP_ANY_LOCATION_WRAPPER (arg2);
+  STRIP_ANY_LOCATION_WRAPPER (arg3);
+
   if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1)))
     {
       tree arg1_type = TREE_TYPE (arg1);
@@ -5588,6 +5591,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
       || error_operand_p (arg3))
     return error_mark_node;
 
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (arg1);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (arg2);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (arg3);
+
   bool ismodop = code == MODIFY_EXPR;
   if (ismodop)
     {
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 586a32c..781594c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1377,6 +1377,7 @@ mark_or_check_attr_tags (tree attr, tree *tp, abi_tag_data *p, bool val)
 	 list = TREE_CHAIN (list))
       {
 	tree tag = TREE_VALUE (list);
+	STRIP_ANY_LOCATION_WRAPPER (tag);
 	tree id = get_identifier (TREE_STRING_POINTER (tag));
 	if (tp)
 	  check_tag (tag, id, tp, p);
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index d6b6843..3122743 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3943,6 +3943,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 			      tree *jump_target)
 {
   constexpr_ctx new_ctx;
+  STRIP_ANY_LOCATION_WRAPPER (t);
   tree r = t;
 
   if (jump_target && *jump_target)
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index b3a6f69..fdc2b8d 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -766,6 +766,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 	     the original value is within the range of the enumeration
 	     values. Otherwise, the resulting enumeration value is
 	     unspecified.  */
+	  STRIP_ANY_LOCATION_WRAPPER (e);
 	  if ((complain & tf_warning)
 	      && TREE_CODE (e) == INTEGER_CST
 	      && ENUM_UNDERLYING_TYPE (type)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7e16f7b..9afce0a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5809,6 +5809,8 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
   if (error_operand_p (init))
     return error_mark_node;
 
+  STRIP_ANY_LOCATION_WRAPPER (init);
+
   if (first_initializer_p && !CP_AGGREGATE_TYPE_P (type)
       && has_designator_problem (d, complain))
     return error_mark_node;
@@ -8115,6 +8117,8 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
   int failure;
   tree type, elt_type;
 
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (initial_value);
+
   /* Don't get confused by a CONSTRUCTOR for some other type.  */
   if (initial_value && TREE_CODE (initial_value) == CONSTRUCTOR
       && !BRACE_ENCLOSED_INITIALIZER_P (initial_value)
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 81b9a5b..07630fc 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -220,6 +220,8 @@ mark_discarded_use (tree expr)
   if (expr == NULL_TREE)
     return expr;
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case COND_EXPR:
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 4480c67..c403a25 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -428,6 +428,8 @@ build_capture_proxy (tree member, tree init)
   TREE_USED (var) = 1;
   DECL_CONTEXT (var) = fn;
 
+  STRIP_ANY_LOCATION_WRAPPER (init);
+
   if (DECL_NORMAL_CAPTURE_P (member))
     {
       if (DECL_VLA_CAPTURE_P (member))
@@ -444,6 +446,7 @@ build_capture_proxy (tree member, tree init)
 	    init = TREE_OPERAND (init, 0);
 	  STRIP_NOPS (init);
 	}
+      STRIP_ANY_LOCATION_WRAPPER (init);
       gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL);
       while (is_normal_capture_proxy (init))
 	init = DECL_CAPTURED_VARIABLE (init);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b4976d8..6d5fdcf 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5026,6 +5026,7 @@ handle_namespace_attrs (tree ns, tree attributes)
 	     rather than the namespace as a whole, so we don't touch the
 	     NAMESPACE_DECL at all.  */
 	  tree x = args ? TREE_VALUE (args) : NULL_TREE;
+	  STRIP_ANY_LOCATION_WRAPPER_SAFE (x);
 	  if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
 	    {
 	      warning (OPT_Wattributes,
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8834542..090fb03 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7168,9 +7168,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		  }
 	      }
 
-	    if (TREE_CODE (postfix_expression) == FUNCTION_DECL
-		&& DECL_BUILT_IN_CLASS (postfix_expression) == BUILT_IN_NORMAL
-		&& DECL_FUNCTION_CODE (postfix_expression) == BUILT_IN_MEMSET
+	    tree postfix_expr_noloc = postfix_expression;
+	    STRIP_ANY_LOCATION_WRAPPER (postfix_expr_noloc);
+
+	    if (TREE_CODE (postfix_expr_noloc) == FUNCTION_DECL
+		&& DECL_BUILT_IN_CLASS (postfix_expr_noloc) == BUILT_IN_NORMAL
+		&& DECL_FUNCTION_CODE (postfix_expr_noloc) == BUILT_IN_MEMSET
 		&& vec_safe_length (args) == 3)
 	      {
 		tree arg0 = (*args)[0];
@@ -7184,10 +7187,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		warn_for_memset (input_location, arg0, arg2, literal_mask);
 	      }
 
-	    if (TREE_CODE (postfix_expression) == COMPONENT_REF)
+	    if (TREE_CODE (postfix_expr_noloc) == COMPONENT_REF)
 	      {
-		tree instance = TREE_OPERAND (postfix_expression, 0);
-		tree fn = TREE_OPERAND (postfix_expression, 1);
+		tree instance = TREE_OPERAND (postfix_expr_noloc, 0);
+		tree fn = TREE_OPERAND (postfix_expr_noloc, 1);
 
 		if (processing_template_decl
 		    && (type_dependent_object_expression_p (instance)
@@ -7221,9 +7224,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 					/*koenig_p=*/false,
 					complain);
 	      }
-	    else if (TREE_CODE (postfix_expression) == OFFSET_REF
-		     || TREE_CODE (postfix_expression) == MEMBER_REF
-		     || TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
+	    else if (TREE_CODE (postfix_expr_noloc) == OFFSET_REF
+		     || TREE_CODE (postfix_expr_noloc) == MEMBER_REF
+		     || TREE_CODE (postfix_expr_noloc) == DOTSTAR_EXPR)
 	      postfix_expression = (build_offset_ref_call_from_tree
 				    (postfix_expression, &args,
 				     complain));
@@ -8335,18 +8338,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 	case NEGATE_EXPR:
 	  /* Immediately fold negation of a constant, unless the constant is 0
 	     (since -0 == 0) or it would overflow.  */
-	  if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER
-	      && CONSTANT_CLASS_P (cast_expression)
-	      && !integer_zerop (cast_expression)
-	      && !TREE_OVERFLOW (cast_expression))
+	  if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER)
 	    {
-	      tree folded = fold_build1 (unary_operator,
-					 TREE_TYPE (cast_expression),
-					 cast_expression);
-	      if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+	      cast_expression.strip_any_location_wrapper ();
+	      if (CONSTANT_CLASS_P (cast_expression)
+		  && !integer_zerop (cast_expression)
+		  && !TREE_OVERFLOW (cast_expression))
 		{
-		  expression = cp_expr (folded, loc);
-		  break;
+		  tree folded = fold_build1 (unary_operator,
+					     TREE_TYPE (cast_expression),
+					     cast_expression);
+		  if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+		    {
+		      expression = cp_expr (folded, loc);
+		      expression.maybe_add_location_wrapper ();
+		      break;
+		    }
 		}
 	    }
 	  /* Fall through.  */
@@ -16415,6 +16422,7 @@ cp_parser_template_argument (cp_parser* parser)
 					       /*cast_p=*/false,
 					       /*template_arg_p=*/true,
 					       &idk);
+      STRIP_ANY_LOCATION_WRAPPER (argument);
       if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
 	  || !cp_parser_next_token_ends_template_argument_p (parser))
 	cp_parser_simulate_error (parser);
@@ -16444,6 +16452,7 @@ cp_parser_template_argument (cp_parser* parser)
 					       /*cast_p=*/false,
 					       /*template_arg_p=*/true,
 					       &idk);
+      STRIP_ANY_LOCATION_WRAPPER (argument);
       if (cp_parser_error_occurred (parser)
 	  || !cp_parser_next_token_ends_template_argument_p (parser))
 	cp_parser_abort_tentative_parse (parser);
@@ -34686,6 +34695,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 	    ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
       cp_lexer_consume_token (parser->lexer);
       lhs = cp_parser_simple_cast_expression (parser);
+      STRIP_ANY_LOCATION_WRAPPER (lhs);
       if (lhs != decl
 	  && (!processing_template_decl || !cp_tree_equal (lhs, decl)))
 	return error_mark_node;
@@ -34693,6 +34703,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
     }
 
   lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
   if (lhs != decl
       && (!processing_template_decl || !cp_tree_equal (lhs, decl)))
     return error_mark_node;
@@ -34720,6 +34731,8 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
   lhs = cp_parser_binary_expression (parser, false, false,
 				     PREC_ADDITIVE_EXPRESSION, NULL);
   token = cp_lexer_peek_token (parser->lexer);
+
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
   decl_first = (lhs == decl
 		|| (processing_template_decl && cp_tree_equal (lhs, decl)));
   if (decl_first)
@@ -34754,6 +34767,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 
   if (!decl_first)
     {
+      STRIP_ANY_LOCATION_WRAPPER (rhs);
       if ((rhs != decl
 	   && (!processing_template_decl || !cp_tree_equal (rhs, decl)))
 	  || op == MINUS_EXPR)
@@ -34943,6 +34957,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
       cp_parser_parse_tentatively (parser);
       decl = cp_parser_primary_expression (parser, false, false,
 					   false, &idk);
+      STRIP_ANY_LOCATION_WRAPPER_SAFE (decl);
       cp_token *last_tok = cp_lexer_peek_token (parser->lexer);
       if (!cp_parser_error_occurred (parser)
 	  && decl
@@ -37563,10 +37578,13 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
 	  unsigned int i;
 	  tree arg;
 	  FOR_EACH_VEC_SAFE_ELT (args, i, arg)
-	    if (arg == omp_priv
-		|| (TREE_CODE (arg) == ADDR_EXPR
-		    && TREE_OPERAND (arg, 0) == omp_priv))
-	      break;
+	    {
+	      STRIP_ANY_LOCATION_WRAPPER (arg);
+	      if (arg == omp_priv
+		  || (TREE_CODE (arg) == ADDR_EXPR
+		      && TREE_OPERAND (arg, 0) == omp_priv))
+		break;
+	    }
 	  cp_parser_abort_tentative_parse (parser);
 	  if (arg == NULL_TREE)
 	    error ("one of the initializer call arguments should be %<omp_priv%>"
@@ -39165,6 +39183,7 @@ cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses)
 
 	      e = cp_parser_assignment_expression (parser);
 	      e = maybe_constant_value (e);
+	      STRIP_ANY_LOCATION_WRAPPER (e);
 
 	      if (e == error_mark_node)
 		{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 562b927..71fce74 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6063,6 +6063,7 @@ convert_nontype_argument_function (tree type, tree expr,
      -- the address of an object or function with external [C++11: or
         internal] linkage.  */
 
+  STRIP_ANY_LOCATION_WRAPPER (fn_no_ptr);
   if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL)
     {
       if (complain & tf_error)
@@ -6410,6 +6411,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 {
   tree expr_type;
   location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  STRIP_ANY_LOCATION_WRAPPER (expr);
   tree orig_expr = expr;
 
   /* Detect immediately string literals as invalid non-type argument.
@@ -6475,6 +6477,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      to a null value, but otherwise still need to be of a specific form.  */
   if (cxx_dialect >= cxx11)
     {
+      STRIP_ANY_LOCATION_WRAPPER (expr);
       if (TREE_CODE (expr) == PTRMEM_CST)
 	/* A PTRMEM_CST is already constant, and a valid template
 	   argument for a parameter of pointer to member type, we just want
@@ -6506,6 +6509,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   else
     expr = mark_rvalue_use (expr);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   /* HACK: Due to double coercion, we can get a
      NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
      which is the tree that we built on the first call (see
@@ -6559,6 +6564,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 
       /* Notice that there are constant expressions like '4 % 0' which
 	 do not fold into integer constants.  */
+      STRIP_ANY_LOCATION_WRAPPER (expr);
       if (TREE_CODE (expr) != INTEGER_CST
 	  && !value_dependent_expression_p (expr))
 	{
@@ -6592,6 +6598,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      conversion (_conv.array_) are applied.  */
   else if (TYPE_PTROBV_P (type))
     {
+      STRIP_ANY_LOCATION_WRAPPER (expr);
       tree decayed = expr;
 
       /* Look through any NOP_EXPRs around an ADDR_EXPR, whether they come from
@@ -6630,6 +6637,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 	/* Null pointer values are OK in C++11.  */;
       else if (TREE_CODE (expr) != ADDR_EXPR)
 	{
+	  STRIP_ANY_LOCATION_WRAPPER (expr);
 	  if (VAR_P (expr))
 	    {
 	      if (complain & tf_error)
@@ -6653,7 +6661,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
       else
 	{
 	  tree decl = TREE_OPERAND (expr, 0);
-
+	  STRIP_ANY_LOCATION_WRAPPER (decl);
 	  if (!VAR_P (decl))
 	    {
 	      if (complain & tf_error)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f292d17..2f37dc8 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1489,6 +1489,8 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
 	     otherwise we'll get an error.  Gross, but ...  */
 	  STRIP_NOPS (operand);
 
+	  STRIP_ANY_LOCATION_WRAPPER (operand);
+
 	  operand = mark_lvalue_use (operand);
 
 	  if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error))
@@ -2249,6 +2251,8 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
   bool template_id = false;
   location_t loc = fn.get_location ();
 
+  fn.strip_any_location_wrapper ();
+
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
     {
       /* Use a separate flag to handle null args.  */
@@ -4603,7 +4607,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
 
   type = TREE_TYPE (ret);
   low_bound = TREE_PURPOSE (t);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (low_bound);
   length = TREE_VALUE (t);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (length);
   if ((low_bound && type_dependent_expression_p (low_bound))
       || (length && type_dependent_expression_p (length)))
     return NULL_TREE;
@@ -4894,11 +4900,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
 	  tree length = TREE_VALUE (t);
 
 	  i--;
+	  STRIP_ANY_LOCATION_WRAPPER_SAFE (low_bound);
 	  if (low_bound
 	      && TREE_CODE (low_bound) == INTEGER_CST
 	      && TYPE_PRECISION (TREE_TYPE (low_bound))
 		 > TYPE_PRECISION (sizetype))
 	    low_bound = fold_convert (sizetype, low_bound);
+	  STRIP_ANY_LOCATION_WRAPPER_SAFE (length);
 	  if (length
 	      && TREE_CODE (length) == INTEGER_CST
 	      && TYPE_PRECISION (TREE_TYPE (length))
@@ -5204,6 +5212,7 @@ omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp,
 						  type),
 				false, false);
   tree fns = id;
+  STRIP_ANY_LOCATION_WRAPPER (fns);
   id = NULL_TREE;
   if (fns && is_overloaded_fn (fns))
     {
@@ -8062,22 +8071,25 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
       if (decl == NULL)
 	{
 	  if (init != NULL)
-	    switch (TREE_CODE (init))
-	      {
-	      case MODIFY_EXPR:
-		decl = TREE_OPERAND (init, 0);
-		init = TREE_OPERAND (init, 1);
-		break;
-	      case MODOP_EXPR:
-		if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
-		  {
-		    decl = TREE_OPERAND (init, 0);
-		    init = TREE_OPERAND (init, 2);
-		  }
-		break;
-	      default:
-		break;
-	      }
+	    {
+	      STRIP_ANY_LOCATION_WRAPPER (init);
+	      switch (TREE_CODE (init))
+		{
+		case MODIFY_EXPR:
+		  decl = TREE_OPERAND (init, 0);
+		  init = TREE_OPERAND (init, 1);
+		  break;
+		case MODOP_EXPR:
+		  if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
+		    {
+		      decl = TREE_OPERAND (init, 0);
+		      init = TREE_OPERAND (init, 2);
+		    }
+		  break;
+		default:
+		  break;
+		}
+	    }
 
 	  if (decl == NULL)
 	    {
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index fd4641c..3bb8b8f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -333,6 +333,8 @@ bitfield_p (const_tree ref)
 tree
 cp_stabilize_reference (tree ref)
 {
+  STRIP_ANY_LOCATION_WRAPPER (ref);
+
   switch (TREE_CODE (ref))
     {
     case NON_DEPENDENT_EXPR:
@@ -377,6 +379,8 @@ cp_stabilize_reference (tree ref)
 bool
 builtin_valid_in_constant_expr_p (const_tree decl)
 {
+  STRIP_ANY_LOCATION_WRAPPER (decl);
+
   if (!(TREE_CODE (decl) == FUNCTION_DECL
 	&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL))
     /* Not a built-in.  */
@@ -2425,6 +2429,8 @@ lookup_keep (tree lookup, bool keep)
 int
 is_overloaded_fn (tree x)
 {
+  STRIP_ANY_LOCATION_WRAPPER (x);
+
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (x) == OFFSET_REF
       || TREE_CODE (x) == COMPONENT_REF)
@@ -2472,6 +2478,7 @@ really_overloaded_fn (tree x)
 tree
 get_fns (tree from)
 {
+  STRIP_ANY_LOCATION_WRAPPER (from);
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (from) == OFFSET_REF
       || TREE_CODE (from) == COMPONENT_REF)
@@ -4467,6 +4474,7 @@ check_abi_tag_args (tree args, tree name)
   for (tree arg = args; arg; arg = TREE_CHAIN (arg))
     {
       tree elt = TREE_VALUE (arg);
+      STRIP_ANY_LOCATION_WRAPPER (elt);
       if (TREE_CODE (elt) != STRING_CST
 	  || (!same_type_ignoring_top_level_qualifiers_p
 	      (strip_array_types (TREE_TYPE (elt)),
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a5e4745..027bafb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1614,6 +1614,8 @@ cxx_sizeof_nowarn (tree type)
 static tree
 cxx_sizeof_expr (tree e, tsubst_flags_t complain)
 {
+  STRIP_ANY_LOCATION_WRAPPER (e);
+
   if (e == error_mark_node)
     return error_mark_node;
 
@@ -4202,6 +4204,9 @@ cp_build_binary_op (location_t location,
   /* True if both operands have arithmetic type.  */
   bool arithmetic_types_p;
 
+  STRIP_ANY_LOCATION_WRAPPER (orig_op0);
+  STRIP_ANY_LOCATION_WRAPPER (orig_op1);
+
   /* Apply default conversions.  */
   op0 = orig_op0;
   op1 = orig_op1;
@@ -4394,6 +4399,7 @@ cp_build_binary_op (location_t location,
 	  tree type0 = TREE_OPERAND (op0, 0);
 	  tree type1 = TREE_OPERAND (op1, 0);
 	  tree first_arg = type0;
+	  STRIP_ANY_LOCATION_WRAPPER (first_arg);
 	  if (!TYPE_P (type0))
 	    type0 = TREE_TYPE (type0);
 	  if (!TYPE_P (type1))
@@ -7751,6 +7757,9 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 {
   lhs = mark_lvalue_use_nonread (lhs);
 
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
+  STRIP_ANY_LOCATION_WRAPPER (rhs);
+
   tree result = NULL_TREE;
   tree newrhs = rhs;
   tree lhstype = TREE_TYPE (lhs);
@@ -8888,10 +8897,16 @@ maybe_warn_about_returning_address_of_local (tree retval)
   for (;;)
     {
       if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
-	whats_returned = TREE_OPERAND (whats_returned, 1);
+	{
+	  whats_returned = TREE_OPERAND (whats_returned, 1);
+	  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+	}
       else if (CONVERT_EXPR_P (whats_returned)
 	       || TREE_CODE (whats_returned) == NON_LVALUE_EXPR)
-	whats_returned = TREE_OPERAND (whats_returned, 0);
+	{
+	  whats_returned = TREE_OPERAND (whats_returned, 0);
+	  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+	}
       else
 	break;
     }
@@ -8899,10 +8914,14 @@ maybe_warn_about_returning_address_of_local (tree retval)
   if (TREE_CODE (whats_returned) != ADDR_EXPR)
     return false;
   whats_returned = TREE_OPERAND (whats_returned, 0);
+  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
 
   while (TREE_CODE (whats_returned) == COMPONENT_REF
 	 || TREE_CODE (whats_returned) == ARRAY_REF)
-    whats_returned = TREE_OPERAND (whats_returned, 0);
+    {
+      whats_returned = TREE_OPERAND (whats_returned, 0);
+      STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+    }
 
   if (TREE_CODE (valtype) == REFERENCE_TYPE)
     {
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e135b0d..77f6f3e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -464,6 +464,8 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (value);
+
   if (value != 0 && (VAR_P (value)
 		     || TREE_CODE (value) == PARM_DECL
 		     || TREE_CODE (value) == FIELD_DECL))
@@ -1023,6 +1025,8 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 
   location_t loc = EXPR_LOC_OR_LOC (init, input_location);
 
+  STRIP_ANY_LOCATION_WRAPPER (init);
+
   /* Initialization of an array of chars from a string constant. The initializer
      can be optionally enclosed in braces, but reshape_init has already removed
      them if they were present.  */
-- 
1.8.5.3

