[PING] Re: [PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486)
David Malcolm
dmalcolm@redhat.com
Mon Nov 19 16:51:00 GMT 2018
Ping, for these patches:
[PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486)
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00304.html
[PATCH 2/2] C++: improvements to binary operator diagnostics (PR c++/87504)
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00303.html
Thanks
Dave
On Mon, 2018-11-05 at 15:31 -0500, David Malcolm wrote:
> 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&ch
> xr=1,58.26,61.79&chco=FF0000,0000FF&chdl=control|experiment&chds=58.2
> 6,61.79&chd=t:59.55,60.26,60.53,60.35,60.17,60.27,59.26,60.01,60.21,6
> 0.23,60.1,60.2,60.12,60.48,60.32,60.18,60.01,60.01,60.04,59.96,60.1,6
> 0.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=Compilatio
> n+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&ch
> xr=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&ch
> xr=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.7
> 2|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.7
> 8,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+kdec
> ore.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=*/fals
> e,
> /*allow_expansi
> on_p=*/true,
> - /*non_constant_
> p=*/NULL);
> + /*non_constant_
> p=*/NULL,
> + /*close_paren_l
> oc=*/NULL,
> + /*wrap_location
> s_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=*/NUL
> L,
> 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)
More information about the Gcc-patches
mailing list