]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
C++: more location wrapper nodes (PR c++/43064, PR c++/43486)
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Dec 2018 15:08:21 +0000 (15:08 +0000)
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Dec 2018 15:08:21 +0000 (15:08 +0000)
This is v6 of the patch, as posted to:
  https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01331.html

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" };
      |                           ^~~~~~~~~~

gcc/c-family/ChangeLog:
PR c++/43064
PR c++/43486
* c-common.c (unsafe_conversion_p): Fold 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/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): Strip expr when using TREE_OVERFLOW.
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.
* convert.h (preserve_any_location_wrapper): New decl.
* fold-const.c (size_binop_loc): Strip location wrappers when
using TREE_OVERFLOW.
(operand_equal_p): Strip any location wrappers.
(integer_valued_real_p): Strip any location wrapper.
* selftest-run-tests.c (selftest::run_tests): Call
selftest::convert_c_tests.
* selftest.h (selftest::convert_c_tests): New decl.
* tree.c (build_complex): Assert that REAL and IMAG are constants.
(integer_zerop): Look through location wrappers.
(integer_onep): Likewise.
(integer_each_onep): Likewise.
(integer_all_onesp): Likewise.
(integer_minus_onep): Likewise.
(integer_pow2p): Likewise.
(integer_nonzerop): Likewise.
(integer_truep): Likewise.
(fixed_zerop): Likewise.
(real_zerop): Likewise.
(real_onep): Likewise.
(real_minus_onep): Likewise.
(tree_int_cst_equal): Likewise.
(simple_cst_equal): Treat location wrappers with non-equal source
locations as being unequal.
(uniform_integer_cst_p): Look through location wrappers.
(maybe_wrap_with_location): Don't create wrappers if any
auto_suppress_location_wrappers are active.
(suppress_location_wrappers): New variable.
(selftest::test_predicates): New test.
(selftest::tree_c_tests): Call it.
* tree.h (CONSTANT_CLASS_OR_WRAPPER_P): New macro.
(suppress_location_wrappers): New decl.
(class auto_suppress_location_wrappers): New class.

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.
* 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.
* 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_unary_expression): Ensure that folding of NEGATE_EXPR
around a constant happens in the presence of location wrappers and
returns a wrapped result.
(cp_parser_has_attribute_expression): Strip any location wrapper
from "oper".
(cp_parser_binary_expression): Strip any location wrapper when
checking for DECL_P on the lhs.
(cp_parser_decltype): Strip any location wrapper from result of
cp_parser_decltype_expr.
(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.
(cp_parser_std_attribute_spec_seq): Likewise.
(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.
(tsubst_default_argument): Move note about which callsite led to
instantiation to after the check_default_argument call.
(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.
(capture_decltype): Use lookup_name_real rather than value_member
when looking up decl within the capture-list.
* tree.c (cp_stabilize_reference): Strip any location wrapper.
(builtin_valid_in_constant_expr_p): Likewise.
(strip_typedefs_expr): Strip any location wrapper before checking
for decls or constants.
(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): Call maybe_constant_value on "idx".
(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.
(gen_declaration): Strip location wrappers from "w".

gcc/testsuite/ChangeLog:
PR c++/43064
PR c++/43486
* c-c++-common/pr51712.c (valid2): Mark xfail as passing on C++.
* g++.dg/cpp0x/constexpr-47969.C: Update column of expected error.
* g++.dg/cpp0x/constexpr-ex2.C: Likewise.
* g++.dg/cpp0x/scoped_enum2.C: Likewise.
* g++.dg/cpp1z/decomp48.C: Update expected location of warning
for named local variables to use that of the local variable.
* g++.dg/ext/vla1.C: Update column.
* 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/new44.C: Add "-ftrack-macro-expansion=0".
* 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/other/fold1.C: Update column of expected error.
* g++.dg/parse/crash36.C: Likewise.
* g++.dg/plugin/diagnostic-test-expressions-1.C: Add negative
integer and float expressions.
* g++.dg/template/defarg6.C: Move expected error to the default
argument; add expected message about where instantiated.
* g++.dg/wrappers/Wparentheses.C: New test.
* g++.old-deja/g++.bugs/900402_02.C: Update column of expected
error.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@267272 138bc75d-0d04-0410-961f-82ee72b054a4

47 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-pretty-print.c
gcc/c-family/c-warn.c
gcc/convert.c
gcc/convert.h
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/constexpr.c
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/fold-const.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/selftest-run-tests.c
gcc/selftest.h
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr51712.c
gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
gcc/testsuite/g++.dg/cpp1z/decomp48.C
gcc/testsuite/g++.dg/ext/vla1.C
gcc/testsuite/g++.dg/init/array43.C
gcc/testsuite/g++.dg/init/initializer-string-too-long.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/new44.C
gcc/testsuite/g++.dg/init/pr43064-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/pr43064-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/pr43064-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/fold1.C
gcc/testsuite/g++.dg/parse/crash36.C
gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
gcc/testsuite/g++.dg/template/defarg6.C
gcc/testsuite/g++.dg/wrappers/Wparentheses.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.bugs/900402_02.C
gcc/tree.c
gcc/tree.h

index 5aef7b5ee10fdf1f950b4f4056d76889d6cbabd8..4784244002b62887e3696baafeeec687ede7da95 100644 (file)
@@ -1,3 +1,53 @@
+2018-12-19  David Malcolm  <dmalcolm@redhat.com>
+
+       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): Strip expr when using TREE_OVERFLOW.
+       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.
+       * convert.h (preserve_any_location_wrapper): New decl.
+       * fold-const.c (size_binop_loc): Strip location wrappers when
+       using TREE_OVERFLOW.
+       (operand_equal_p): Strip any location wrappers.
+       (integer_valued_real_p): Strip any location wrapper.
+       * selftest-run-tests.c (selftest::run_tests): Call
+       selftest::convert_c_tests.
+       * selftest.h (selftest::convert_c_tests): New decl.
+       * tree.c (build_complex): Assert that REAL and IMAG are constants.
+       (integer_zerop): Look through location wrappers.
+       (integer_onep): Likewise.
+       (integer_each_onep): Likewise.
+       (integer_all_onesp): Likewise.
+       (integer_minus_onep): Likewise.
+       (integer_pow2p): Likewise.
+       (integer_nonzerop): Likewise.
+       (integer_truep): Likewise.
+       (fixed_zerop): Likewise.
+       (real_zerop): Likewise.
+       (real_onep): Likewise.
+       (real_minus_onep): Likewise.
+       (tree_int_cst_equal): Likewise.
+       (simple_cst_equal): Treat location wrappers with non-equal source
+       locations as being unequal.
+       (uniform_integer_cst_p): Look through location wrappers.
+       (maybe_wrap_with_location): Don't create wrappers if any
+       auto_suppress_location_wrappers are active.
+       (suppress_location_wrappers): New variable.
+       (selftest::test_predicates): New test.
+       (selftest::tree_c_tests): Call it.
+       * tree.h (CONSTANT_CLASS_OR_WRAPPER_P): New macro.
+       (suppress_location_wrappers): New decl.
+       (class auto_suppress_location_wrappers): New class.
+
 2018-12-19  Paul A. Clarke  <pc@us.ibm.com>
 
        * config/rs6000/tmmintrin.h (_mm_hadds_epi16): Vector lanes swapped.
index 7015aeec693330e71d41b826a29efcd8ad7efb92..eb148bb25e76c6231c8839981f6e3e3ea73fa624 100644 (file)
@@ -1,3 +1,27 @@
+2018-12-19  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/43064
+       PR c++/43486
+       * c-common.c (unsafe_conversion_p): Fold 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.
+
 2018-12-06  Jason Merrill  <jason@redhat.com>
 
        PR c++/88136 - -Wdeprecated-copy false positives
index 4c903650650d2a42f044e7a99012ee4040f0e4c4..2282515a1925a8019c02e9c1e7da0cccd9af53d0 100644 (file)
@@ -1250,6 +1250,8 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
 
     loc = expansion_point_location_if_in_system_header (loc);
 
+  expr = fold_for_warn (expr);
+
   if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
     {
       /* If type is complex, we are interested in compatibility with
@@ -1947,6 +1949,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.
@@ -3241,6 +3250,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:
@@ -3460,6 +3470,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;
     }
@@ -6279,6 +6297,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)
@@ -6357,6 +6376,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
@@ -7906,6 +7927,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)))
index a13cd8490533d21a83c75b41e58af906d1a693d2..5a55440778c4a67445450647f3886bf2330ddfcd 100644 (file)
@@ -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;
     }
 }
index 798ad1bcb399fd30969d879bc2247305bc156797..4c0bdf96d4c368068dfa189ff7ae187c3c8f0a5e 100644 (file)
@@ -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.
@@ -1529,6 +1538,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.  */
@@ -1669,15 +1679,22 @@ 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)
+    {
+      /* If INDEX has a location, use it; otherwise use LOC (the location
+        of the subscripting expression as a whole).  */
+      loc = EXPR_LOC_OR_LOC (index, loc);
+      STRIP_ANY_LOCATION_WRAPPER (index);
+      if (TREE_CODE (index) != INTEGER_CST)
+       warning_at (loc, OPT_Wchar_subscripts,
+                   "array subscript has type %<char%>");
+    }
 }
 
 /* Implement -Wparentheses for the unexpected C precedence rules, to
index 68705f3e9b09c5d0e6bae0ba1c7bca0db7107980..028497fdf27d16ef4576559b667119007baf0d82 100644 (file)
@@ -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.  */
+
+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
@@ -679,7 +705,8 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      if (integer_zerop (expr) && !TREE_OVERFLOW (expr))
+      if (integer_zerop (expr)
+         && !TREE_OVERFLOW (tree_strip_any_location_wrapper (expr)))
        return build_int_cst (type, 0);
 
       /* Convert to an unsigned integer of the correct width first, and from
@@ -959,7 +986,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 +1044,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 +1131,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 +1204,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 */
index 4ffa6ef8534458258f3aeb3ab4a475b918a87a48..f3334f973ee0cdbbfc4f797f64a625fea61f96db 100644 (file)
@@ -40,4 +40,6 @@ extern inline tree convert_to_real_nofold (tree t, tree x)
 extern inline tree convert_to_complex_nofold (tree t, tree x)
 { return convert_to_complex_maybe_fold (t, x, false); }
 
+extern tree preserve_any_location_wrapper (tree result, tree orig_expr);
+
 #endif /* GCC_CONVERT_H */
index b2360d54354c4d7a74aa61b2fab0859a0a729f28..0ebc36692863ba4e3edd5c9ff20b72afe977d9dc 100644 (file)
@@ -1,3 +1,98 @@
+2018-12-19  David Malcolm  <dmalcolm@redhat.com>
+
+       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.
+       * 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.
+       * 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_unary_expression): Ensure that folding of NEGATE_EXPR
+       around a constant happens in the presence of location wrappers and
+       returns a wrapped result.
+       (cp_parser_has_attribute_expression): Strip any location wrapper
+       from "oper".
+       (cp_parser_binary_expression): Strip any location wrapper when
+       checking for DECL_P on the lhs.
+       (cp_parser_decltype): Strip any location wrapper from result of
+       cp_parser_decltype_expr.
+       (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.
+       (cp_parser_std_attribute_spec_seq): Likewise.
+       (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.
+       (tsubst_default_argument): Move note about which callsite led to
+       instantiation to after the check_default_argument call.
+       (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.
+       (capture_decltype): Use lookup_name_real rather than value_member
+       when looking up decl within the capture-list.
+       * tree.c (cp_stabilize_reference): Strip any location wrapper.
+       (builtin_valid_in_constant_expr_p): Likewise.
+       (strip_typedefs_expr): Strip any location wrapper before checking
+       for decls or constants.
+       (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): Call maybe_constant_value on "idx".
+       (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.
+
 2018-12-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/87934
index 6328a36b6049dca5c7fdd30888e7b8d947c0494a..ef3a02ce01ba50a82555c66d9f370dea7934c892 100644 (file)
@@ -5347,9 +5347,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)
index 36e17572a3322657694b97a3ea423d99a463681e..5d6e12f2578081762a582ff4941a1a3c40603e7c 100644 (file)
@@ -7388,6 +7388,14 @@ 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
+       /* TODO: Recursion may be correct for some non-location-wrapper
+          uses of VIEW_CONVERT_EXPR.  */
+       return NULL_TREE;
+
     default:
       return NULL_TREE;
     }
index 79df70e67a10ab7648d95864dacccc6b1755b097..15a30fdcdd0de0bad7c13586068bea3c69f6761a 100644 (file)
@@ -5762,13 +5762,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));
       }
