public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486)
@ 2018-11-05 19:44 David Malcolm
  2018-11-05 19:44 ` [PATCH 2/2] C++: improvements to binary operator diagnostics (PR c++/87504) David Malcolm
                   ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: David Malcolm @ 2018-11-05 19:44 UTC (permalink / raw)
  To: gcc-patches, jason; +Cc: David Malcolm

The C++ frontend gained various location wrapper nodes in r256448 (GCC 8).
That patch:
  https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00799.html
added wrapper nodes around all nodes with !CAN_HAVE_LOCATION_P for:

* arguments at callsites, and for

* typeid, alignof, sizeof, and offsetof.

This is a followup to that patch, adding many more location wrappers
to the C++ frontend.  It adds location wrappers for nodes with
!CAN_HAVE_LOCATION_P to:

* all literal nodes (in cp_parser_primary_expression)

* all id-expression nodes (in finish_id_expression), except within a
  decltype.

* all mem-initializer nodes within a mem-initializer-list
  (in cp_parser_mem_initializer)

However, the patch also adds some suppressions: regions in the parser
for which wrapper nodes will not be created:

* within a template-parameter-list or template-argument-list (in
  cp_parser_template_parameter_list and cp_parser_template_argument_list
  respectively), to avoid encoding the spelling location of the nodes
  in types.  For example, "array<10>" and "array<10>" are the same type,
  despite the fact that the two different "10" tokens are spelled in
  different locations in the source.

* within a gnu-style attribute (none of are handlers are set up to cope
  with location wrappers yet)

* within various OpenMP clauses

The patch enables various improvements to locations for bad
initializations, for -Wchar-subscripts, and enables various other
improvements in the followup patch.

For example, given the followup buggy mem-initializer:

class X {
  X() : bad(42),
        good(42)
  { }
  void* bad;
  int good;
};

previously, our diagnostic was on the final close parenthesis of the
mem-initializer-list, leaving it unclear where the problem is:

t.cc: In constructor 'X::X()':
t.cc:3:16: error: invalid conversion from 'int' to 'void*' [-fpermissive]
    3 |         good(42)
      |                ^
      |                |
      |                int

whereas with the patch we highlight which expression is bogus:

t.cc: In constructor 'X::X()':
t.cc:2:13: error: invalid conversion from 'int' to 'void*' [-fpermissive]
    2 |   X() : bad(42),
      |             ^~
      |             |
      |             int

Similarly, the diagnostic for this bogus initialization:

i.cc:1:44: error: initializer-string for array of chars is too long [-fpermissive]
    1 | char test[3][4] = { "ok", "too long", "ok" };
      |                                            ^

is improved by the patch so that it indicates which string is too long:

i.cc:1:27: error: initializer-string for array of chars is too long [-fpermissive]
    1 | char test[3][4] = { "ok", "too long", "ok" };
      |                           ^~~~~~~~~~

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu, in
conjunction with the followup patch [1]

I did some light performance testing, comparing release builds with and
without the patch on kdecore.cc (preprocessed all-of-KDE) and a test file
that includes all of the C++ stdlib (but does nothing) with it, in both
cases compiling at -O3 -g.  In both cases there was no significant
difference in the overall wallclock time for all of compilation:

kdecode.c total wallclock time:

http://chart.apis.google.com/chart?cht=lc&chs=700x400&chxt=x,y,x,y&chxr=1,58.26,61.79&chco=FF0000,0000FF&chdl=control|experiment&chds=58.26,61.79&chd=t:59.55,60.26,60.53,60.35,60.17,60.27,59.26,60.01,60.21,60.23,60.1,60.2,60.12,60.48,60.32,60.18,60.01,60.01,60.04,59.96,60.1,60.11,60.21,60.36,60.08,60.1,60.16,60.01,60.21,60.15,60.12,60.09,59.96,60.12,60.06,60.12,60.05,60.11,59.93,59.99|59.6,59.3,60.03,60.1,60.49,60.35,60.03,60.1,59.87,60.39,60.1,59.96,60.19,60.45,59.97,59.91,60.0,59.99,60.09,60.15,60.79,59.98,60.16,60.09,60.02,60.05,60.32,60.01,59.95,59.88,60.1,60.07,60.22,59.87,60.04,60.11,60.01,60.09,59.86,59.86&chxl=0:|1|8|16|24|32|40|2:||Iteration|3:||Time+(secs)&chtt=Compilation+of+kdecore.cc+at+-O3+with+-g+for+x86_64-pc-linux-gnu:+total:+wall

cp-stdlib.cc total wallclock time:

http://chart.apis.google.com/chart?cht=lc&chs=700x400&chxt=x,y,x,y&chxr=1,1.88,4.59&chco=FF0000,0000FF&chdl=control|experiment&chds=1.88,4.59&chd=t:3.59,2.94,2.95,2.94,2.94,2.93,2.92,2.94,2.93,2.94,2.94,2.88,2.94,2.9,2.94,2.9,2.94,2.93,2.94,2.93,2.95,2.93,2.9,2.9,2.94,2.99,2.95,3.0,2.94,3.0,2.94,2.99,2.95,2.95,2.9,2.99,2.94,2.99,2.94,2.96|3.54,2.92,2.93,2.88,2.94,2.92,2.93,2.92,2.9,2.93,2.89,2.93,2.9,2.93,2.89,2.91,2.93,2.92,2.89,2.93,2.93,2.92,2.93,2.92,2.93,2.92,2.88,2.92,2.89,2.93,2.94,2.92,2.9,2.92,2.92,2.91,2.94,2.92,2.98,2.88&chxl=0:|1|8|16|24|32|40|2:||Iteration|3:||Time+(secs)&chtt=Compilation+of+cp-stdlib.cc+at+-O3+with+-g+for+x86_64-pc-linux-gnu:+total:+wall

-ftime-report did show that kdecode.cc's "phase parsing" was 3% slower
by wallclock:

http://chart.apis.google.com/chart?cht=lc&chs=700x400&chxt=x,y,x,y&chxr=1,1.71,3.95&chco=FF0000,0000FF&chdl=control|experiment&chds=1.71,3.95&chd=t:2.74,2.72,2.73,2.8,2.72,2.73,2.72,2.74,2.73,2.73,2.73,2.73,2.73,2.72,2.72,2.72,2.73,2.72,2.72,2.72,2.73,2.73,2.73,2.71,2.72,2.72,2.73,2.73,2.72,2.73,2.73,2.72,2.73,2.73,2.73,2.72,2.73,2.72,2.72,2.72|2.81,2.78,2.78,2.79,2.78,2.78,2.78,2.79,2.78,2.79,2.8,2.79,2.78,2.78,2.79,2.78,2.79,2.79,2.8,2.79,2.79,2.78,2.79,2.8,2.79,2.79,2.78,2.79,2.79,2.78,2.78,2.8,2.95,2.78,2.79,2.79,2.79,2.79,2.79,2.79&chxl=0:|1|8|16|24|32|40|2:||Iteration|3:||Time+(secs)&chtt=Compilation+of+kdecore.cc+at+-O3+with+-g+for+x86_64-pc-linux-gnu:+phase+parsing:+wall

but this time was lost in the noise when optimizing.
There was no significant change for the other test's "phase parsing"
timing.

"mem max" ggc usage for both workloads increased by roughly half a
percent larger. (kdecore.cc went up from 1295533.000 to 1301373.000;
cp-stdlib.cc from 189535.000 to 190580.000).

OK for trunk?
Dave

[1] I've split them up for ease of review; they could be reworked to be
fully independent, but there's some churn in the results for
-Wtautological-compare introduced by the 1st patch which the 2nd
patch addresses.

gcc/ChangeLog:
	PR c++/43064
	PR c++/43486
	* convert.c: Include "selftest.h".
	(preserve_any_location_wrapper): New function.
	(convert_to_pointer_maybe_fold): Update to handle location
	wrappers.
	(convert_to_real_maybe_fold): Likewise.
	(convert_to_integer_1): Handle location wrappers when checking for
	INTEGER_CST.
	(convert_to_integer_maybe_fold): Update to handle location
	wrappers.
	(convert_to_complex_maybe_fold): Likewise.
	(selftest::test_convert_to_integer_maybe_fold): New functions.
	(selftest::convert_c_tests): New function.
	* fold-const.c (operand_equal_p): Strip any location wrappers.
	* selftest-run-tests.c (selftest::run_tests): Call
	selftest::convert_c_tests.
	* selftest.h (selftest::convert_c_tests): New decl.
	* tree.c (tree_int_cst_equal): Strip any location wrappers.
	(maybe_wrap_with_location): Don't create wrappers if any
	auto_suppress_location_wrappers are active.
	(suppress_location_wrappers): New variable.
	* tree.h (CONSTANT_CLASS_OR_WRAPPER_P): New macro.
	(suppress_location_wrappers): New decl.
	(class auto_suppress_location_wrappers): New class.

gcc/c-family/ChangeLog:
	PR c++/43064
	PR c++/43486
	* c-common.c (unsafe_conversion_p): Strip any location wrapper.
	(verify_tree): Handle location wrappers.
	(c_common_truthvalue_conversion): Strip any location wrapper.
	Handle CONST_DECL.
	(fold_offsetof): Strip any location wrapper.
	(complete_array_type): Likewise for initial_value.
	(convert_vector_to_array_for_subscript): Call fold_for_warn on the
	index before checking for INTEGER_CST.
	* c-pretty-print.c (c_pretty_printer::primary_expression): Don't
	print parentheses around location wrappers.
	* c-warn.c (warn_logical_operator): Call fold_for_warn on op_right
	before checking for INTEGER_CST.
	(warn_tautological_bitwise_comparison): Call
	tree_strip_any_location_wrapper on lhs, rhs, and bitop's operand
	before checking for INTEGER_CST.
	(readonly_error): Strip any location wrapper.
	(warn_array_subscript_with_type_char): Strip location wrappers
	before checking for INTEGER_CST.  Use the location of the index if
	available.

gcc/cp/ChangeLog:
	PR c++/43064
	PR c++/43486
	* call.c (build_conditional_expr_1): Strip location wrappers when
	checking for CONST_DECL.
	(conversion_null_warnings): Use location of "expr" if available.
	* class.c (fixed_type_or_null): Handle location wrappers.
	* constexpr.c (potential_constant_expression_1): Likewise.
	* cvt.c (ignore_overflows): Strip location wrappers when
	checking for INTEGER_CST, and re-wrap the result if present.
	(ocp_convert): Call fold_for_warn before checking for INTEGER_CST.
	* decl.c (reshape_init_r): Strip any location wrapper.
	(undeduced_auto_decl): Likewise.
	* decl2.c (grokbitfield): Likewise for width.
	* expr.c (mark_discarded_use): Likewise for expr.
	* init.c (build_aggr_init): Likewise before checking init for
	DECL_P.
	(warn_placement_new_too_small): Call fold_for_warn on adj before
	checking for CONSTANT_CLASS_P, and on nelts.  Strip any location
	wrapper from op0 and on oper before checking for VAR_P.
	* lambda.c (add_capture): Strip any location from initializer.
	* name-lookup.c (handle_namespace_attrs): Strip any location from
	x before checking for STRING_CST.
	* parser.c (cp_parser_primary_expression): Call
	maybe_add_location_wrapper on numeric and string literals.
	(cp_parser_postfix_expression): Strip any location wrapper when
	checking for DECL_IS_BUILTIN_CONSTANT_P.
	(cp_parser_binary_expression): Strip any location wrapper when
	checking for DECL_P on the lhs.
	(cp_parser_decltype_expr): Suppress location wrappers in the
	id-expression.
	(cp_parser_mem_initializer): Add location wrappers to the
	parenthesized expression list.
	(cp_parser_template_parameter_list): Don't create wrapper nodes
	within a template-parameter-list.
	(cp_parser_template_argument_list): Don't create wrapper nodes
	within a template-argument-list.
	(cp_parser_parameter_declaration): Strip location wrappers from
	default arguments.
	(cp_parser_gnu_attribute_list): Don't create wrapper nodes within
	an attribute.
	(cp_parser_late_parsing_default_args): Strip location wrappers
	from default arguments.
	(cp_parser_omp_all_clauses): Don't create wrapper nodes within
	OpenMP clauses.
	(cp_parser_omp_for_loop): Likewise.
	(cp_parser_omp_declare_reduction_exprs): Likewise.
	* pt.c (convert_nontype_argument_function): Strip location
	wrappers from fn_no_ptr before checking for FUNCTION_DECL.
	(do_auto_deduction): Likewise from init before checking for
	DECL_P.
	* semantics.c (force_paren_expr): Likewise from expr before
	checking for DECL_P.
	(finish_parenthesized_expr): Likewise from expr before
	checking for STRING_CST.
	(perform_koenig_lookup): Likewise from fn.
	(finish_call_expr): Likewise.
	(finish_id_expression): Rename to...
	(finish_id_expression_1): ...this, calling
	maybe_add_location_wrapper on the result.
	* tree.c (cp_stabilize_reference): Strip any location wrapper.
	(builtin_valid_in_constant_expr_p): Likewise.
	(is_overloaded_fn): Likewise.
	(maybe_get_fns): Likewise.
	(selftest::test_lvalue_kind): Verify lvalue_p.
	* typeck.c (cxx_sizeof_expr): Strip any location wrapper.
	(cxx_alignof_expr): Likewise.
	(is_bitfield_expr_with_lowered_type): Handle location wrappers.
	(cp_build_array_ref): Strip location wrappers from idx before
	checking for INTEGER_CST.
	(cp_build_binary_op): Strip location wrapper from first_arg before
	checking for PARM_DECL.  Likewise for op1 before checking for
	INTEGER_CST in two places.  Likewise for orig_op0 and orig_op1
	when checking for STRING_CST.
	(cp_build_addr_expr_1): Likewise for arg when checking for
	FUNCTION_DECL.
	(cp_build_modify_expr): Likewise for newrhs when checking for
	STRING_CST.
	(convert_for_assignment): Don't strip location wrappers when
	stripping NON_LVALUE_EXPR.
	(maybe_warn_about_returning_address_of_local): Strip location
	wrapper from whats_returned before checking for DECL_P.
	(can_do_nrvo_p): Strip location wrapper from retval.
	(treat_lvalue_as_rvalue_p): Likewise.
	(check_return_expr): Likewise.
	* typeck2.c (cxx_incomplete_type_diagnostic): Strip location
	wrapper from value before checking for VAR_P or PARM_DECL.
	(digest_init_r): Strip location wrapper from init.  When
	copying "init", also copy the wrapped node.

gcc/objc/ChangeLog:
	PR c++/43064
	PR c++/43486
	* objc-act.c (objc_maybe_build_component_ref): Strip any location
	wrapper before checking for UOBJC_SUPER_decl and self_decl.
	(objc_finish_message_expr): Strip any location wrapper.

gcc/testsuite/ChangeLog:
	PR c++/43064
	PR c++/43486
	* c-c++-common/pr51712.c (valid2): Mark xfail as passing on C++.
	* g++.dg/cpp1z/decomp48.C: Update expected location of warning
	for named local variables to use that of the local variable.
	* g++.dg/init/array43.C: Update expected column to be that of the
	initializer.
	* g++.dg/init/initializer-string-too-long.C: New test.
	* g++.dg/init/pr43064-1.C: New test.
	* g++.dg/init/pr43064-2.C: New test.
	* g++.dg/init/pr43064-3.C: New test.
	* g++.dg/wrappers/Wparentheses.C: New test.
---
 gcc/c-family/c-common.c                            |  22 ++++
 gcc/c-family/c-pretty-print.c                      |  11 +-
 gcc/c-family/c-warn.c                              |  70 ++++++-----
 gcc/convert.c                                      | 132 +++++++++++++++++++--
 gcc/cp/call.c                                      |  19 +--
 gcc/cp/class.c                                     |   6 +
 gcc/cp/constexpr.c                                 |  17 ++-
 gcc/cp/cvt.c                                       |  25 ++--
 gcc/cp/decl.c                                      |  33 +++---
 gcc/cp/decl2.c                                     |   3 +
 gcc/cp/expr.c                                      |   2 +
 gcc/cp/init.c                                      |   9 +-
 gcc/cp/lambda.c                                    |   3 +
 gcc/cp/name-lookup.c                               |   2 +
 gcc/cp/parser.c                                    |  52 ++++++--
 gcc/cp/pt.c                                        |   4 +-
 gcc/cp/semantics.c                                 |  77 ++++++++----
 gcc/cp/tree.c                                      |  14 +++
 gcc/cp/typeck.c                                    | 110 +++++++++++------
 gcc/cp/typeck2.c                                   |  56 +++++----
 gcc/fold-const.c                                   |   3 +
 gcc/objc/objc-act.c                                |   4 +
 gcc/selftest-run-tests.c                           |   1 +
 gcc/selftest.h                                     |   1 +
 gcc/testsuite/c-c++-common/pr51712.c               |   2 +-
 gcc/testsuite/g++.dg/cpp1z/decomp48.C              |   8 +-
 gcc/testsuite/g++.dg/init/array43.C                |   2 +-
 .../g++.dg/init/initializer-string-too-long.C      |   9 ++
 gcc/testsuite/g++.dg/init/pr43064-1.C              |  21 ++++
 gcc/testsuite/g++.dg/init/pr43064-2.C              |  34 ++++++
 gcc/testsuite/g++.dg/init/pr43064-3.C              |  32 +++++
 gcc/testsuite/g++.dg/wrappers/Wparentheses.C       |  10 ++
 gcc/tree.c                                         |  10 ++
 gcc/tree.h                                         |  19 +++
 34 files changed, 655 insertions(+), 168 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/init/initializer-string-too-long.C
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-1.C
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-2.C
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-3.C
 create mode 100644 gcc/testsuite/g++.dg/wrappers/Wparentheses.C

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index f10cf89..0386045 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1236,6 +1236,8 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
 
     loc = expansion_point_location_if_in_system_header (loc);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
     {
       /* If type is complex, we are interested in compatibility with
@@ -1933,6 +1935,13 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
       writer = 0;
       goto restart;
 
+    case VIEW_CONVERT_EXPR:
+      if (location_wrapper_p (x))
+	{
+	  x = TREE_OPERAND (x, 0);
+	  goto restart;
+	}
+      gcc_fallthrough ();
     default:
       /* For other expressions, simply recurse on their operands.
 	 Manual tail recursion for unary expressions.
@@ -3227,6 +3236,7 @@ decl_with_nonnull_addr_p (const_tree expr)
 tree
 c_common_truthvalue_conversion (location_t location, tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
   switch (TREE_CODE (expr))
     {
     case EQ_EXPR:   case NE_EXPR:   case UNEQ_EXPR: case LTGT_EXPR:
@@ -3446,6 +3456,14 @@ c_common_truthvalue_conversion (location_t location, tree expr)
 	}
       break;
 
+    case CONST_DECL:
+      {
+	tree folded_expr = fold_for_warn (expr);
+	if (folded_expr != expr)
+	  return c_common_truthvalue_conversion (location, folded_expr);
+      }
+      break;
+
     default:
       break;
     }
@@ -6226,6 +6244,7 @@ fold_offsetof (tree expr, tree type, enum tree_code ctx)
 	return base;
 
       t = TREE_OPERAND (expr, 1);
+      STRIP_ANY_LOCATION_WRAPPER (t);
 
       /* Check if the offset goes beyond the upper bound of the array.  */
       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
@@ -6304,6 +6323,8 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
   maxindex = size_zero_node;
   if (initial_value)
     {
+      STRIP_ANY_LOCATION_WRAPPER (initial_value);
+
       if (TREE_CODE (initial_value) == STRING_CST)
 	{
 	  int eltsize
@@ -7853,6 +7874,7 @@ convert_vector_to_array_for_subscript (location_t loc,
 
       ret = !lvalue_p (*vecp);
 
+      index = fold_for_warn (index);
       if (TREE_CODE (index) == INTEGER_CST)
         if (!tree_fits_uhwi_p (index)
 	    || maybe_ge (tree_to_uhwi (index), TYPE_VECTOR_SUBPARTS (type)))
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index a13cd84..5a55440 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1260,9 +1260,14 @@ c_pretty_printer::primary_expression (tree e)
 
     default:
       /* FIXME:  Make sure we won't get into an infinite loop.  */
-      pp_c_left_paren (this);
-      expression (e);
-      pp_c_right_paren (this);
+      if (location_wrapper_p (e))
+	expression (e);
+      else
+	{
+	  pp_c_left_paren (this);
+	  expression (e);
+	  pp_c_right_paren (this);
+	}
       break;
     }
 }
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index a1a7f93..f2ed711 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -208,19 +208,22 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
   if (!truth_value_p (code_left)
       && INTEGRAL_TYPE_P (TREE_TYPE (op_left))
       && !CONSTANT_CLASS_P (op_left)
-      && !TREE_NO_WARNING (op_left)
-      && TREE_CODE (op_right) == INTEGER_CST
-      && !integer_zerop (op_right)
-      && !integer_onep (op_right))
+      && !TREE_NO_WARNING (op_left))
     {
-      if (or_op)
-	warning_at (location, OPT_Wlogical_op, "logical %<or%>"
-		    " applied to non-boolean constant");
-      else
-	warning_at (location, OPT_Wlogical_op, "logical %<and%>"
-		    " applied to non-boolean constant");
-      TREE_NO_WARNING (op_left) = true;
-      return;
+      tree folded_op_right = fold_for_warn (op_right);
+      if (TREE_CODE (folded_op_right) == INTEGER_CST
+	  && !integer_zerop (folded_op_right)
+	  && !integer_onep (folded_op_right))
+	{
+	  if (or_op)
+	    warning_at (location, OPT_Wlogical_op, "logical %<or%>"
+			" applied to non-boolean constant");
+	  else
+	    warning_at (location, OPT_Wlogical_op, "logical %<and%>"
+			" applied to non-boolean constant");
+	  TREE_NO_WARNING (op_left) = true;
+	  return;
+	}
     }
 
   /* We do not warn for constants because they are typical of macro
@@ -340,24 +343,30 @@ warn_tautological_bitwise_comparison (location_t loc, tree_code code,
   /* Extract the operands from e.g. (x & 8) == 4.  */
   tree bitop;
   tree cst;
+  tree stripped_lhs = tree_strip_any_location_wrapper (lhs);
+  tree stripped_rhs = tree_strip_any_location_wrapper (rhs);
   if ((TREE_CODE (lhs) == BIT_AND_EXPR
        || TREE_CODE (lhs) == BIT_IOR_EXPR)
-      && TREE_CODE (rhs) == INTEGER_CST)
-    bitop = lhs, cst = rhs;
+      && TREE_CODE (stripped_rhs) == INTEGER_CST)
+    bitop = lhs, cst = stripped_rhs;
   else if ((TREE_CODE (rhs) == BIT_AND_EXPR
 	    || TREE_CODE (rhs) == BIT_IOR_EXPR)
-	   && TREE_CODE (lhs) == INTEGER_CST)
-    bitop = rhs, cst = lhs;
+	   && TREE_CODE (stripped_lhs) == INTEGER_CST)
+    bitop = rhs, cst = stripped_lhs;
   else
     return;
 
   tree bitopcst;
-  if (TREE_CODE (TREE_OPERAND (bitop, 0)) == INTEGER_CST)
-    bitopcst = TREE_OPERAND (bitop, 0);
-  else if (TREE_CODE (TREE_OPERAND (bitop, 1)) == INTEGER_CST)
-    bitopcst = TREE_OPERAND (bitop, 1);
-  else
-    return;
+  tree bitop_op0 = fold_for_warn (TREE_OPERAND (bitop, 0));
+  if (TREE_CODE (bitop_op0) == INTEGER_CST)
+    bitopcst = bitop_op0;
+  else {
+    tree bitop_op1 = fold_for_warn (TREE_OPERAND (bitop, 1));
+    if (TREE_CODE (bitop_op1) == INTEGER_CST)
+      bitopcst = bitop_op1;
+    else
+      return;
+  }
 
   /* Note that the two operands are from before the usual integer
      conversions, so their types might not be the same.
@@ -1524,6 +1533,7 @@ readonly_error (location_t loc, tree arg, enum lvalue_use use)
 {
   gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
 	      || use == lv_asm);
+  STRIP_ANY_LOCATION_WRAPPER (arg);
   /* Using this macro rather than (for example) arrays of messages
      ensures that all the format strings are checked at compile
      time.  */
@@ -1664,15 +1674,21 @@ invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
    warn for unsigned char since that type is safe.  Don't warn for
    signed char because anyone who uses that must have done so
    deliberately. Furthermore, we reduce the false positive load by
-   warning only for non-constant value of type char.  */
+   warning only for non-constant value of type char.
+   LOC is the location of the subscripting expression.  */
 
 void
 warn_array_subscript_with_type_char (location_t loc, tree index)
 {
-  if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node
-      && TREE_CODE (index) != INTEGER_CST)
-    warning_at (loc, OPT_Wchar_subscripts,
-		"array subscript has type %<char%>");
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
+    {
+      STRIP_ANY_LOCATION_WRAPPER (index);
+      if (TREE_CODE (index) != INTEGER_CST)
+	/* If INDEX has a location, use it; otherwise use LOC (the location
+	   of the subscripting expression as a whole).  */
+	warning_at (EXPR_LOC_OR_LOC (index, loc), OPT_Wchar_subscripts,
+		    "array subscript has type %<char%>");
+    }
 }
 
 /* Implement -Wparentheses for the unexpected C precedence rules, to
diff --git a/gcc/convert.c b/gcc/convert.c
index 68705f3..043a5d0 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "asan.h"
+#include "selftest.h"
 
 #define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \
   ((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR)	     \
@@ -98,6 +99,25 @@ convert_to_pointer_1 (tree type, tree expr, bool fold_p)
     }
 }
 
+/* Subroutine of the various convert_to_*_maybe_fold routines.
+
+   If a location wrapper has been folded to a constant (presumably of
+   a different type), re-wrap the new constant with a location wrapper.  */
+
+static tree
+preserve_any_location_wrapper (tree result, tree orig_expr)
+{
+  if (CONSTANT_CLASS_P (result) && location_wrapper_p (orig_expr))
+    {
+      if (result == TREE_OPERAND (orig_expr, 0))
+	return orig_expr;
+      else
+	return maybe_wrap_with_location (result, EXPR_LOCATION (orig_expr));
+    }
+
+  return result;
+}
+
 /* A wrapper around convert_to_pointer_1 that always folds the
    expression.  */
 
@@ -108,12 +128,15 @@ convert_to_pointer (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_pointer_1 that only folds the
-   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P.  */
 
 tree
 convert_to_pointer_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_pointer_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
+  tree result
+    = convert_to_pointer_1 (type, expr,
+			    dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr));
+  return preserve_any_location_wrapper (result, expr);
 }
 
 /* Convert EXPR to some floating-point type TYPE.
@@ -408,12 +431,15 @@ convert_to_real (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_real_1 that only folds the
-   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P.  */
 
 tree
 convert_to_real_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_real_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
+  tree result
+    = convert_to_real_1 (type, expr,
+			 dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr));
+  return preserve_any_location_wrapper (result, expr);
 }
 
 /* Try to narrow EX_FORM ARG0 ARG1 in narrowed arg types producing a
@@ -959,7 +985,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
 
       /* When parsing long initializers, we might end up with a lot of casts.
 	 Shortcut this.  */
-      if (TREE_CODE (expr) == INTEGER_CST)
+      if (TREE_CODE (tree_strip_any_location_wrapper (expr)) == INTEGER_CST)
 	return fold_convert (type, expr);
       return build1 (CONVERT_EXPR, type, expr);
 
@@ -1017,12 +1043,15 @@ convert_to_integer (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_complex_1 that only folds the
-   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P.  */
 
 tree
 convert_to_integer_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_integer_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
+  tree result
+    = convert_to_integer_1 (type, expr,
+			    dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr));
+  return preserve_any_location_wrapper (result, expr);
 }
 
 /* Convert EXPR to the complex type TYPE in the usual ways.  If FOLD_P is
@@ -1101,12 +1130,15 @@ convert_to_complex (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_complex_1 that only folds the
-   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_OR_WRAPPER_P.  */
 
 tree
 convert_to_complex_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_complex_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
+  tree result
+    = convert_to_complex_1 (type, expr,
+			    dofold || CONSTANT_CLASS_OR_WRAPPER_P (expr));
+  return preserve_any_location_wrapper (result, expr);
 }
 
 /* Convert EXPR to the vector type TYPE in the usual ways.  */
@@ -1171,3 +1203,85 @@ convert_to_fixed (tree type, tree expr)
       return error_mark_node;
     }
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for conversions.  */
+
+static void
+test_convert_to_integer_maybe_fold (tree orig_type, tree new_type)
+{
+  /* Calling convert_to_integer_maybe_fold on an INTEGER_CST.  */
+
+  tree orig_cst = build_int_cst (orig_type, 42);
+
+  /* Verify that convert_to_integer_maybe_fold on a constant returns a new
+     constant of the new type, unless the types are the same, in which
+     case verify it's a no-op.  */
+  {
+    tree result = convert_to_integer_maybe_fold (new_type,
+						 orig_cst, false);
+    if (orig_type != new_type)
+      {
+	ASSERT_EQ (TREE_TYPE (result), new_type);
+	ASSERT_EQ (TREE_CODE (result), INTEGER_CST);
+      }
+    else
+      ASSERT_EQ (result, orig_cst);
+  }
+
+  /* Calling convert_to_integer_maybe_fold on a location wrapper around
+     an INTEGER_CST.
+
+     Verify that convert_to_integer_maybe_fold on a location wrapper
+     around a constant returns a new location wrapper around an equivalent
+     constant, both of the new type, unless the types are the same,
+     in which case the original wrapper should be returned.   */
+  {
+    const location_t loc = BUILTINS_LOCATION;
+    tree wrapped_orig_cst = maybe_wrap_with_location (orig_cst, loc);
+    tree result
+      = convert_to_integer_maybe_fold (new_type, wrapped_orig_cst, false);
+    ASSERT_EQ (TREE_TYPE (result), new_type);
+    ASSERT_EQ (EXPR_LOCATION (result), loc);
+    ASSERT_TRUE (location_wrapper_p (result));
+    ASSERT_EQ (TREE_TYPE (TREE_OPERAND (result, 0)), new_type);
+    ASSERT_EQ (TREE_CODE (TREE_OPERAND (result, 0)), INTEGER_CST);
+
+    if (orig_type == new_type)
+      ASSERT_EQ (result, wrapped_orig_cst);
+  }
+}
+
+/* Verify that convert_to_integer_maybe_fold preserves locations.  */
+
+static void
+test_convert_to_integer_maybe_fold ()
+{
+  /* char -> long.  */
+  test_convert_to_integer_maybe_fold (char_type_node, long_integer_type_node);
+
+  /* char -> char.  */
+  test_convert_to_integer_maybe_fold (char_type_node, char_type_node);
+
+  /* long -> char.  */
+  test_convert_to_integer_maybe_fold (char_type_node, long_integer_type_node);
+
+  /* long -> long.  */
+  test_convert_to_integer_maybe_fold (long_integer_type_node,
+				      long_integer_type_node);
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+convert_c_tests ()
+{
+  test_convert_to_integer_maybe_fold ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cd0c0f6..d366d35 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5341,9 +5341,12 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
       if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
 	  && TREE_CODE (arg3_type) == ENUMERAL_TYPE)
         {
-	  if (TREE_CODE (orig_arg2) == CONST_DECL
-	      && TREE_CODE (orig_arg3) == CONST_DECL
-	      && DECL_CONTEXT (orig_arg2) == DECL_CONTEXT (orig_arg3))
+	  tree stripped_orig_arg2 = tree_strip_any_location_wrapper (orig_arg2);
+	  tree stripped_orig_arg3 = tree_strip_any_location_wrapper (orig_arg3);
+	  if (TREE_CODE (stripped_orig_arg2) == CONST_DECL
+	      && TREE_CODE (stripped_orig_arg3) == CONST_DECL
+	      && (DECL_CONTEXT (stripped_orig_arg2)
+		  == DECL_CONTEXT (stripped_orig_arg3)))
 	    /* Two enumerators from the same enumeration can have different
 	       types when the enumeration is still being defined.  */;
           else if (complain & tf_warning)
@@ -6630,8 +6633,8 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
   if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
       && ARITHMETIC_TYPE_P (totype))
     {
-      source_location loc =
-	expansion_point_location_if_in_system_header (input_location);
+      location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+      loc = expansion_point_location_if_in_system_header (loc);
 
       if (fn)
 	warning_at (loc, OPT_Wconversion_null,
@@ -6646,12 +6649,14 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
   else if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
 	   && TYPE_PTR_P (totype))
     {
+      location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+
       if (fn)
-	warning_at (input_location, OPT_Wconversion_null,
+	warning_at (loc, OPT_Wconversion_null,
 		    "converting %<false%> to pointer type for argument %P "
 		    "of %qD", argnum, fn);
       else
-	warning_at (input_location, OPT_Wconversion_null,
+	warning_at (loc, OPT_Wconversion_null,
 		    "converting %<false%> to pointer type %qT", totype);
     }
   /* Handle zero as null pointer warnings for cases other
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1789d1e..8b36e30 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7375,6 +7375,12 @@ fixed_type_or_null (tree instance, int *nonnull, int *cdtorp)
 	}
       return NULL_TREE;
 
+    case VIEW_CONVERT_EXPR:
+      if (location_wrapper_p (instance))
+	return RECUR (TREE_OPERAND (instance, 0));
+      else
+	return NULL_TREE;
+
     default:
       return NULL_TREE;
     }
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 4fa8c96..00f639b 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -5698,13 +5698,18 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
 	 may change to something more specific to type-punning (DR 1312).  */
       {
         tree from = TREE_OPERAND (t, 0);
-	if (INDIRECT_TYPE_P (TREE_TYPE (t))
-	    && TREE_CODE (from) == INTEGER_CST
-	    && !integer_zerop (from))
+	if (location_wrapper_p (t))
+	  return (RECUR (from, want_rval));
+	if (INDIRECT_TYPE_P (TREE_TYPE (t)))
 	  {
-	    if (flags & tf_error)
-	      error_at (loc, "reinterpret_cast from integer to pointer");
-	    return false;
+	    STRIP_ANY_LOCATION_WRAPPER (from);
+	    if (TREE_CODE (from) == INTEGER_CST
+		&& !integer_zerop (from))
+	      {
+		if (flags & tf_error)
+		  error_at (loc, "reinterpret_cast from integer to pointer");
+		return false;
+	      }
 	  }
         return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
       }
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 315b0d6..82ac296 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -582,15 +582,23 @@ force_rvalue (tree expr, tsubst_flags_t complain)
 static tree
 ignore_overflows (tree expr, tree orig)
 {
-  if (TREE_CODE (expr) == INTEGER_CST
-      && TREE_CODE (orig) == INTEGER_CST
-      && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig))
+  tree stripped_expr = tree_strip_any_location_wrapper (expr);
+  tree stripped_orig = tree_strip_any_location_wrapper (orig);
+
+  if (TREE_CODE (stripped_expr) == INTEGER_CST
+      && TREE_CODE (stripped_orig) == INTEGER_CST
+      && TREE_OVERFLOW (stripped_expr) != TREE_OVERFLOW (stripped_orig))
     {
-      gcc_assert (!TREE_OVERFLOW (orig));
+      gcc_assert (!TREE_OVERFLOW (stripped_orig));
       /* Ensure constant sharing.  */
-      expr = wide_int_to_tree (TREE_TYPE (expr), wi::to_wide (expr));
+      stripped_expr = wide_int_to_tree (TREE_TYPE (stripped_expr),
+					wi::to_wide (stripped_expr));
     }
-  return expr;
+
+  if (location_wrapper_p (expr))
+    return maybe_wrap_with_location (stripped_expr, EXPR_LOCATION (expr));
+
+  return stripped_expr;
 }
 
 /* Fold away simple conversions, but make sure TREE_OVERFLOW is set
@@ -792,10 +800,11 @@ 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.  */
+	  tree val = fold_for_warn (e);
 	  if ((complain & tf_warning)
-	      && TREE_CODE (e) == INTEGER_CST
+	      && TREE_CODE (val) == INTEGER_CST
 	      && ENUM_UNDERLYING_TYPE (type)
-	      && !int_fits_type_p (e, ENUM_UNDERLYING_TYPE (type)))
+	      && !int_fits_type_p (val, ENUM_UNDERLYING_TYPE (type)))
 	    warning_at (loc, OPT_Wconversion, 
 			"the result of the conversion is unspecified because "
 			"%qE is outside the range of type %qT",
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5ebfaaf..aea8089 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6000,14 +6000,16 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
       && has_designator_problem (d, complain))
     return error_mark_node;
 
+  tree stripped_init = tree_strip_any_location_wrapper (init);
+
   if (TREE_CODE (type) == COMPLEX_TYPE)
     {
       /* A complex type can be initialized from one or two initializers,
 	 but braces are not elided.  */
       d->cur++;
-      if (BRACE_ENCLOSED_INITIALIZER_P (init))
+      if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init))
 	{
-	  if (CONSTRUCTOR_NELTS (init) > 2)
+	  if (CONSTRUCTOR_NELTS (stripped_init) > 2)
 	    {
 	      if (complain & tf_error)
 		error ("too many initializers for %qT", type);
@@ -6037,16 +6039,16 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
 	 We need to check for BRACE_ENCLOSED_INITIALIZER_P here because
 	 of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is
 	 a CONSTRUCTOR (with a record type).  */
-      if (TREE_CODE (init) == CONSTRUCTOR
+      if (TREE_CODE (stripped_init) == CONSTRUCTOR
 	  /* Don't complain about a capture-init.  */
-	  && !CONSTRUCTOR_IS_DIRECT_INIT (init)
-	  && BRACE_ENCLOSED_INITIALIZER_P (init))  /* p7626.C */
+	  && !CONSTRUCTOR_IS_DIRECT_INIT (stripped_init)
+	  && BRACE_ENCLOSED_INITIALIZER_P (stripped_init))  /* p7626.C */
 	{
 	  if (SCALAR_TYPE_P (type))
 	    {
 	      if (cxx_dialect < cxx11
 		  /* Isn't value-initialization.  */
-		  || CONSTRUCTOR_NELTS (init) > 0)
+		  || CONSTRUCTOR_NELTS (stripped_init) > 0)
 		{
 		  if (complain & tf_error)
 		    error ("braces around scalar initializer for type %qT",
@@ -6106,20 +6108,22 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
       && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
     {
       tree str_init = init;
+      tree stripped_str_init = stripped_init;
 
       /* Strip one level of braces if and only if they enclose a single
 	 element (as allowed by [dcl.init.string]).  */
       if (!first_initializer_p
-	  && TREE_CODE (str_init) == CONSTRUCTOR
-	  && CONSTRUCTOR_NELTS (str_init) == 1)
+	  && TREE_CODE (stripped_str_init) == CONSTRUCTOR
+	  && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
 	{
-	  str_init = (*CONSTRUCTOR_ELTS (str_init))[0].value;
+	  str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+	  stripped_str_init = tree_strip_any_location_wrapper (str_init);
 	}
 
       /* If it's a string literal, then it's the initializer for the array
 	 as a whole. Otherwise, continue with normal initialization for
 	 array types (one value per array element).  */
-      if (TREE_CODE (str_init) == STRING_CST)
+      if (TREE_CODE (stripped_str_init) == STRING_CST)
 	{
 	  if (has_designator_problem (d, complain))
 	    return error_mark_node;
@@ -6134,24 +6138,24 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
      which reshape_init exists).  */
   if (!first_initializer_p)
     {
-      if (TREE_CODE (init) == CONSTRUCTOR)
+      if (TREE_CODE (stripped_init) == CONSTRUCTOR)
 	{
 	  if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
 	    /* There is no need to reshape pointer-to-member function
 	       initializers, as they are always constructed correctly
 	       by the front end.  */
            ;
-	  else if (COMPOUND_LITERAL_P (init))
+	  else if (COMPOUND_LITERAL_P (stripped_init))
 	  /* For a nested compound literal, there is no need to reshape since
 	     brace elision is not allowed. Even if we decided to allow it,
 	     we should add a call to reshape_init in finish_compound_literal,
 	     before calling digest_init, so changing this code would still
 	     not be necessary.  */
-	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
+	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
 	  else
 	    {
 	      ++d->cur;
-	      gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
+	      gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
 	      return reshape_init (type, init, complain);
 	    }
 	}
@@ -16541,6 +16545,7 @@ undeduced_auto_decl (tree decl)
 {
   if (cxx_dialect < cxx11)
     return false;
+  STRIP_ANY_LOCATION_WRAPPER (decl);
   return ((VAR_OR_FUNCTION_DECL_P (decl)
 	   || TREE_CODE (decl) == TEMPLATE_DECL)
 	  && type_uses_auto (TREE_TYPE (decl)));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a5ad0ee..a0dd9a3 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1058,6 +1058,9 @@ grokbitfield (const cp_declarator *declarator,
       return NULL_TREE;
     }
 
+  if (width)
+    STRIP_ANY_LOCATION_WRAPPER (width);
+
   if (width && TYPE_WARN_IF_NOT_ALIGN (TREE_TYPE (value)))
     {
       error ("cannot declare bit-field %qD with %<warn_if_not_aligned%> type",
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 93477bc..8163866 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -263,6 +263,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/init.c b/gcc/cp/init.c
index 15046b4..8f5a155 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1758,7 +1758,8 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
 	{
 	  from_array = 1;
 	  init = mark_rvalue_use (init);
-	  if (init && DECL_P (init)
+	  if (init
+	      && DECL_P (tree_strip_any_location_wrapper (init))
 	      && !(flags & LOOKUP_ONLYCONVERTING))
 	    {
 	      /* Wrap the initializer in a CONSTRUCTOR so that build_vec_init
@@ -2606,6 +2607,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
 	 Otherwise, use the size of the entire array as an optimistic
 	 estimate (this may lead to false negatives).  */
       tree adj = TREE_OPERAND (oper, 1);
+      adj = fold_for_warn (adj);
       if (CONSTANT_CLASS_P (adj))
 	adjust += wi::to_offset (convert (ssizetype, adj));
       else
@@ -2669,11 +2671,13 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
 
       tree op0 = oper;
       while (TREE_CODE (op0 = TREE_OPERAND (op0, 0)) == COMPONENT_REF);
+      STRIP_ANY_LOCATION_WRAPPER (op0);
       if (VAR_P (op0))
 	var_decl = op0;
       oper = TREE_OPERAND (oper, 1);
     }
 
+  STRIP_ANY_LOCATION_WRAPPER (oper);
   tree opertype = TREE_TYPE (oper);
   if ((addr_expr || !INDIRECT_TYPE_P (opertype))
       && (VAR_P (oper)
@@ -2764,6 +2768,9 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
 	 others.  */
       offset_int bytes_need;
 
+      if (nelts)
+	nelts = fold_for_warn (nelts);
+
       if (CONSTANT_CLASS_P (size))
 	bytes_need = wi::to_offset (size);
       else if (nelts && CONSTANT_CLASS_P (nelts))
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 297327f..ad88a0d 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -656,6 +656,9 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
       listmem = make_pack_expansion (member);
       initializer = orig_init;
     }
+
+  STRIP_ANY_LOCATION_WRAPPER (initializer);
+
   LAMBDA_EXPR_CAPTURE_LIST (lambda)
     = tree_cons (listmem, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
 
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 08632c3..aea4d43 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4985,6 +4985,8 @@ 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;
+	  if (x)
+	    STRIP_ANY_LOCATION_WRAPPER (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 ebe326e..b3876e2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5175,7 +5175,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  if (!cast_p)
 	    cp_parser_non_integral_constant_expression (parser, NIC_FLOAT);
 	}
-      return cp_expr (token->u.value, token->location);
+      return (cp_expr (token->u.value, token->location)
+	      .maybe_add_location_wrapper ());
 
     case CPP_CHAR_USERDEF:
     case CPP_CHAR16_USERDEF:
@@ -5197,9 +5198,10 @@ cp_parser_primary_expression (cp_parser *parser,
       /* ??? Should wide strings be allowed when parser->translate_strings_p
 	 is false (i.e. in attributes)?  If not, we can kill the third
 	 argument to cp_parser_string_literal.  */
-      return cp_parser_string_literal (parser,
-				       parser->translate_strings_p,
-				       true);
+      return (cp_parser_string_literal (parser,
+					parser->translate_strings_p,
+					true)
+	      .maybe_add_location_wrapper ());
 
     case CPP_OPEN_PAREN:
       /* If we see `( { ' then we are looking at the beginning of
@@ -7118,8 +7120,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
             is_member_access = false;
 
+	    tree stripped_expression
+	      = tree_strip_any_location_wrapper (postfix_expression);
 	    is_builtin_constant_p
-	      = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
+	      = DECL_IS_BUILTIN_CONSTANT_P (stripped_expression);
 	    if (is_builtin_constant_p)
 	      {
 		/* The whole point of __builtin_constant_p is to allow
@@ -9329,7 +9333,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 		      || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0)))
 			  != BOOLEAN_TYPE))))
 	  /* Avoid warning for !!b == y where b is boolean.  */
-	  && (!DECL_P (current.lhs)
+	  && (!DECL_P (tree_strip_any_location_wrapper (current.lhs))
 	      || TREE_TYPE (current.lhs) == NULL_TREE
 	      || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE))
 	warn_logical_not_parentheses (current.loc, current.tree_type,
@@ -14122,6 +14126,7 @@ cp_parser_decltype_expr (cp_parser *parser,
           && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
         {
           /* Complete lookup of the id-expression.  */
+	  auto_suppress_location_wrappers sentinel;
           expr = (finish_id_expression
                   (id_expression, expr, parser->scope, &idk,
                    /*integral_constant_expression_p=*/false,
@@ -14634,7 +14639,9 @@ cp_parser_mem_initializer (cp_parser* parser)
       vec = cp_parser_parenthesized_expression_list (parser, non_attr,
 						     /*cast_p=*/false,
 						     /*allow_expansion_p=*/true,
-						     /*non_constant_p=*/NULL);
+						     /*non_constant_p=*/NULL,
+						     /*close_paren_loc=*/NULL,
+						     /*wrap_locations_p=*/true);
       if (vec == NULL)
 	return error_mark_node;
       expression_list = build_tree_list_vec (vec);
@@ -15164,6 +15171,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 {
   tree parameter_list = NULL_TREE;
 
+  /* Don't create wrapper nodes within a template-parameter-list,
+     since we don't want to have different types based on the
+     spelling location of constants and decls within them.  */
+  auto_suppress_location_wrappers sentinel;
+
   begin_template_parm_list ();
 
   /* The loop below parses the template parms.  We first need to know
@@ -16281,6 +16293,9 @@ cp_parser_template_argument_list (cp_parser* parser)
   bool saved_ice_p;
   bool saved_non_ice_p;
 
+  /* Don't create location wrapper nodes within a template-argument-list.  */
+  auto_suppress_location_wrappers sentinel;
+
   saved_in_template_argument_list_p = parser->in_template_argument_list_p;
   parser->in_template_argument_list_p = true;
   /* Even if the template-id appears in an integral
@@ -21832,6 +21847,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
   else
     default_argument = NULL_TREE;
 
+  if (default_argument)
+    STRIP_ANY_LOCATION_WRAPPER (default_argument);
+
   /* Generate a location for the parameter, ranging from the start of the
      initial token to the end of the final token (using input_location for
      the latter, set up by cp_lexer_set_source_position_from_token when
@@ -25199,6 +25217,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
 	      vec<tree, va_gc> *vec;
 	      int attr_flag = (attribute_takes_identifier_p (identifier)
 			       ? id_attr : normal_attr);
+	      /* Don't create wrapper nodes within an attribute: the
+		 handlers don't know how to handle them.  */
+	      auto_suppress_location_wrappers sentinel;
 	      vec = cp_parser_parenthesized_expression_list 
 		    (parser, attr_flag, /*cast_p=*/false, 
 		    /*allow_expansion_p=*/false, 
@@ -28029,6 +28050,14 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 	= cp_parser_late_parse_one_default_arg (parser, parmdecl,
 						default_arg,
 						TREE_VALUE (parm));
+
+      /* Since default args are effectively part of the function type,
+	 strip location wrappers here, since otherwise the location of
+	 one function's default arguments is arbitrarily chosen for
+	 all functions with similar signature (due to canonicalization
+	 of function types).  */
+      STRIP_ANY_LOCATION_WRAPPER (parsed_arg);
+
       TREE_PURPOSE (parm) = parsed_arg;
 
       /* Update any instantiations we've already created.  */
@@ -33939,6 +33968,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
   bool first = true;
   cp_token *token = NULL;
 
+  /* Don't create location wrapper nodes within OpenMP clauses.  */
+  auto_suppress_location_wrappers sentinel;
+
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
       pragma_omp_clause c_kind;
@@ -35223,6 +35255,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
 	}
       loc = cp_lexer_consume_token (parser->lexer)->location;
 
+      /* Don't create location wrapper nodes within an OpenMP "for"
+	 statement.  */
+      auto_suppress_location_wrappers sentinel;
+
       matching_parens parens;
       if (!parens.require_open (parser))
 	return NULL;
@@ -37592,6 +37628,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
       else
 	{
 	  cp_parser_parse_tentatively (parser);
+	  /* Don't create location wrapper nodes here.  */
+	  auto_suppress_location_wrappers sentinel;
 	  tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false,
 						  /*check_dependency_p=*/true,
 						  /*template_p=*/NULL,
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f290cb3..bce0abe 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6257,6 +6257,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)
@@ -26830,7 +26831,8 @@ do_auto_deduction (tree type, tree init, tree auto_node,
 					 complain);
   else if (AUTO_IS_DECLTYPE (auto_node))
     {
-      bool id = (DECL_P (init)
+      tree stripped_init = tree_strip_any_location_wrapper (init);
+      bool id = (DECL_P (stripped_init)
 		 || ((TREE_CODE (init) == COMPONENT_REF
 		      || TREE_CODE (init) == SCOPE_REF)
 		     && !REF_PARENTHESIZED_P (init)));
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4c05365..cb97bec 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1740,7 +1740,8 @@ force_paren_expr (tree expr)
   if (cp_unevaluated_operand)
     return expr;
 
-  if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
+  if (!DECL_P (tree_strip_any_location_wrapper (expr))
+      && TREE_CODE (expr) != COMPONENT_REF
       && TREE_CODE (expr) != SCOPE_REF)
     return expr;
 
@@ -1803,8 +1804,9 @@ finish_parenthesized_expr (cp_expr expr)
        enclosed in parentheses.  */
     PTRMEM_OK_P (expr) = 0;
 
-  if (TREE_CODE (expr) == STRING_CST)
-    PAREN_STRING_LITERAL_P (expr) = 1;
+  tree stripped_expr = tree_strip_any_location_wrapper (expr);
+  if (TREE_CODE (stripped_expr) == STRING_CST)
+    PAREN_STRING_LITERAL_P (stripped_expr) = 1;
 
   expr = cp_expr (force_paren_expr (expr), expr.get_location ());
 
@@ -2297,19 +2299,22 @@ empty_expr_stmt_p (tree expr_stmt)
   return false;
 }
 
-/* Perform Koenig lookup.  FN is the postfix-expression representing
+/* Perform Koenig lookup.  FN_EXPR is the postfix-expression representing
    the function (or functions) to call; ARGS are the arguments to the
    call.  Returns the functions to be considered by overload resolution.  */
 
 cp_expr
-perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
+perform_koenig_lookup (cp_expr fn_expr, vec<tree, va_gc> *args,
 		       tsubst_flags_t complain)
 {
   tree identifier = NULL_TREE;
   tree functions = NULL_TREE;
   tree tmpl_args = NULL_TREE;
   bool template_id = false;
-  location_t loc = fn.get_location ();
+  location_t loc = fn_expr.get_location ();
+  tree fn = fn_expr.get_value ();
+
+  STRIP_ANY_LOCATION_WRAPPER (fn);
 
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
     {
@@ -2354,7 +2359,7 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
   if (fn && template_id && fn != error_mark_node)
     fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args);
   
-  return fn;
+  return cp_expr (fn, loc);
 }
 
 /* Generate an expression for `FN (ARGS)'.  This may change the
@@ -2385,6 +2390,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
      it so that we can tell this is a call to a known function.  */
   fn = maybe_undo_parenthesized_ref (fn);
 
+  STRIP_ANY_LOCATION_WRAPPER (fn);
+
   orig_fn = fn;
 
   if (processing_template_decl)
@@ -3532,20 +3539,20 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-cp_expr
-finish_id_expression (tree id_expression,
-		      tree decl,
-		      tree scope,
-		      cp_id_kind *idk,
-		      bool integral_constant_expression_p,
-		      bool allow_non_integral_constant_expression_p,
-		      bool *non_integral_constant_expression_p,
-		      bool template_p,
-		      bool done,
-		      bool address_p,
-		      bool template_arg_p,
-		      const char **error_msg,
-		      location_t location)
+static cp_expr
+finish_id_expression_1 (tree id_expression,
+			tree decl,
+			tree scope,
+			cp_id_kind *idk,
+			bool integral_constant_expression_p,
+			bool allow_non_integral_constant_expression_p,
+			bool *non_integral_constant_expression_p,
+			bool template_p,
+			bool done,
+			bool address_p,
+			bool template_arg_p,
+			const char **error_msg,
+			location_t location)
 {
   decl = strip_using_decl (decl);
 
@@ -3840,6 +3847,34 @@ finish_id_expression (tree id_expression,
   return cp_expr (decl, location);
 }
 
+/* As per finish_id_expression_1, but adding a wrapper node
+   around the result if needed to express LOCATION.  */
+
+cp_expr
+finish_id_expression (tree id_expression,
+		      tree decl,
+		      tree scope,
+		      cp_id_kind *idk,
+		      bool integral_constant_expression_p,
+		      bool allow_non_integral_constant_expression_p,
+		      bool *non_integral_constant_expression_p,
+		      bool template_p,
+		      bool done,
+		      bool address_p,
+		      bool template_arg_p,
+		      const char **error_msg,
+		      location_t location)
+{
+  cp_expr result
+    = finish_id_expression_1 (id_expression, decl, scope, idk,
+			      integral_constant_expression_p,
+			      allow_non_integral_constant_expression_p,
+			      non_integral_constant_expression_p,
+			      template_p, done, address_p, template_arg_p,
+			      error_msg, location);
+  return result.maybe_add_location_wrapper ();
+}
+
 /* Implement the __typeof keyword: Return the type of EXPR, suitable for
    use as a type-specifier.  */
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 251c344..58614e7 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -371,6 +371,7 @@ bitfield_p (const_tree ref)
 tree
 cp_stabilize_reference (tree ref)
 {
+  STRIP_ANY_LOCATION_WRAPPER (ref);
   switch (TREE_CODE (ref))
     {
     case NON_DEPENDENT_EXPR:
@@ -415,6 +416,7 @@ 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)
     /* Not a function.  */
     return false;
@@ -2428,6 +2430,8 @@ lookup_keep (tree lookup)
 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)
@@ -2476,6 +2480,8 @@ really_overloaded_fn (tree x)
 tree
 maybe_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)
@@ -5550,6 +5556,14 @@ test_lvalue_kind ()
   ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm));
   tree rvalue_ref_of_wrapped_parm = move (wrapped_parm);
   ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm));
+
+  /* Verify lvalue_p.  */
+  ASSERT_FALSE (lvalue_p (int_cst));
+  ASSERT_FALSE (lvalue_p (wrapped_int_cst));
+  ASSERT_TRUE (lvalue_p (parm));
+  ASSERT_TRUE (lvalue_p (wrapped_parm));
+  ASSERT_FALSE (lvalue_p (rvalue_ref_of_parm));
+  ASSERT_FALSE (lvalue_p (rvalue_ref_of_wrapped_parm));
 }
 
 /* Run all of the selftests within this file.  */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index c921096..b97d3da 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1682,6 +1682,8 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
       return e;
     }
 
+  STRIP_ANY_LOCATION_WRAPPER (e);
+
   /* To get the size of a static data member declared as an array of
      unknown bound, we need to instantiate it.  */
   if (VAR_P (e)
@@ -1754,6 +1756,8 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain)
       return e;
     }
 
+  STRIP_ANY_LOCATION_WRAPPER (e);
+
   e = mark_type_use (e);
 
   if (VAR_P (e))
@@ -1944,6 +1948,12 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
 						   (CONST_CAST_TREE (exp)));
       return NULL_TREE;
 
+    case VIEW_CONVERT_EXPR:
+      if (location_wrapper_p (exp))
+	return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+      else
+	return NULL_TREE;
+
     CASE_CONVERT:
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0)))
 	  == TYPE_MAIN_VARIANT (TREE_TYPE (exp)))
