From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 85216 invoked by alias); 19 Nov 2018 16:51:22 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 85193 invoked by uid 89); 19 Nov 2018 16:51:21 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=typical, tcc, ranging, 85 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 Nov 2018 16:51:11 +0000 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4186C37E85 for ; Mon, 19 Nov 2018 16:51:10 +0000 (UTC) Received: from ovpn-116-30.phx2.redhat.com (ovpn-116-30.phx2.redhat.com [10.3.116.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id 78AAB19C7B; Mon, 19 Nov 2018 16:51:09 +0000 (UTC) Message-ID: <1542646268.4619.46.camel@redhat.com> Subject: [PING] Re: [PATCH 1/2] C++: more location wrapper nodes (PR c++/43064, PR c++/43486) From: David Malcolm To: gcc-patches@gcc.gnu.org, jason@redhat.com Date: Mon, 19 Nov 2018 16:51:00 -0000 In-Reply-To: <1541449869-59851-1-git-send-email-dmalcolm@redhat.com> References: <1541449869-59851-1-git-send-email-dmalcolm@redhat.com> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2018-11/txt/msg01645.txt.bz2 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 %" > - " applied to non-boolean constant"); > - else > - warning_at (location, OPT_Wlogical_op, "logical %" > - " 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 %" > + " applied to non-boolean constant"); > + else > + warning_at (location, OPT_Wlogical_op, "logical %" > + " 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 %"); > + 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 %"); > + } > } > > /* 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 % 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 % 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 > % 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 *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 *args, > +perform_koenig_lookup (cp_expr fn_expr, vec *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 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 > **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 % (%T)%> does " > - "not compute the number of array > elements", > - type0, type1)) > - if (DECL_P (first_arg)) > - inform (DECL_SOURCE_LOCATION (first_arg), > - "first % 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 % (%T)%> does " > + "not compute the number of array > elements", > + type0, type1)) > + if (DECL_P (first_arg)) > + inform (DECL_SOURCE_LOCATION (first_arg), > + "first % 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)