index eb1687377c3e049bd6164a0b6405b0ad90a96ddb..f758f2d9bc8f500ae1c728ef59422a7c84180d80 100644 (file)
@@ -582,15 +582,20 @@ 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;
+
+  return preserve_any_location_wrapper (stripped_expr, expr);
 }
 
 /* Fold away simple conversions, but make sure TREE_OVERFLOW is set
@@ -800,10 +805,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",
index d6028e3608c448e7bd8db683af5ae40f7220c18a..056bf19268467555968bc78b48ff1368ba8fded4 100644 (file)
@@ -6010,14 +6010,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);
@@ -6047,16 +6049,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",
@@ -6116,20 +6118,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;
@@ -6144,24 +6148,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);
            }
        }
@@ -16593,6 +16597,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)));
index 93477bcd12f1409ba8c85ddf86e064d340654ee9..8163866e4ae2b0ce05a0d7882e179d81ab67fa67 100644 (file)
@@ -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:
index 54a1dae488568adbbfb3bfaad97205e3469ef229..5538eebf3e1d52f6a5bb6583b92920d677d5a536 100644 (file)
@@ -1756,7 +1756,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
@@ -2604,6 +2605,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
@@ -2667,11 +2669,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)
@@ -2762,6 +2766,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))
index b57e35d04c5b32b43705d00411f4b3fae72ff24d..c0552b5be910897ed9d789d35931ce275b16afed 100644 (file)
@@ -5232,7 +5232,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:
@@ -5254,9 +5255,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
@@ -7169,8 +7171,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
@@ -8363,18 +8367,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
        case NEGATE_EXPR:
          /* Immediately fold negation of a constant, unless the constant is 0
             (since -0 == 0) or it would overflow.  */