@@ -3404,11 +3414,13 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
 	 pointer arithmetic.)  */
       idx = cp_perform_integral_promotions (idx, complain);
 
+      tree stripped_idx = tree_strip_any_location_wrapper (idx);
+
       /* An array that is indexed by a non-constant
 	 cannot be stored in a register; we must be able to do
 	 address arithmetic on its address.
 	 Likewise an array of elements of variable size.  */
-      if (TREE_CODE (idx) != INTEGER_CST
+      if (TREE_CODE (stripped_idx) != INTEGER_CST
 	  || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
 	      && (TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))))
 		  != INTEGER_CST)))
@@ -3421,9 +3433,9 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
 	 the array bounds cannot be stored in a register either; because we
 	 would get a crash in store_bit_field/extract_bit_field when trying
 	 to access a non-existent part of the register.  */
-      if (TREE_CODE (idx) == INTEGER_CST
+      if (TREE_CODE (stripped_idx) == INTEGER_CST
 	  && TYPE_DOMAIN (TREE_TYPE (array))
-	  && ! int_fits_type_p (idx, TYPE_DOMAIN (TREE_TYPE (array))))
+	  && ! int_fits_type_p (stripped_idx, TYPE_DOMAIN (TREE_TYPE (array))))
 	{
 	  if (!cxx_mark_addressable (array))
 	    return error_mark_node;
@@ -4542,20 +4554,23 @@ cp_build_binary_op (location_t location,
 	    type0 = TREE_TYPE (type0);
 	  if (!TYPE_P (type1))
 	    type1 = TREE_TYPE (type1);
-	  if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1)
-	      && !(TREE_CODE (first_arg) == PARM_DECL
-		   && DECL_ARRAY_PARAMETER_P (first_arg)
-		   && warn_sizeof_array_argument)
-	      && (complain & tf_warning))
+	  if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1))
 	    {
-	      auto_diagnostic_group d;
-	      if (warning_at (location, OPT_Wsizeof_pointer_div,
-				"division %<sizeof (%T) / sizeof (%T)%> does "
-				"not compute the number of array elements",
-			    type0, type1))
-		if (DECL_P (first_arg))
-		  inform (DECL_SOURCE_LOCATION (first_arg),
-			    "first %<sizeof%> operand was declared here");
+	      STRIP_ANY_LOCATION_WRAPPER (first_arg);
+	      if (!(TREE_CODE (first_arg) == PARM_DECL
+		    && DECL_ARRAY_PARAMETER_P (first_arg)
+		    && warn_sizeof_array_argument)
+		  && (complain & tf_warning))
+		{
+		  auto_diagnostic_group d;
+		  if (warning_at (location, OPT_Wsizeof_pointer_div,
+				  "division %<sizeof (%T) / sizeof (%T)%> does "
+				  "not compute the number of array elements",
+				  type0, type1))
+		    if (DECL_P (first_arg))
+		      inform (DECL_SOURCE_LOCATION (first_arg),
+			      "first %<sizeof%> operand was declared here");
+		}
 	    }
 	}
 