-         if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER
-             && CONSTANT_CLASS_P (cast_expression)
-             && !integer_zerop (cast_expression)
-             && !TREE_OVERFLOW (cast_expression))
+         if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER)
            {
-             tree folded = fold_build1 (unary_operator,
-                                        TREE_TYPE (cast_expression),
-                                        cast_expression);
-             if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+             tree stripped_expr
+               = tree_strip_any_location_wrapper (cast_expression);
+             if (CONSTANT_CLASS_P (stripped_expr)
+                 && !integer_zerop (stripped_expr)
+                 && !TREE_OVERFLOW (stripped_expr))
                {
-                 expression = cp_expr (folded, loc);
-                 break;
+                 tree folded = fold_build1 (unary_operator,
+                                            TREE_TYPE (stripped_expr),
+                                            stripped_expr);
+                 if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+                   {
+                     expression = maybe_wrap_with_location (folded, loc);
+                     break;
+                   }
                }
            }
          /* Fall through.  */
@@ -8489,6 +8497,8 @@ cp_parser_has_attribute_expression (cp_parser *parser)
   if (!oper || oper == error_mark_node)
     oper = cp_parser_unary_expression (parser);
 
+  STRIP_ANY_LOCATION_WRAPPER (oper);
+
   /* Go back to evaluating expressions.  */
   --cp_unevaluated_operand;
   --c_inhibit_evaluation_warnings;
@@ -9508,7 +9518,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,
@@ -14546,6 +14556,7 @@ cp_parser_decltype (cp_parser *parser)
       ++c_inhibit_evaluation_warnings;
 
       expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
+      STRIP_ANY_LOCATION_WRAPPER (expr);
 
       /* Go back to evaluating expressions.  */
       --cp_unevaluated_operand;
@@ -14923,7 +14934,9 @@ cp_parser_mem_initializer (cp_parser* parser)
       vec = cp_parser_parenthesized_expression_list (parser, non_attr,
                                                     /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
-                                                    /*non_constant_p=*/NULL);
+                                                    /*non_constant_p=*/NULL,
+                                                    /*close_paren_loc=*/NULL,
+                                                    /*wrap_locations_p=*/true);
       if (vec == NULL)
        return error_mark_node;
       expression_list = build_tree_list_vec (vec);
@@ -15464,6 +15477,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
@@ -16636,6 +16654,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
@@ -22313,6 +22334,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
@@ -25661,6 +25685,10 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
   tree attribute_list = NULL_TREE;
   bool save_translate_strings_p = parser->translate_strings_p;
 
+  /* Don't create wrapper nodes within attributes: the
+     handlers don't know how to handle them.  */
+  auto_suppress_location_wrappers sentinel;
+
   parser->translate_strings_p = false;
   while (true)
     {
@@ -26106,6 +26134,10 @@ cp_parser_std_attribute_spec_seq (cp_parser *parser)
   tree attr_specs = NULL_TREE;
   tree attr_last = NULL_TREE;
 
+  /* Don't create wrapper nodes within attributes: the
+     handlers don't know how to handle them.  */
+  auto_suppress_location_wrappers sentinel;
+
   while (true)
     {
       tree attr_spec = cp_parser_std_attribute_spec (parser);
@@ -34880,6 +34912,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;
@@ -36597,6 +36632,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;
@@ -39168,6 +39207,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
       else
        {
          cp_parser_parse_tentatively (parser);
+         /* Don't create location wrapper nodes here.  */
+         auto_suppress_location_wrappers sentinel;
          tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false,
                                                  /*check_dependency_p=*/true,
                                                  /*template_p=*/NULL,
index e99de71ea9e25114660f8d0303d1ca3a1d73becf..d4ac034671ae392eaee49d2d548446d72e72fb1a 100644 (file)
@@ -6196,6 +6196,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)
@@ -12756,14 +12757,14 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
 
   finish_lambda_scope ();
 
+  /* Make sure the default argument is reasonable.  */
+  arg = check_default_argument (type, arg, complain);
+
   if (errorcount+sorrycount > errs
       && (complain & tf_warning_or_error))
     inform (input_location,
            "  when instantiating default argument for call to %qD", fn);
 
-  /* Make sure the default argument is reasonable.  */
-  arg = check_default_argument (type, arg, complain);
-
   pop_access_scope (fn);
   pop_from_top_level ();
 
@@ -27224,7 +27225,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)));
index 09ed97de2c7b3d9e79d7d4de92b89c3d20e10b7d..0865076493d5c9f478de1cc28e5ad51584b0aa69 100644 (file)
@@ -1742,7 +1742,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;
 
@@ -1805,8 +1806,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 ());
 
@@ -2299,19 +2301,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)
     {
@@ -2351,7 +2356,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
@@ -2382,6 +2387,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)
@@ -3523,20 +3530,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);
 
@@ -3841,6 +3848,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.  */
 
@@ -9766,12 +9801,12 @@ static tree
 capture_decltype (tree decl)
 {
   tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
-  /* FIXME do lookup instead of list walk? */
-  tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam));
+  tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
+                              /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
   tree type;
 
-  if (cap)
-    type = TREE_TYPE (TREE_PURPOSE (cap));
+  if (cap && is_capture_proxy (cap))
+    type = TREE_TYPE (cap);
   else
     switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam))
       {
index 97074dfab563a53611bab7d248cdef580d120308..aac3ecede8de75e1bcd99f6aeee294c187f89959 100644 (file)
@@ -377,6 +377,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:
@@ -421,6 +422,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;
@@ -1715,6 +1717,8 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
   if (t == NULL_TREE || t == error_mark_node)
     return t;
 
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
   if (DECL_P (t) || CONSTANT_CLASS_P (t))
     return t;
 
@@ -2369,6 +2373,8 @@ lookup_maybe_add (tree fns, tree lookup, bool deduping)
 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)
@@ -2417,6 +2423,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)
@@ -5527,6 +5535,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.  */
index 47ddad16fc1019473fe1a0dfa045abd531aac832..519510dd8b04c3f931f12084614cbca73551f08b 100644 (file)
@@ -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)))
@@ -3415,6 +3425,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
         pointer arithmetic.)  */
       idx = cp_perform_integral_promotions (idx, complain);
 
+      idx = maybe_constant_value (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.
@@ -4561,20 +4573,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");
+               }
            }
        }
 
@@ -4596,15 +4611,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;
        }
@@ -4638,10 +4656,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;
@@ -4842,13 +4861,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
@@ -6080,8 +6103,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)
@@ -8304,7 +8328,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)
        {
@@ -8823,9 +8848,10 @@ convert_for_assignment (tree type, tree rhs,
   enum tree_code coder;
 
   location_t rhs_loc = EXPR_LOC_OR_LOC (rhs, input_location);
-
-  /* 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
@@ -9199,6 +9225,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)
@@ -9300,6 +9328,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
@@ -9326,6 +9356,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))
@@ -9619,6 +9650,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)
index 64e36efd17e60d8b78b56763f776a1e31eed2fc7..c1fa4a94843de3f879c1a73444bae7f84e4c7127 100644 (file)
@@ -460,14 +460,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.  */
 
@@ -1052,6 +1057,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.  */
@@ -1065,7 +1072,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)));
 
@@ -1113,6 +1120,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)))
            {
@@ -1123,12 +1138,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;
                }
            }
@@ -1137,7 +1153,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)
@@ -1162,23 +1178,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 "
@@ -1188,12 +1204,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;
index 45de94c93c5278ebedd698aa0eba481ce91fe93e..1851a3dc39884a3d83d8b1b4afc4d31e6c195d17 100644 (file)
@@ -1911,19 +1911,23 @@ size_binop_loc (location_t loc, enum tree_code code, tree arg0, tree arg1)
       /* And some specific cases even faster than that.  */
       if (code == PLUS_EXPR)
        {
-         if (integer_zerop (arg0) && !TREE_OVERFLOW (arg0))
+         if (integer_zerop (arg0)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg0)))
            return arg1;
-         if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
+         if (integer_zerop (arg1)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg1)))
            return arg0;
        }
       else if (code == MINUS_EXPR)
        {
-         if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
+         if (integer_zerop (arg1)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg1)))
            return arg0;
        }
       else if (code == MULT_EXPR)
        {
-         if (integer_onep (arg0) && !TREE_OVERFLOW (arg0))
+         if (integer_onep (arg0)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg0)))
            return arg1;
        }
 
@@ -2938,6 +2942,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.  */
@@ -13681,6 +13688,8 @@ integer_valued_real_p (tree t, int depth)
   if (t == error_mark_node)
     return false;
 
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
   tree_code code = TREE_CODE (t);
   switch (TREE_CODE_CLASS (code))
     {
index ebff7446f5cc148fefbf0abec04c9bfcc139a7dd..8e11f78907f8ba438c2c7ee2aceae4fd8c80245a 100644 (file)
@@ -1,3 +1,12 @@
+2018-12-19  David Malcolm  <dmalcolm@redhat.com>
+
+       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.
+       (gen_declaration): Strip location wrappers from "w".
+
 2018-10-17  David Malcolm  <dmalcolm@redhat.com>
 
        * Make-lang.in (selftest-objc): New.
index d08693051eaa0afc05a5b229ba930ef0fa601289..42b2fc221f99c943a3d1aeb8cb6076a606d85b69 100644 (file)
@@ -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);
 
@@ -8906,9 +8910,13 @@ gen_declaration (tree decl)
 #else
       tree w = DECL_INITIAL (decl);
 #endif
-      if (w && TREE_CODE (w) == INTEGER_CST)
-       sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
-                TREE_INT_CST_LOW (w));
+      if (w)
+       {
+         STRIP_ANY_LOCATION_WRAPPER (w);
+         if (TREE_CODE (w) == INTEGER_CST)
+           sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
+                    TREE_INT_CST_LOW (w));
+       }
     }
 
   return errbuf;
index 6d65d2491d352ec01643e0791faecc4535f5d473..27be70d4c4e9c6cd95120f4d2f9fcffcdcedd666 100644 (file)
@@ -81,6 +81,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 ();
index 2d7cc3b55e3f79b7c2c6039ece46766e6e533ce5..3b2298b73d8ee97bc011ba821dc8234e26b5692c 100644 (file)
@@ -216,6 +216,7 @@ class test_runner
 extern void attribute_c_tests ();
 extern void bitmap_c_tests ();
 extern void cgraph_c_tests ();
+extern void convert_c_tests ();
 extern void diagnostic_c_tests ();
 extern void diagnostic_show_locus_c_tests ();
 extern void dumpfile_c_tests ();
index 9265458e9740dc1793bd99de1a5652c45bdd1b86..ecf5ad6c9291ba46d4da9774bd7b48979cb45f73 100644 (file)
@@ -1,3 +1,31 @@
+2018-12-19  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/43064
+       PR c++/43486
+       * c-c++-common/pr51712.c (valid2): Mark xfail as passing on C++.
+       * g++.dg/cpp0x/constexpr-47969.C: Update column of expected error.
+       * g++.dg/cpp0x/constexpr-ex2.C: Likewise.
+       * g++.dg/cpp0x/scoped_enum2.C: Likewise.
+       * g++.dg/cpp1z/decomp48.C: Update expected location of warning
+       for named local variables to use that of the local variable.
+       * g++.dg/ext/vla1.C: Update column.
+       * 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/new44.C: Add "-ftrack-macro-expansion=0".
+       * 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/other/fold1.C: Update column of expected error.
+       * g++.dg/parse/crash36.C: Likewise.
+       * g++.dg/plugin/diagnostic-test-expressions-1.C: Add negative
+       integer and float expressions.
+       * g++.dg/template/defarg6.C: Move expected error to the default
+       argument; add expected message about where instantiated.
+       * g++.dg/wrappers/Wparentheses.C: New test.
+       * g++.old-deja/g++.bugs/900402_02.C: Update column of expected
+       error.
+
 2018-12-19  Paul A. Clarke  <pc@us.ibm.com>
 
        * gcc.target/powerpc/ssse3-check.h: Enable tests to run.
index 69e316d24521834a5f31aad89b68969b7ec9fe6b..1ff36c40a1248cf5be2d84b90cbadf3fd641bd3a 100644 (file)
@@ -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 } } */
 }
index bfd9d8fe526223873739d7531a9bae6b9408ae4c..9ff21578b15dfe73a617a16d5d1951cd33871f2e 100644 (file)
@@ -9,4 +9,4 @@ struct A
 constexpr A a = A();
 
 int ar[a]; // { dg-error "could not convert" }
-// { dg-error "5:size of array .ar. has non-integral" "" { target c++11 } .-1 }
+// { dg-error "8:size of array .ar. has non-integral" "" { target c++11 } .-1 }
index e726a348fc8434cf4f849fe0c7a0265bc618fbda..f6973007b8917ac165521f427f2792bd32a5815f 100644 (file)
@@ -19,4 +19,4 @@ constexpr A a = 42;
 X<a> x;            // OK: unique conversion to int
 int ar[X<a>::i]; // also OK
 int ary[a]; // { dg-error "could not convert" } ambiguous conversion
-// { dg-error "5:size of array .ary. has non-integral" "" { target c++11 } .-1 }
+// { dg-error "9:size of array .ary. has non-integral" "" { target c++11 } .-1 }
index 0313c01abb0a29cb90afb31ebd213ff2414f6b1f..c4a869a6539e15cb6fdcced4f6761cdad15aea36 100644 (file)
@@ -5,7 +5,7 @@ enum E2 { e2 = 10 };
 
 struct C {
   int arr[E::e];    // { dg-error "could not convert" }
-// { dg-error "7:size of array .arr. has non-integral" "" { target c++11 } .-1 }
+// { dg-error "14:size of array .arr. has non-integral" "" { target c++11 } .-1 }
   int arr2[E2::e2]; // OK
   int i: E::e;     // { dg-error "could not convert|non-integral type" }
   int i2: E2::e2;   // OK
index 35413c79a9daf32906cd1bd34a008ac0037b7f8f..3c50b02a6c247165b45192a9b1912650ec795aeb 100644 (file)
@@ -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 *
index d6df686cb69ac7904a1b0093da0fd229067e2db3..c017b6e90ed8fb4fd97be6ee0107b27a0535ba12 100644 (file)
@@ -19,7 +19,7 @@ class B { B (int); };
 B::B (int i)
 {
   struct S {
-    int ar[1][i];  // { dg-error "9:size of array .ar. is not an integral" "" { target c++11 } }
+    int ar[1][i];  // { dg-error "15:size of array .ar. is not an integral" "" { target c++11 } }
 // { dg-error "array bound" "" { target c++98_only } .-1 }
   } s;
 
index b4e6512284a7dc1ed639e188ff04d8fa5de3cbc0..00787840f196af8f5b2122880606ec5b734b86fa 100644 (file)
@@ -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 (file)
index 0000000..c4ce468
--- /dev/null
@@ -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 "" } */
index 4ab73209e224181706a069c7d3578d82010cfe26..5c81c2c746b7fe68cb39d87596a969d2ac1e609c 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-ftrack-macro-expansion=0" }
 
 // Test for PR c++/67927 - array new expression with excessive number
 // of elements not diagnosed.
diff --git a/gcc/testsuite/g++.dg/init/pr43064-1.C b/gcc/testsuite/g++.dg/init/pr43064-1.C
new file mode 100644 (file)
index 0000000..171061b
--- /dev/null
@@ -0,0 +1,37 @@
+/* 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 "" } */
+};
+
+class Y {
+  Y() : bad(-1), // { dg-error "invalid conversion from 'int' to 'void\\*'" }
+       good(42)
+  { }
+  
+  void* bad;
+  int good;
+
+  /* { dg-begin-multiline-output "" }
+   Y() : bad(-1),
+             ^~
+             |
+             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 (file)
index 0000000..bc87947
--- /dev/null
@@ -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 (file)
index 0000000..36726a8
--- /dev/null
@@ -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 "" } */
index 25f9accc41d15ae5781c4aa5d6bdc00e1155bb34..8d8df3de68eb368f12c7e6a954da71b033dcc312 100644 (file)
@@ -4,5 +4,5 @@
 struct A
 {
     static const int i = i;  // { dg-error "not declared" }
-    int x[i];               // { dg-error "9:size of array .x. is not an integral constant-expression" }
+    int x[i];               // { dg-error "11:size of array .x. is not an integral constant-expression" }
 };
index 14fcdd833f784336403f230b585f97187a1ef35f..8a2b6f3a6223dd42ea3d786fc3179b63a69f6669 100644 (file)
@@ -9,4 +9,4 @@ template <typename... T> struct A       // { dg-warning "variadic templates" }
   static const int i = sizeof (++t);   // { dg-error "was not declared in this scope" }
 };
 