@@ -4577,15 +4592,18 @@ cp_build_binary_op (location_t location,
 	  if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
 	    resultcode = RDIV_EXPR;
 	  else
-	    /* When dividing two signed integers, we have to promote to int.
-	       unless we divide by a constant != -1.  Note that default
-	       conversion will have been performed on the operands at this
-	       point, so we have to dig out the original type to find out if
-	       it was unsigned.  */
-	    shorten = ((TREE_CODE (op0) == NOP_EXPR
-			&& TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
-		       || (TREE_CODE (op1) == INTEGER_CST
-			   && ! integer_all_onesp (op1)));
+	    {
+	      /* When dividing two signed integers, we have to promote to int.
+		 unless we divide by a constant != -1.  Note that default
+		 conversion will have been performed on the operands at this
+		 point, so we have to dig out the original type to find out if
+		 it was unsigned.  */
+	      tree stripped_op1 = tree_strip_any_location_wrapper (op1);
+	      shorten = ((TREE_CODE (op0) == NOP_EXPR
+			  && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
+			 || (TREE_CODE (stripped_op1) == INTEGER_CST
+			     && ! integer_all_onesp (stripped_op1)));
+	    }
 
 	  common = 1;
 	}
@@ -4619,10 +4637,11 @@ cp_build_binary_op (location_t location,
 	     on some targets, since the modulo instruction is undefined if the
 	     quotient can't be represented in the computation mode.  We shorten
 	     only if unsigned or if dividing by something we know != -1.  */
+	  tree stripped_op1 = tree_strip_any_location_wrapper (op1);
 	  shorten = ((TREE_CODE (op0) == NOP_EXPR
 		      && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
-		     || (TREE_CODE (op1) == INTEGER_CST
-			 && ! integer_all_onesp (op1)));
+		     || (TREE_CODE (stripped_op1) == INTEGER_CST
+			 && ! integer_all_onesp (stripped_op1)));
 	  common = 1;
 	}
       break;
@@ -4823,13 +4842,17 @@ cp_build_binary_op (location_t location,
 	  && (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)))
 	warning (OPT_Wfloat_equal,
 		 "comparing floating point with == or != is unsafe");
-      if ((complain & tf_warning)
-	  && ((TREE_CODE (orig_op0) == STRING_CST
+      if (complain & tf_warning)
+	{
+	  tree stripped_orig_op0 = tree_strip_any_location_wrapper (orig_op0);
+	  tree stripped_orig_op1 = tree_strip_any_location_wrapper (orig_op1);
+	  if ((TREE_CODE (stripped_orig_op0) == STRING_CST
 	       && !integer_zerop (cp_fully_fold (op1)))
-	      || (TREE_CODE (orig_op1) == STRING_CST
-		  && !integer_zerop (cp_fully_fold (op0)))))
-	warning (OPT_Waddress, "comparison with string literal results "
-			       "in unspecified behavior");
+	      || (TREE_CODE (stripped_orig_op1) == STRING_CST
+		  && !integer_zerop (cp_fully_fold (op0))))
+	    warning (OPT_Waddress, "comparison with string literal results "
+		     "in unspecified behavior");
+	}
 
       build_type = boolean_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
@@ -6061,8 +6084,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
      so we can just form an ADDR_EXPR with the correct type.  */
   if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF)
     {
-      if (TREE_CODE (arg) == FUNCTION_DECL
-	  && !mark_used (arg, complain) && !(complain & tf_error))
+      tree stripped_arg = tree_strip_any_location_wrapper (arg);
+      if (TREE_CODE (stripped_arg) == FUNCTION_DECL
+	  && !mark_used (stripped_arg, complain) && !(complain & tf_error))
 	return error_mark_node;
       val = build_address (arg);
       if (TREE_CODE (arg) == OFFSET_REF)
@@ -8272,7 +8296,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
       /* C++11 8.5/17: "If the destination type is an array of characters,
 	 an array of char16_t, an array of char32_t, or an array of wchar_t,
 	 and the initializer is a string literal...".  */
-      else if (TREE_CODE (newrhs) == STRING_CST
+      else if ((TREE_CODE (tree_strip_any_location_wrapper (newrhs))
+		== STRING_CST)
 	       && char_type_p (TREE_TYPE (TYPE_MAIN_VARIANT (lhstype)))
 	       && modifycode == INIT_EXPR)
 	{
@@ -8790,8 +8815,10 @@ convert_for_assignment (tree type, tree rhs,
   tree rhstype;
   enum tree_code coder;
 
-  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
-  if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
+  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue,
+     but preserve location wrappers.  */
+  if (TREE_CODE (rhs) == NON_LVALUE_EXPR
+      && !location_wrapper_p (rhs))
     rhs = TREE_OPERAND (rhs, 0);
 
   /* Handle [dcl.init.list] direct-list-initialization from
@@ -9165,6 +9192,8 @@ maybe_warn_about_returning_address_of_local (tree retval)
       return true;
     }
 
+  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+
   if (DECL_P (whats_returned)
       && DECL_NAME (whats_returned)
       && DECL_FUNCTION_SCOPE_P (whats_returned)
@@ -9266,6 +9295,8 @@ is_std_move_p (tree fn)
 static bool
 can_do_nrvo_p (tree retval, tree functype)
 {
+  if (retval)
+    STRIP_ANY_LOCATION_WRAPPER (retval);
   tree result = DECL_RESULT (current_function_decl);
   return (retval != NULL_TREE
 	  && !processing_template_decl
@@ -9292,6 +9323,7 @@ can_do_nrvo_p (tree retval, tree functype)
 bool
 treat_lvalue_as_rvalue_p (tree retval, bool parm_ok)
 {
+  STRIP_ANY_LOCATION_WRAPPER (retval);
   return ((cxx_dialect != cxx98)
 	  && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval))
 	      || (parm_ok && TREE_CODE (retval) == PARM_DECL))
@@ -9585,6 +9617,8 @@ check_return_expr (tree retval, bool *no_warning)
      this restriction, anyway.  (jason 2000-11-19)
 
      See finish_function and finalize_nrv for the rest of this optimization.  */
+  if (retval)
+    STRIP_ANY_LOCATION_WRAPPER (retval);
 
   bool named_return_value_okay_p = can_do_nrvo_p (retval, functype);
   if (fn_returns_value_p && flag_elide_constructors)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index fec1db0..9034362 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -459,14 +459,19 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
-  if (value != 0 && (VAR_P (value)
-		     || TREE_CODE (value) == PARM_DECL
-		     || TREE_CODE (value) == FIELD_DECL))
+  if (value)
     {
-      complained = emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (value), 0,
-				    "%qD has incomplete type", value);
-      is_decl = true;
-    } 
+      STRIP_ANY_LOCATION_WRAPPER (value);
+
+      if (VAR_P (value)
+	  || TREE_CODE (value) == PARM_DECL
+	  || TREE_CODE (value) == FIELD_DECL)
+	{
+	  complained = emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (value), 0,
+					"%qD has incomplete type", value);
+	  is_decl = true;
+	}
+    }
  retry:
   /* We must print an error message.  Be clever about what it says.  */
 
@@ -1044,6 +1049,8 @@ digest_init_r (tree type, tree init, int nested, int flags,
 
   location_t loc = cp_expr_loc_or_loc (init, input_location);
 
+  tree stripped_init = tree_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.  */
@@ -1057,7 +1064,7 @@ digest_init_r (tree type, tree init, int nested, int flags,
       tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
       if (char_type_p (typ1)
 	  /*&& init */
-	  && TREE_CODE (init) == STRING_CST)
+	  && TREE_CODE (stripped_init) == STRING_CST)
 	{
 	  tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
 
@@ -1101,6 +1108,14 @@ digest_init_r (tree type, tree init, int nested, int flags,
 	    {
 	      init = copy_node (init);
 	      TREE_TYPE (init) = type;
+	      /* If we have a location wrapper, then also copy the wrapped
+		 node, and update the copy's type.  */
+	      if (location_wrapper_p (init))
+		{
+		  stripped_init = copy_node (stripped_init);
+		  TREE_OPERAND (init, 0) = stripped_init;
+		  TREE_TYPE (stripped_init) = type;
+		}
 	    }
 	  if (TYPE_DOMAIN (type) && TREE_CONSTANT (TYPE_SIZE (type)))
 	    {
@@ -1111,12 +1126,13 @@ digest_init_r (tree type, tree init, int nested, int flags,
 		 because it's ok to ignore the terminating null char that is
 		 counted in the length of the constant, but in C++ this would
 		 be invalid.  */
-	      if (size < TREE_STRING_LENGTH (init))
+	      if (size < TREE_STRING_LENGTH (stripped_init))
 		{
 		  permerror (loc, "initializer-string for array "
 			     "of chars is too long");
 
-		  init = build_string (size, TREE_STRING_POINTER (init));
+		  init = build_string (size,
+				       TREE_STRING_POINTER (stripped_init));
 		  TREE_TYPE (init) = type;
 		}
 	    }
@@ -1125,7 +1141,7 @@ digest_init_r (tree type, tree init, int nested, int flags,
     }
 
   /* Handle scalar types (including conversions) and references.  */
-  if ((code != COMPLEX_TYPE || BRACE_ENCLOSED_INITIALIZER_P (init))
+  if ((code != COMPLEX_TYPE || BRACE_ENCLOSED_INITIALIZER_P (stripped_init))
       && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
     {
       if (nested)
@@ -1150,23 +1166,23 @@ digest_init_r (tree type, tree init, int nested, int flags,
      the object is initialized from that element."  */
   if (flag_checking
       && cxx_dialect >= cxx11
-      && BRACE_ENCLOSED_INITIALIZER_P (init)
-      && CONSTRUCTOR_NELTS (init) == 1
+      && BRACE_ENCLOSED_INITIALIZER_P (stripped_init)
+      && CONSTRUCTOR_NELTS (stripped_init) == 1
       && ((CLASS_TYPE_P (type) && !CLASSTYPE_NON_AGGREGATE (type))
 	  || VECTOR_TYPE_P (type)))
     {
-      tree elt = CONSTRUCTOR_ELT (init, 0)->value;
+      tree elt = CONSTRUCTOR_ELT (stripped_init, 0)->value;
       if (reference_related_p (type, TREE_TYPE (elt)))
 	/* We should have fixed this in reshape_init.  */
 	gcc_unreachable ();
     }
 
-  if (BRACE_ENCLOSED_INITIALIZER_P (init)
+  if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init)
       && !TYPE_NON_AGGREGATE_CLASS (type))
-    return process_init_constructor (type, init, nested, complain);
+    return process_init_constructor (type, stripped_init, nested, complain);
   else
     {
-      if (COMPOUND_LITERAL_P (init) && code == ARRAY_TYPE)
+      if (COMPOUND_LITERAL_P (stripped_init) && code == ARRAY_TYPE)
 	{
 	  if (complain & tf_error)
 	    error_at (loc, "cannot initialize aggregate of type %qT with "
@@ -1176,12 +1192,12 @@ digest_init_r (tree type, tree init, int nested, int flags,
 	}
 
       if (code == ARRAY_TYPE
-	  && !BRACE_ENCLOSED_INITIALIZER_P (init))
+	  && !BRACE_ENCLOSED_INITIALIZER_P (stripped_init))
 	{
 	  /* Allow the result of build_array_copy and of
 	     build_value_init_noctor.  */
-	  if ((TREE_CODE (init) == VEC_INIT_EXPR
-	       || TREE_CODE (init) == CONSTRUCTOR)
+	  if ((TREE_CODE (stripped_init) == VEC_INIT_EXPR
+	       || TREE_CODE (stripped_init) == CONSTRUCTOR)
 	      && (same_type_ignoring_top_level_qualifiers_p
 		  (type, TREE_TYPE (init))))
 	    return init;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5399288..b982608 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2938,6 +2938,9 @@ combine_comparisons (location_t loc,
 int
 operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 {
+  STRIP_ANY_LOCATION_WRAPPER (arg0);
+  STRIP_ANY_LOCATION_WRAPPER (arg1);
+
   /* When checking, verify at the outermost operand_equal_p call that
      if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
      hash value.  */
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index d086930..e5237d6 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -1455,6 +1455,8 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
 		 || TREE_CODE (t) == COMPONENT_REF)
 	    t = TREE_OPERAND (t, 0);
 
+	  STRIP_ANY_LOCATION_WRAPPER (t);
+
 	  if (t == UOBJC_SUPER_decl)
 	    interface_type = lookup_interface (CLASS_SUPER_NAME (implementation_template));
 	  else if (t == self_decl)
@@ -5339,6 +5341,8 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
   tree retval, class_tree;
   int self, super, have_cast;
 
+  STRIP_ANY_LOCATION_WRAPPER (receiver);
+
   /* We have used the receiver, so mark it as read.  */
   mark_exp_read (receiver);
 
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 562ada7..8149b90 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -80,6 +80,7 @@ selftest::run_tests ()
   input_c_tests ();
   vec_perm_indices_c_tests ();
   tree_c_tests ();
+  convert_c_tests ();
   gimple_c_tests ();
   rtl_tests_c_tests ();
   read_rtl_function_c_tests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 8da7c4a..74be3b7 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -215,6 +215,7 @@ class test_runner
    alphabetical order.  */
 extern void attribute_c_tests ();
 extern void bitmap_c_tests ();
+extern void convert_c_tests ();
 extern void diagnostic_c_tests ();
 extern void diagnostic_show_locus_c_tests ();
 extern void dumpfile_c_tests ();
diff --git a/gcc/testsuite/c-c++-common/pr51712.c b/gcc/testsuite/c-c++-common/pr51712.c
index 69e316d..1ff36c4 100644
--- a/gcc/testsuite/c-c++-common/pr51712.c
+++ b/gcc/testsuite/c-c++-common/pr51712.c
@@ -15,5 +15,5 @@ int valid(enum test_enum arg)
 
 int valid2(unsigned int arg2)
 {
-  return arg2 >= FOO && arg2 <= BAR; /* { dg-bogus "comparison of unsigned expression" "" { xfail *-*-* } } */
+  return arg2 >= FOO && arg2 <= BAR; /* { dg-bogus "comparison of unsigned expression" "" { xfail c } } */
 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp48.C b/gcc/testsuite/g++.dg/cpp1z/decomp48.C
index 35413c7..3c50b02 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp48.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp48.C
@@ -18,7 +18,7 @@ f2 ()
 {
   S v {1, 2};
   auto& [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
-  return s;		// { dg-warning "reference to local variable 'v' returned" }
+  return s;		// { dg-warning "reference to local variable 'v' returned" "" { target *-*-* } .-1 }
 }
 
 int &
@@ -33,7 +33,7 @@ f4 ()
 {
   int a[3] = {1, 2, 3};
   auto& [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
-  return s;		// { dg-warning "reference to local variable 'a' returned" }
+  return s;		// { dg-warning "reference to local variable 'a' returned" "" { target *-*-* } .-1 }
 }
 
 int &
@@ -78,7 +78,7 @@ f10 ()
 {
   S v {1, 2};
   auto& [s, t] = v;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
-  return &s;		// { dg-warning "address of local variable 'v' returned" }
+  return &s;		// { dg-warning "address of local variable 'v' returned" "" { target *-*-* } .-1 }
 }
 
 int *
@@ -93,7 +93,7 @@ f12 ()
 {
   int a[3] = {1, 2, 3};
   auto& [s, t, u] = a;	// { dg-warning "structured bindings only available with" "" { target c++14_down } }
-  return &s;		// { dg-warning "address of local variable 'a' returned" }
+  return &s;		// { dg-warning "address of local variable 'a' returned" "" { target *-*-* } .-1 }
 }
 
 int *
diff --git a/gcc/testsuite/g++.dg/init/array43.C b/gcc/testsuite/g++.dg/init/array43.C
index b4e6512..0078784 100644
--- a/gcc/testsuite/g++.dg/init/array43.C
+++ b/gcc/testsuite/g++.dg/init/array43.C
@@ -1,2 +1,2 @@
-int a[] = 0;  // { dg-error "5:initializer fails to determine size" }
+int a[] = 0;  // { dg-error "11:initializer fails to determine size" }
 // { dg-error "11:array must be initialized" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/init/initializer-string-too-long.C b/gcc/testsuite/g++.dg/init/initializer-string-too-long.C
new file mode 100644
index 0000000..c4ce468
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/initializer-string-too-long.C
@@ -0,0 +1,9 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+/* Verify that we highlight *which* string is too long.  */
+
+char test[3][4] = { "ok", "too long", "ok" }; // { dg-error "initializer-string for array of chars is too long" }
+/* { dg-begin-multiline-output "" }
+ char test[3][4] = { "ok", "too long", "ok" };
+                           ^~~~~~~~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/init/pr43064-1.C b/gcc/testsuite/g++.dg/init/pr43064-1.C
new file mode 100644
index 0000000..8ba396b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-1.C
@@ -0,0 +1,21 @@
+/* Verify that errors about member initializers appear at the bad value,
+   rather than on the last token of the final initializer.  */
+
+// { dg-do compile }
+// { dg-options "-fdiagnostics-show-caret" }
+
+class X {
+  X() : bad(42), // { dg-error "invalid conversion from 'int' to 'void\\*'" }
+	good(42)
+  { }
+  
+  void* bad;
+  int good;
+
+  /* { dg-begin-multiline-output "" }
+   X() : bad(42),
+             ^~
+             |
+             int
+     { dg-end-multiline-output "" } */
+};
diff --git a/gcc/testsuite/g++.dg/init/pr43064-2.C b/gcc/testsuite/g++.dg/init/pr43064-2.C
new file mode 100644
index 0000000..bc87947
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-2.C
@@ -0,0 +1,34 @@
+/* Verify that warnings about member initializers appear at the bad value,
+   rather than on the last token of the final initializer.  */
+
+// { dg-do compile }
+// { dg-options "-Wconversion-null -fdiagnostics-show-caret" }
+
+#define NULL ((void *)0) // { dg-error "invalid conversion from 'void\\*' to 'int'" }
+/* { dg-begin-multiline-output "" }
+ #define NULL ((void *)0)
+              ~^~~~~~~~~~
+               |
+               void*
+   { dg-end-multiline-output "" } */
+
+class A
+{
+public:
+  A();
+  bool m_bool;
+  int m_int;
+  void *m_ptr;
+};
+
+A::A()
+  : m_bool(NULL),
+    m_int(NULL), // { dg-message "in expansion of macro 'NULL'" }
+    m_ptr(NULL)
+{
+}
+
+/* { dg-begin-multiline-output "" }
+     m_int(NULL),
+           ^~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/init/pr43064-3.C b/gcc/testsuite/g++.dg/init/pr43064-3.C
new file mode 100644
index 0000000..36726a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-3.C
@@ -0,0 +1,32 @@
+/* Verify that warnings about member initializers appear at the bad value,
+   rather than on the last token of the final initializer.  */
+
+// { dg-do compile }
+// { dg-options "-Wconversion-null -fdiagnostics-show-caret" }
+
+#define NULL __null // { dg-warning "converting to non-pointer type 'int' from NULL" }
+/* { dg-begin-multiline-output "" }
+ #define NULL __null
+              ^~~~~~
+   { dg-end-multiline-output "" } */
+
+class A
+{
+public:
+  A();
+  bool m_bool;
+  int m_int;
+  void *m_ptr;
+};
+
+A::A()
+  : m_bool(NULL),
+    m_int(NULL), // { dg-message "in expansion of macro 'NULL'" }
+    m_ptr(NULL)
+{
+}
+
+/* { dg-begin-multiline-output "" }
+     m_int(NULL),
+           ^~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/wrappers/Wparentheses.C b/gcc/testsuite/g++.dg/wrappers/Wparentheses.C
new file mode 100644
index 0000000..c6157dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/wrappers/Wparentheses.C
@@ -0,0 +1,10 @@
+// { dg-options "-Wparentheses" }
+
+extern char read_skip_spaces ();
+
+void test ()
+{
+  char c;
+  while ((c = read_skip_spaces ()) && c != ']')
+    ;
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 593ef1a..e4761ec 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6761,6 +6761,9 @@ tree_int_cst_equal (const_tree t1, const_tree t2)
   if (t1 == 0 || t2 == 0)
     return 0;
 
+  STRIP_ANY_LOCATION_WRAPPER (t1);
+  STRIP_ANY_LOCATION_WRAPPER (t2);
+
   if (TREE_CODE (t1) == INTEGER_CST
       && TREE_CODE (t2) == INTEGER_CST
       && wi::to_widest (t1) == wi::to_widest (t2))
@@ -14229,6 +14232,11 @@ maybe_wrap_with_location (tree expr, location_t loc)
   if (EXCEPTIONAL_CLASS_P (expr))
     return expr;
 
+  /* If any auto_suppress_location_wrappers are active, don't create
+     wrappers.  */
+  if (suppress_location_wrappers > 0)
+    return expr;
+
   tree_code code
     = (((CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST)
 	|| (TREE_CODE (expr) == CONST_DECL && !TREE_STATIC (expr)))
@@ -14239,6 +14247,8 @@ maybe_wrap_with_location (tree expr, location_t loc)
   return wrapper;
 }
 
+int suppress_location_wrappers;
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
diff --git a/gcc/tree.h b/gcc/tree.h
index 0ef96ba..311caa1 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -131,6 +131,12 @@ as_internal_fn (combined_fn code)
 #define CONSTANT_CLASS_P(NODE)\
 	(TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_constant)
 
+/* Nonzero if NODE represents a constant, or is a location wrapper
+   around such a node.  */
+
+#define CONSTANT_CLASS_OR_WRAPPER_P(NODE)\
+	(CONSTANT_CLASS_P (tree_strip_any_location_wrapper (NODE)))
+
 /* Nonzero if NODE represents a type.  */
 
 #define TYPE_P(NODE)\
@@ -1175,6 +1181,19 @@ extern void protected_set_expr_location (tree, location_t);
 
 extern tree maybe_wrap_with_location (tree, location_t);
 
+extern int suppress_location_wrappers;
+
+/* A class for suppressing the creation of location wrappers.
+   Location wrappers will not be created during the lifetime
+   of an instance of this class.  */
+
+class auto_suppress_location_wrappers
+{
+ public:
+  auto_suppress_location_wrappers () { ++suppress_location_wrappers; }
+  ~auto_suppress_location_wrappers () { --suppress_location_wrappers; }
+};
+
 /* In a TARGET_EXPR node.  */
 #define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0)
 #define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1)
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2020-11-26 10:02 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-05 19:44 [PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486) David Malcolm
2018-11-05 19:44 ` [PATCH 2/2] C++: improvements to binary operator diagnostics (PR c++/87504) David Malcolm
2018-11-19 16:51 ` [PING] Re: [PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486) David Malcolm
2018-12-03 22:10   ` Jeff Law
2018-12-04 15:20     ` David Malcolm
2018-12-04 21:48     ` [PATCH 1/2] v2: " David Malcolm
2018-12-04 21:48       ` [PATCH 2/2] v2: C++: improvements to binary operator diagnostics (PR c++/87504) David Malcolm
2018-12-11 19:52         ` PING " David Malcolm
2018-12-12 20:43         ` Jason Merrill
2018-12-19 23:28           ` Aaron Sawdey
2018-12-20  2:13             ` [PATCH] -Wtautological-compare: fix comparison of macro expansions David Malcolm
2018-12-20 14:29               ` David Malcolm
2018-12-20 23:35                 ` Aaron Sawdey
2018-12-04 23:31     ` [PING] Re: [PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486) Jason Merrill
2018-12-07 19:25       ` [PATCH 1/2] v3: " David Malcolm
2018-12-12 20:37         ` Jason Merrill
2018-12-13 19:24           ` [PATCH] v4: " David Malcolm
2018-12-13 20:38             ` Jason Merrill
2018-12-14 23:29               ` [PATCH] v5: " David Malcolm
2018-12-17 19:33                 ` Jason Merrill
2018-12-17 23:30                   ` David Malcolm
2018-12-18 20:23                     ` Jason Merrill
2018-12-18 20:34                     ` [PATCH] v6: " David Malcolm
2018-12-18 20:40                       ` Jason Merrill
2018-12-19 15:35                         ` David Malcolm
2018-12-19 19:01 ` [PATCH 1/2] " Thomas Schwinge
2018-12-20  2:29   ` David Malcolm
2020-03-26  5:02   ` [PATCH, OpenACC] Bug fix for processing OpenACC data clauses in C++ Sandra Loosemore
     [not found]     ` <4a68ec90-456a-cf49-036e-471ba275706c@codesourcery.com>
2020-03-26 14:27       ` C++ 'NON_LVALUE_EXPR' in OMP array section handling (was: [PATCH, OpenACC] Bug fix for processing OpenACC data clauses in C++) Thomas Schwinge
2020-03-26 15:09         ` C++ 'NON_LVALUE_EXPR' in OMP array section handling Sandra Loosemore
2020-03-26 20:53           ` Thomas Schwinge
2020-05-25 10:56             ` [WIP] Fold 'NON_LVALUE_EXPR' some more (was: C++ 'NON_LVALUE_EXPR' in OMP array section handling) Thomas Schwinge
2020-11-26  9:36               ` Don't create location wrapper nodes within OpenACC clauses (was: [WIP] Fold 'NON_LVALUE_EXPR' some more (was: C++ 'NON_LVALUE_EXPR' in OMP array section handling)) Thomas Schwinge
2020-11-26 10:02                 ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).