-int x[A <int>::i];             // { dg-error "5:size of array .x. is not an integral constant-expression" }
+int x[A <int>::i];             // { dg-error "16:size of array .x. is not an integral constant-expression" }
index c08fec4d019dd18957e95b003e862610093002a2..288da2cecff2b3af6cdd06c63538eb7c79bd8166 100644 (file)
@@ -63,6 +63,13 @@ void test_integer_constants (void)
    __emit_expression_range (0, 0);
                                ^
    { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, -273); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, -273);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
 }
 
 void test_character_constants (void)
@@ -111,6 +118,13 @@ void test_floating_constants (void)
    __emit_expression_range (0, 6.022140857e23l );
                                ^~~~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, -273.15f); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, -273.15f);
+                               ^~~~~~~~
+   { dg-end-multiline-output "" } */
+
 }
 
 enum test_enum {
index 15848a13694a8e49277b1e03ecb34a247444bc00..f5fd6b6e10fa04aa1459306be8db4683cf92abc0 100644 (file)
@@ -14,14 +14,12 @@ struct C
 template <typename T>
 struct D
 {
-  static void func (X &ref = a); // not an error at this point
+  static void func (X &ref = a); // { dg-error "cannot bind non-const lvalue reference" }
 };
 
 void Foo (X & obj)
 {
   D<int>::func (obj);
 
-  D<int>::func (); // { dg-error "" }
+  D<int>::func (); // { dg-message "when instantiating default argument for call" }
 }
-
-// { dg-prune-output "passing argument" }
diff --git a/gcc/testsuite/g++.dg/wrappers/Wparentheses.C b/gcc/testsuite/g++.dg/wrappers/Wparentheses.C
new file mode 100644 (file)
index 0000000..c6157dd
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-Wparentheses" }
+
+extern char read_skip_spaces ();
+
+void test ()
+{
+  char c;
+  while ((c = read_skip_spaces ()) && c != ']')
+    ;
+}
index 46a3ec3c276f41b2832a1f4f2bf263202df8639c..21e2765c8eefb764c3d10ed9836fe051ac173685 100644 (file)
@@ -6,17 +6,17 @@
 
 // keywords: arrays, array bound, zero length
 
-typedef int array_type[0];             // { dg-error "13:ISO C\\+\\+ forbids zero-size array" }
+typedef int array_type[0];             // { dg-error "24:ISO C\\+\\+ forbids zero-size array" }
 
-int array_object_1[0];                 // { dg-error "5:ISO C\\+\\+ forbids zero-size array" }
+int array_object_1[0];                 // { dg-error "20:ISO C\\+\\+ forbids zero-size array" }
 
-void function_0 (int formal_array[0])  // { dg-error "22:ISO C\\+\\+ forbids zero-size array" }
+void function_0 (int formal_array[0])  // { dg-error "35:ISO C\\+\\+ forbids zero-size array" }
 {
 }
 
 void function_2 ()
 {
-  int local_object_array_0[0];         // { dg-error "7:ISO C\\+\\+ forbids zero-size array" }
+  int local_object_array_0[0];         // { dg-error "28:ISO C\\+\\+ forbids zero-size array" }
 }
 
 int main () { return 0; }
index 170ef1300ed240fb6a4bd51bdaf94991e46f1f55..5d0d4d3276811e665131647a0820c6a10260573c 100644 (file)
@@ -2208,6 +2208,9 @@ build_string (int len, const char *str)
 tree
 build_complex (tree type, tree real, tree imag)
 {
+  gcc_assert (CONSTANT_CLASS_P (real));
+  gcc_assert (CONSTANT_CLASS_P (imag));
+
   tree t = make_node (COMPLEX_CST);
 
   TREE_REALPART (t) = real;
@@ -2506,11 +2509,13 @@ zerop (const_tree expr)
 }
 
 /* Return 1 if EXPR is the integer constant zero or a complex constant
-   of zero.  */
+   of zero, or a location wrapper for such a constant.  */
 
 bool
 integer_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -2528,11 +2533,13 @@ integer_zerop (const_tree expr)
 }
 
 /* Return 1 if EXPR is the integer constant one or the corresponding
-   complex constant.  */
+   complex constant, or a location wrapper for such a constant.  */
 
 bool
 integer_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -2550,11 +2557,14 @@ integer_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is the integer constant one.  For complex and vector,
-   return 1 if every piece is the integer constant one.  */
+   return 1 if every piece is the integer constant one.
+   Also return 1 for location wrappers for such a constant.  */
 
 bool
 integer_each_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return (integer_onep (TREE_REALPART (expr))
            && integer_onep (TREE_IMAGPART (expr)));
@@ -2563,11 +2573,14 @@ integer_each_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is an integer containing all 1's in as much precision as
-   it contains, or a complex or vector whose subparts are such integers.  */
+   it contains, or a complex or vector whose subparts are such integers,
+   or a location wrapper for such a constant.  */
 
 bool
 integer_all_onesp (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST
       && integer_all_onesp (TREE_REALPART (expr))
       && integer_all_onesp (TREE_IMAGPART (expr)))
@@ -2585,11 +2598,14 @@ integer_all_onesp (const_tree expr)
          == wi::to_wide (expr));
 }
 
-/* Return 1 if EXPR is the integer constant minus one.  */
+/* Return 1 if EXPR is the integer constant minus one, or a location wrapper
+   for such a constant.  */
 
 bool
 integer_minus_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return (integer_all_onesp (TREE_REALPART (expr))
            && integer_zerop (TREE_IMAGPART (expr)));
@@ -2598,11 +2614,13 @@ integer_minus_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is an integer constant that is a power of 2 (i.e., has only
-   one bit on).  */
+   one bit on), or a location wrapper for such a constant.  */
 
 bool
 integer_pow2p (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST
       && integer_pow2p (TREE_REALPART (expr))
       && integer_zerop (TREE_IMAGPART (expr)))
@@ -2615,11 +2633,14 @@ integer_pow2p (const_tree expr)
 }
 
 /* Return 1 if EXPR is an integer constant other than zero or a
-   complex constant other than zero.  */
+   complex constant other than zero, or a location wrapper for such a
+   constant.  */
 
 bool
 integer_nonzerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   return ((TREE_CODE (expr) == INTEGER_CST
           && wi::to_wide (expr) != 0)
          || (TREE_CODE (expr) == COMPLEX_CST
@@ -2629,21 +2650,27 @@ integer_nonzerop (const_tree expr)
 
 /* Return 1 if EXPR is the integer constant one.  For vector,
    return 1 if every piece is the integer constant minus one
-   (representing the value TRUE).  */
+   (representing the value TRUE).
+   Also return 1 for location wrappers for such a constant.  */
 
 bool
 integer_truep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == VECTOR_CST)
     return integer_all_onesp (expr);
   return integer_onep (expr);
 }
 
-/* Return 1 if EXPR is the fixed-point constant zero.  */
+/* Return 1 if EXPR is the fixed-point constant zero, or a location wrapper
+   for such a constant.  */
 
 bool
 fixed_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   return (TREE_CODE (expr) == FIXED_CST
          && TREE_FIXED_CST (expr).data.is_zero ());
 }
@@ -2784,11 +2811,14 @@ tree_ctz (const_tree expr)
 }
 
 /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
-   decimal float constants, so don't return 1 for them.  */
+   decimal float constants, so don't return 1 for them.
+   Also return 1 for location wrappers around such a constant.  */
 
 bool
 real_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2814,11 +2844,14 @@ real_zerop (const_tree expr)
 
 /* Return 1 if EXPR is the real constant one in real or complex form.
    Trailing zeroes matter for decimal float constants, so don't return
-   1 for them.  */
+   1 for them.
+   Also return 1 for location wrappers around such a constant.  */
 
 bool
 real_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2837,11 +2870,14 @@ real_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is the real constant minus one.  Trailing zeroes
-   matter for decimal float constants, so don't return 1 for them.  */
+   matter for decimal float constants, so don't return 1 for them.
+   Also return 1 for location wrappers around such a constant.  */
 
 bool
 real_minus_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -7106,6 +7142,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))
@@ -7266,6 +7305,15 @@ simple_cst_equal (const_tree t1, const_tree t2)
   if (t1 == 0 || t2 == 0)
     return 0;
 
+  /* For location wrappers to be the same, they must be at the same
+     source location (and wrap the same thing).  */
+  if (location_wrapper_p (t1) && location_wrapper_p (t2))
+    {
+      if (EXPR_LOCATION (t1) != EXPR_LOCATION (t2))
+       return 0;
+      return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+    }
+
   code1 = TREE_CODE (t1);
   code2 = TREE_CODE (t2);
 
@@ -11226,11 +11274,14 @@ uniform_vector_p (const_tree vec)
 
 /* If the argument is INTEGER_CST, return it.  If the argument is vector
    with all elements the same INTEGER_CST, return that INTEGER_CST.  Otherwise
-   return NULL_TREE.  */
+   return NULL_TREE.
+   Look through location wrappers. */
 
 tree
 uniform_integer_cst_p (tree t)
 {
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
   if (TREE_CODE (t) == INTEGER_CST)
     return t;
 
@@ -14646,6 +14697,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)))
@@ -14656,6 +14712,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 *
@@ -15146,6 +15204,323 @@ test_location_wrappers ()
   check_strip_nops (wrapped_int_var, int_var);
 }
 
+/* Test various tree predicates.  Verify that location wrappers don't
+   affect the results.  */
+
+static void
+test_predicates ()
+{
+  /* Build various constants and wrappers around them.  */
+
+  location_t loc = BUILTINS_LOCATION;
+
+  tree i_0 = build_int_cst (integer_type_node, 0);
+  tree wr_i_0 = maybe_wrap_with_location (i_0, loc);
+
+  tree i_1 = build_int_cst (integer_type_node, 1);
+  tree wr_i_1 = maybe_wrap_with_location (i_1, loc);
+
+  tree i_m1 = build_int_cst (integer_type_node, -1);
+  tree wr_i_m1 = maybe_wrap_with_location (i_m1, loc);
+
+  tree f_0 = build_real_from_int_cst (float_type_node, i_0);
+  tree wr_f_0 = maybe_wrap_with_location (f_0, loc);
+  tree f_1 = build_real_from_int_cst (float_type_node, i_1);
+  tree wr_f_1 = maybe_wrap_with_location (f_1, loc);
+  tree f_m1 = build_real_from_int_cst (float_type_node, i_m1);
+  tree wr_f_m1 = maybe_wrap_with_location (f_m1, loc);
+
+  tree c_i_0 = build_complex (NULL_TREE, i_0, i_0);
+  tree c_i_1 = build_complex (NULL_TREE, i_1, i_0);
+  tree c_i_m1 = build_complex (NULL_TREE, i_m1, i_0);
+
+  tree c_f_0 = build_complex (NULL_TREE, f_0, f_0);
+  tree c_f_1 = build_complex (NULL_TREE, f_1, f_0);
+  tree c_f_m1 = build_complex (NULL_TREE, f_m1, f_0);
+
+  /* TODO: vector constants.  */
+
+  /* Test integer_onep.  */
+  ASSERT_FALSE (integer_onep (i_0));
+  ASSERT_FALSE (integer_onep (wr_i_0));
+  ASSERT_TRUE (integer_onep (i_1));
+  ASSERT_TRUE (integer_onep (wr_i_1));
+  ASSERT_FALSE (integer_onep (i_m1));
+  ASSERT_FALSE (integer_onep (wr_i_m1));
+  ASSERT_FALSE (integer_onep (f_0));
+  ASSERT_FALSE (integer_onep (wr_f_0));
+  ASSERT_FALSE (integer_onep (f_1));
+  ASSERT_FALSE (integer_onep (wr_f_1));
+  ASSERT_FALSE (integer_onep (f_m1));
+  ASSERT_FALSE (integer_onep (wr_f_m1));
+  ASSERT_FALSE (integer_onep (c_i_0));
+  ASSERT_TRUE (integer_onep (c_i_1));
+  ASSERT_FALSE (integer_onep (c_i_m1));
+  ASSERT_FALSE (integer_onep (c_f_0));
+  ASSERT_FALSE (integer_onep (c_f_1));
+  ASSERT_FALSE (integer_onep (c_f_m1));
+
+  /* Test integer_zerop.  */
+  ASSERT_TRUE (integer_zerop (i_0));
+  ASSERT_TRUE (integer_zerop (wr_i_0));
+  ASSERT_FALSE (integer_zerop (i_1));
+  ASSERT_FALSE (integer_zerop (wr_i_1));
+  ASSERT_FALSE (integer_zerop (i_m1));
+  ASSERT_FALSE (integer_zerop (wr_i_m1));
+  ASSERT_FALSE (integer_zerop (f_0));
+  ASSERT_FALSE (integer_zerop (wr_f_0));
+  ASSERT_FALSE (integer_zerop (f_1));
+  ASSERT_FALSE (integer_zerop (wr_f_1));
+  ASSERT_FALSE (integer_zerop (f_m1));
+  ASSERT_FALSE (integer_zerop (wr_f_m1));
+  ASSERT_TRUE (integer_zerop (c_i_0));
+  ASSERT_FALSE (integer_zerop (c_i_1));
+  ASSERT_FALSE (integer_zerop (c_i_m1));
+  ASSERT_FALSE (integer_zerop (c_f_0));
+  ASSERT_FALSE (integer_zerop (c_f_1));
+  ASSERT_FALSE (integer_zerop (c_f_m1));
+
+  /* Test integer_all_onesp.  */
+  ASSERT_FALSE (integer_all_onesp (i_0));
+  ASSERT_FALSE (integer_all_onesp (wr_i_0));
+  ASSERT_FALSE (integer_all_onesp (i_1));
+  ASSERT_FALSE (integer_all_onesp (wr_i_1));
+  ASSERT_TRUE (integer_all_onesp (i_m1));
+  ASSERT_TRUE (integer_all_onesp (wr_i_m1));
+  ASSERT_FALSE (integer_all_onesp (f_0));
+  ASSERT_FALSE (integer_all_onesp (wr_f_0));
+  ASSERT_FALSE (integer_all_onesp (f_1));
+  ASSERT_FALSE (integer_all_onesp (wr_f_1));
+  ASSERT_FALSE (integer_all_onesp (f_m1));
+  ASSERT_FALSE (integer_all_onesp (wr_f_m1));
+  ASSERT_FALSE (integer_all_onesp (c_i_0));
+  ASSERT_FALSE (integer_all_onesp (c_i_1));
+  ASSERT_FALSE (integer_all_onesp (c_i_m1));
+  ASSERT_FALSE (integer_all_onesp (c_f_0));
+  ASSERT_FALSE (integer_all_onesp (c_f_1));
+  ASSERT_FALSE (integer_all_onesp (c_f_m1));
+
+  /* Test integer_minus_onep.  */
+  ASSERT_FALSE (integer_minus_onep (i_0));
+  ASSERT_FALSE (integer_minus_onep (wr_i_0));
+  ASSERT_FALSE (integer_minus_onep (i_1));
+  ASSERT_FALSE (integer_minus_onep (wr_i_1));
+  ASSERT_TRUE (integer_minus_onep (i_m1));
+  ASSERT_TRUE (integer_minus_onep (wr_i_m1));
+  ASSERT_FALSE (integer_minus_onep (f_0));
+  ASSERT_FALSE (integer_minus_onep (wr_f_0));
+  ASSERT_FALSE (integer_minus_onep (f_1));
+  ASSERT_FALSE (integer_minus_onep (wr_f_1));
+  ASSERT_FALSE (integer_minus_onep (f_m1));
+  ASSERT_FALSE (integer_minus_onep (wr_f_m1));
+  ASSERT_FALSE (integer_minus_onep (c_i_0));
+  ASSERT_FALSE (integer_minus_onep (c_i_1));
+  ASSERT_TRUE (integer_minus_onep (c_i_m1));
+  ASSERT_FALSE (integer_minus_onep (c_f_0));
+  ASSERT_FALSE (integer_minus_onep (c_f_1));
+  ASSERT_FALSE (integer_minus_onep (c_f_m1));
+
+  /* Test integer_each_onep.  */
+  ASSERT_FALSE (integer_each_onep (i_0));
+  ASSERT_FALSE (integer_each_onep (wr_i_0));
+  ASSERT_TRUE (integer_each_onep (i_1));
+  ASSERT_TRUE (integer_each_onep (wr_i_1));
+  ASSERT_FALSE (integer_each_onep (i_m1));
+  ASSERT_FALSE (integer_each_onep (wr_i_m1));
+  ASSERT_FALSE (integer_each_onep (f_0));
+  ASSERT_FALSE (integer_each_onep (wr_f_0));
+  ASSERT_FALSE (integer_each_onep (f_1));
+  ASSERT_FALSE (integer_each_onep (wr_f_1));
+  ASSERT_FALSE (integer_each_onep (f_m1));
+  ASSERT_FALSE (integer_each_onep (wr_f_m1));
+  ASSERT_FALSE (integer_each_onep (c_i_0));
+  ASSERT_FALSE (integer_each_onep (c_i_1));
+  ASSERT_FALSE (integer_each_onep (c_i_m1));
+  ASSERT_FALSE (integer_each_onep (c_f_0));
+  ASSERT_FALSE (integer_each_onep (c_f_1));
+  ASSERT_FALSE (integer_each_onep (c_f_m1));
+
+  /* Test integer_truep.  */
+  ASSERT_FALSE (integer_truep (i_0));
+  ASSERT_FALSE (integer_truep (wr_i_0));
+  ASSERT_TRUE (integer_truep (i_1));
+  ASSERT_TRUE (integer_truep (wr_i_1));
+  ASSERT_FALSE (integer_truep (i_m1));
+  ASSERT_FALSE (integer_truep (wr_i_m1));
+  ASSERT_FALSE (integer_truep (f_0));
+  ASSERT_FALSE (integer_truep (wr_f_0));
+  ASSERT_FALSE (integer_truep (f_1));
+  ASSERT_FALSE (integer_truep (wr_f_1));
+  ASSERT_FALSE (integer_truep (f_m1));
+  ASSERT_FALSE (integer_truep (wr_f_m1));
+  ASSERT_FALSE (integer_truep (c_i_0));
+  ASSERT_TRUE (integer_truep (c_i_1));
+  ASSERT_FALSE (integer_truep (c_i_m1));
+  ASSERT_FALSE (integer_truep (c_f_0));
+  ASSERT_FALSE (integer_truep (c_f_1));
+  ASSERT_FALSE (integer_truep (c_f_m1));
+
+  /* Test integer_nonzerop.  */
+  ASSERT_FALSE (integer_nonzerop (i_0));
+  ASSERT_FALSE (integer_nonzerop (wr_i_0));
+  ASSERT_TRUE (integer_nonzerop (i_1));
+  ASSERT_TRUE (integer_nonzerop (wr_i_1));
+  ASSERT_TRUE (integer_nonzerop (i_m1));
+  ASSERT_TRUE (integer_nonzerop (wr_i_m1));
+  ASSERT_FALSE (integer_nonzerop (f_0));
+  ASSERT_FALSE (integer_nonzerop (wr_f_0));
+  ASSERT_FALSE (integer_nonzerop (f_1));
+  ASSERT_FALSE (integer_nonzerop (wr_f_1));
+  ASSERT_FALSE (integer_nonzerop (f_m1));
+  ASSERT_FALSE (integer_nonzerop (wr_f_m1));
+  ASSERT_FALSE (integer_nonzerop (c_i_0));
+  ASSERT_TRUE (integer_nonzerop (c_i_1));
+  ASSERT_TRUE (integer_nonzerop (c_i_m1));
+  ASSERT_FALSE (integer_nonzerop (c_f_0));
+  ASSERT_FALSE (integer_nonzerop (c_f_1));
+  ASSERT_FALSE (integer_nonzerop (c_f_m1));
+
+  /* Test real_zerop.  */
+  ASSERT_FALSE (real_zerop (i_0));
+  ASSERT_FALSE (real_zerop (wr_i_0));
+  ASSERT_FALSE (real_zerop (i_1));
+  ASSERT_FALSE (real_zerop (wr_i_1));
+  ASSERT_FALSE (real_zerop (i_m1));
+  ASSERT_FALSE (real_zerop (wr_i_m1));
+  ASSERT_TRUE (real_zerop (f_0));
+  ASSERT_TRUE (real_zerop (wr_f_0));
+  ASSERT_FALSE (real_zerop (f_1));
+  ASSERT_FALSE (real_zerop (wr_f_1));
+  ASSERT_FALSE (real_zerop (f_m1));
+  ASSERT_FALSE (real_zerop (wr_f_m1));
+  ASSERT_FALSE (real_zerop (c_i_0));
+  ASSERT_FALSE (real_zerop (c_i_1));
+  ASSERT_FALSE (real_zerop (c_i_m1));
+  ASSERT_TRUE (real_zerop (c_f_0));
+  ASSERT_FALSE (real_zerop (c_f_1));
+  ASSERT_FALSE (real_zerop (c_f_m1));
+
+  /* Test real_onep.  */
+  ASSERT_FALSE (real_onep (i_0));
+  ASSERT_FALSE (real_onep (wr_i_0));
+  ASSERT_FALSE (real_onep (i_1));
+  ASSERT_FALSE (real_onep (wr_i_1));
+  ASSERT_FALSE (real_onep (i_m1));
+  ASSERT_FALSE (real_onep (wr_i_m1));
+  ASSERT_FALSE (real_onep (f_0));
+  ASSERT_FALSE (real_onep (wr_f_0));
+  ASSERT_TRUE (real_onep (f_1));
+  ASSERT_TRUE (real_onep (wr_f_1));
+  ASSERT_FALSE (real_onep (f_m1));
+  ASSERT_FALSE (real_onep (wr_f_m1));
+  ASSERT_FALSE (real_onep (c_i_0));
+  ASSERT_FALSE (real_onep (c_i_1));
+  ASSERT_FALSE (real_onep (c_i_m1));
+  ASSERT_FALSE (real_onep (c_f_0));
+  ASSERT_TRUE (real_onep (c_f_1));
+  ASSERT_FALSE (real_onep (c_f_m1));
+
+  /* Test real_minus_onep.  */
+  ASSERT_FALSE (real_minus_onep (i_0));
+  ASSERT_FALSE (real_minus_onep (wr_i_0));
+  ASSERT_FALSE (real_minus_onep (i_1));
+  ASSERT_FALSE (real_minus_onep (wr_i_1));
+  ASSERT_FALSE (real_minus_onep (i_m1));
+  ASSERT_FALSE (real_minus_onep (wr_i_m1));
+  ASSERT_FALSE (real_minus_onep (f_0));
+  ASSERT_FALSE (real_minus_onep (wr_f_0));
+  ASSERT_FALSE (real_minus_onep (f_1));
+  ASSERT_FALSE (real_minus_onep (wr_f_1));
+  ASSERT_TRUE (real_minus_onep (f_m1));
+  ASSERT_TRUE (real_minus_onep (wr_f_m1));
+  ASSERT_FALSE (real_minus_onep (c_i_0));
+  ASSERT_FALSE (real_minus_onep (c_i_1));
+  ASSERT_FALSE (real_minus_onep (c_i_m1));
+  ASSERT_FALSE (real_minus_onep (c_f_0));
+  ASSERT_FALSE (real_minus_onep (c_f_1));
+  ASSERT_TRUE (real_minus_onep (c_f_m1));
+
+  /* Test zerop.  */
+  ASSERT_TRUE (zerop (i_0));
+  ASSERT_TRUE (zerop (wr_i_0));
+  ASSERT_FALSE (zerop (i_1));
+  ASSERT_FALSE (zerop (wr_i_1));
+  ASSERT_FALSE (zerop (i_m1));
+  ASSERT_FALSE (zerop (wr_i_m1));
+  ASSERT_TRUE (zerop (f_0));
+  ASSERT_TRUE (zerop (wr_f_0));
+  ASSERT_FALSE (zerop (f_1));
+  ASSERT_FALSE (zerop (wr_f_1));
+  ASSERT_FALSE (zerop (f_m1));
+  ASSERT_FALSE (zerop (wr_f_m1));
+  ASSERT_TRUE (zerop (c_i_0));
+  ASSERT_FALSE (zerop (c_i_1));
+  ASSERT_FALSE (zerop (c_i_m1));
+  ASSERT_TRUE (zerop (c_f_0));
+  ASSERT_FALSE (zerop (c_f_1));
+  ASSERT_FALSE (zerop (c_f_m1));
+
+  /* Test tree_expr_nonnegative_p.  */
+  ASSERT_TRUE (tree_expr_nonnegative_p (i_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_i_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (i_1));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_i_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (i_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (wr_i_m1));
+  ASSERT_TRUE (tree_expr_nonnegative_p (f_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_f_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (f_1));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_f_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (f_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (wr_f_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_i_0));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_i_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_i_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_f_0));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_f_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_f_m1));
+
+  /* Test tree_expr_nonzero_p.  */
+  ASSERT_FALSE (tree_expr_nonzero_p (i_0));
+  ASSERT_FALSE (tree_expr_nonzero_p (wr_i_0));
+  ASSERT_TRUE (tree_expr_nonzero_p (i_1));
+  ASSERT_TRUE (tree_expr_nonzero_p (wr_i_1));
+  ASSERT_TRUE (tree_expr_nonzero_p (i_m1));
+  ASSERT_TRUE (tree_expr_nonzero_p (wr_i_m1));
+
+  /* Test integer_valued_real_p.  */
+  ASSERT_FALSE (integer_valued_real_p (i_0));
+  ASSERT_TRUE (integer_valued_real_p (f_0));
+  ASSERT_TRUE (integer_valued_real_p (wr_f_0));
+  ASSERT_TRUE (integer_valued_real_p (f_1));
+  ASSERT_TRUE (integer_valued_real_p (wr_f_1));
+
+  /* Test integer_pow2p.  */
+  ASSERT_FALSE (integer_pow2p (i_0));
+  ASSERT_TRUE (integer_pow2p (i_1));
+  ASSERT_TRUE (integer_pow2p (wr_i_1));
+
+  /* Test uniform_integer_cst_p.  */
+  ASSERT_TRUE (uniform_integer_cst_p (i_0));
+  ASSERT_TRUE (uniform_integer_cst_p (wr_i_0));
+  ASSERT_TRUE (uniform_integer_cst_p (i_1));
+  ASSERT_TRUE (uniform_integer_cst_p (wr_i_1));
+  ASSERT_TRUE (uniform_integer_cst_p (i_m1));
+  ASSERT_TRUE (uniform_integer_cst_p (wr_i_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (f_0));
+  ASSERT_FALSE (uniform_integer_cst_p (wr_f_0));
+  ASSERT_FALSE (uniform_integer_cst_p (f_1));
+  ASSERT_FALSE (uniform_integer_cst_p (wr_f_1));
+  ASSERT_FALSE (uniform_integer_cst_p (f_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (wr_f_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_i_0));
+  ASSERT_FALSE (uniform_integer_cst_p (c_i_1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_i_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_f_0));
+  ASSERT_FALSE (uniform_integer_cst_p (c_f_1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_f_m1));
+}
+
 /* Check that string escaping works correctly.  */
 
 static void
@@ -15199,6 +15574,7 @@ tree_c_tests ()
   test_labels ();
   test_vector_cst_patterns ();
   test_location_wrappers ();
+  test_predicates ();
   test_escaped_strings ();
 }
 
index 761b5083d4d8b02ae6ae779714b7dee298f67892..ab928ca170e16ae7f39fd25d00db8d53c991503e 100644 (file)
@@ -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)