re PR c/66618 (Failure to diagnose non-constant initializer for static object with...
authorJakub Jelinek <jakub@redhat.com>
Sun, 19 Nov 2017 17:17:01 +0000 (18:17 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sun, 19 Nov 2017 17:17:01 +0000 (18:17 +0100)
PR c/66618
PR c/69960
c-family/
* c-common.h (c_fully_fold): Add LVAL argument defaulted to false.
c/
* c-parser.c (c_parser_omp_atomic): Pass true as LVAL to c_fully_fold
where needed.
* c-typeck.c (build_unary_op, build_modify_expr, build_asm_expr,
handle_omp_array_sections): Likewise.
(digest_init): Don't call decl_constant_value_for_optimization.
* c-tree.h (decl_constant_value_for_optimization): Removed.
* c-fold.c (c_fold_array_ref): New function.
(c_fully_fold_internal): Add LVAL argument, propagate it through
recursive calls.  For VAR_P call decl_constant_value and
unshare if not LVAL and either optimizing or IN_INIT.  Remove
decl_constant_value_for_optimization calls.  If IN_INIT and not LVAL,
fold ARRAY_REF with STRING_CST and INTEGER_CST operands.
(c_fully_fold): Add LVAL argument, pass it through to
c_fully_fold_internal.
(decl_constant_value_for_optimization): Removed.
cp/
* cp-gimplify.c (c_fully_fold): Add LVAL argument, call
cp_fold_maybe_rvalue instead of cp_fold_rvalue and pass it !LVAL.
testsuite/
* gcc.dg/pr69960.c: New test.
* gcc.dg/pr66618.c: New test.
* gcc.dg/pr66618-2.c: New test.

From-SVN: r254930

13 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c/ChangeLog
gcc/c/c-fold.c
gcc/c/c-parser.c
gcc/c/c-tree.h
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr66618-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr66618.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr69960.c [new file with mode: 0644]

index 990cd6163bc2dc385125b519f364eb575ba9344b..7323a7d4c91e4535cb019bc48171ac1cb93db1bc 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/66618
+       PR c/69960
+       * c-common.h (c_fully_fold): Add LVAL argument defaulted to false.
+
 2017-11-16  Joseph Myers  <joseph@codesourcery.com>
 
        * c.opt (-std=c17, std=gnu17, -std=iso9899:2017): Refer to 2018
index 5bb86191d2b78cc6967e590ea6e93f7c264767e7..c86c6598c50c7ddc6094a13f8e1a9c4f339ee4a9 100644 (file)
@@ -828,7 +828,7 @@ extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
 extern enum conversion_safety unsafe_conversion_p (location_t, tree, tree, tree,
                                                   bool);
 extern bool decl_with_nonnull_addr_p (const_tree);
-extern tree c_fully_fold (tree, bool, bool *);
+extern tree c_fully_fold (tree, bool, bool *, bool = false);
 extern tree c_wrap_maybe_const (tree, bool);
 extern tree c_common_truthvalue_conversion (location_t, tree);
 extern void c_apply_type_quals_to_decl (int, tree);
index 5622c8ae7875256a96dfbe94ec07fb8a84643454..b10ebfc793a3ce31a5c3bc8d34cd309bbfbee882 100644 (file)
@@ -1,3 +1,23 @@
+2017-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/66618
+       PR c/69960
+       * c-parser.c (c_parser_omp_atomic): Pass true as LVAL to c_fully_fold
+       where needed.
+       * c-typeck.c (build_unary_op, build_modify_expr, build_asm_expr,
+       handle_omp_array_sections): Likewise.
+       (digest_init): Don't call decl_constant_value_for_optimization.
+       * c-tree.h (decl_constant_value_for_optimization): Removed.
+       * c-fold.c (c_fold_array_ref): New function.
+       (c_fully_fold_internal): Add LVAL argument, propagate it through
+       recursive calls.  For VAR_P call decl_constant_value and
+       unshare if not LVAL and either optimizing or IN_INIT.  Remove
+       decl_constant_value_for_optimization calls.  If IN_INIT and not LVAL,
+       fold ARRAY_REF with STRING_CST and INTEGER_CST operands.
+       (c_fully_fold): Add LVAL argument, pass it through to
+       c_fully_fold_internal.
+       (decl_constant_value_for_optimization): Removed.
+
 2017-11-15  Joseph Myers  <joseph@codesourcery.com>
 
        PR c/81156
index 0abc4acc37fb665ec4e839eed8cb70eaeb50e2d0..6a6c7163bbe89e295108c237b5d1cd65feb48f9d 100644 (file)
@@ -27,7 +27,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "gimplify.h"
 
-static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool);
+static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool,
+                                  bool);
 
 /* If DISABLE is true, stop issuing warnings.  This is used when
    parsing code that we know will not be executed.  This function may
@@ -55,6 +56,40 @@ c_enable_warnings (bool enable)
     }
 }
 
+/* Try to fold ARRAY_REF ary[index] if possible and not handled by
+   normal fold, return NULL_TREE otherwise.  */
+
+static tree
+c_fold_array_ref (tree type, tree ary, tree index)
+{
+  if (TREE_CODE (ary) != STRING_CST
+      || TREE_CODE (index) != INTEGER_CST
+      || TREE_OVERFLOW (index)
+      || TREE_CODE (TREE_TYPE (ary)) != ARRAY_TYPE
+      || !tree_fits_uhwi_p (index))
+    return NULL_TREE;
+
+  tree elem_type = TREE_TYPE (TREE_TYPE (ary));
+  unsigned elem_nchars = (TYPE_PRECISION (elem_type)
+                         / TYPE_PRECISION (char_type_node));
+  unsigned len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+  tree nelts = array_type_nelts (TREE_TYPE (ary));
+  bool dummy1 = true, dummy2 = true;
+  nelts = c_fully_fold_internal (nelts, true, &dummy1, &dummy2, false, false);
+  unsigned HOST_WIDE_INT i = tree_to_uhwi (index);
+  if (!tree_int_cst_le (index, nelts)
+      || i >= len
+      || i + elem_nchars > len)
+    return NULL_TREE;
+
+  if (elem_nchars == 1)
+    return build_int_cst (type, TREE_STRING_POINTER (ary)[i]);
+
+  const unsigned char *ptr
+    = ((const unsigned char *)TREE_STRING_POINTER (ary) + i * elem_nchars);
+  return native_interpret_expr (type, ptr, elem_nchars);
+}
+
 /* Fully fold EXPR, an expression that was not folded (beyond integer
    constant expressions and null pointer constants) when being built
    up.  If IN_INIT, this is in a static initializer and certain
@@ -68,10 +103,11 @@ c_enable_warnings (bool enable)
    folded expression.  Function arguments have already been folded
    before calling this function, as have the contents of SAVE_EXPR,
    TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
-   C_MAYBE_CONST_EXPR.  */
+   C_MAYBE_CONST_EXPR.  LVAL is true if it should be treated as an
+   lvalue.  */
 
 tree
-c_fully_fold (tree expr, bool in_init, bool *maybe_const)
+c_fully_fold (tree expr, bool in_init, bool *maybe_const, bool lval)
 {
   tree ret;
   tree eptype = NULL_TREE;
@@ -87,7 +123,7 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const)
       expr = TREE_OPERAND (expr, 0);
     }
   ret = c_fully_fold_internal (expr, in_init, maybe_const,
-                              &maybe_const_itself, false);
+                              &maybe_const_itself, false, lval);
   if (eptype)
     ret = fold_convert_loc (loc, eptype, ret);
   *maybe_const &= maybe_const_itself;
@@ -102,11 +138,13 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const)
    *MAYBE_CONST_ITSELF is carried from only evaluated
    subexpressions).  FOR_INT_CONST indicates if EXPR is an expression
    with integer constant operands, and if any of the operands doesn't
-   get folded to an integer constant, don't fold the expression itself.  */
+   get folded to an integer constant, don't fold the expression itself.
+   LVAL indicates folding of lvalue, where we can't replace it with
+   an rvalue.  */
 
 static tree
 c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
-                      bool *maybe_const_itself, bool for_int_const)
+                      bool *maybe_const_itself, bool for_int_const, bool lval)
 {
   tree ret = expr;
   enum tree_code code = TREE_CODE (expr);
@@ -118,14 +156,27 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
   bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
   bool nowarning = TREE_NO_WARNING (expr);
   bool unused_p;
+  bool op0_lval = false;
   source_range old_range;
 
   /* Constants, declarations, statements, errors, and anything else not
      counted as an expression cannot usefully be folded further at this
      point.  */
-  if (!IS_EXPR_CODE_CLASS (kind)
-      || kind == tcc_statement)
-    return expr;
+  if (!IS_EXPR_CODE_CLASS (kind) || kind == tcc_statement)
+    {
+      /* Except for variables which we can optimize to its initializer.  */
+      if (VAR_P (expr) && !lval && (optimize || in_init))
+       {
+         ret = decl_constant_value (expr);
+         /* Avoid unwanted tree sharing between the initializer and current
+            function's body where the tree can be modified e.g. by the
+            gimplifier.  */
+         if (ret != expr && TREE_STATIC (expr))
+           ret = unshare_expr (ret);
+         return ret;
+       }
+      return expr;
+    }
 
   if (IS_EXPR_CODE_CLASS (kind))
     old_range = EXPR_LOCATION_RANGE (expr);
@@ -150,7 +201,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
        {
          *maybe_const_itself = false;
          inner = c_fully_fold_internal (inner, in_init, maybe_const_operands,
-                                        maybe_const_itself, true);
+                                        maybe_const_itself, true, lval);
        }
       if (pre && !in_init)
        ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
@@ -201,7 +252,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       op1 = TREE_OPERAND (expr, 1);
       op2 = TREE_OPERAND (expr, 2);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const, lval);
       STRIP_TYPE_NOPS (op0);
       if (op0 != orig_op0)
        ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
@@ -218,12 +269,19 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       op2 = TREE_OPERAND (expr, 2);
       op3 = TREE_OPERAND (expr, 3);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const, lval);
       STRIP_TYPE_NOPS (op0);
       op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const, false);
       STRIP_TYPE_NOPS (op1);
-      op1 = decl_constant_value_for_optimization (op1);
+      /* Fold "foo"[2] in initializers.  */
+      if (!lval && in_init)
+       {
+         ret = c_fold_array_ref (TREE_TYPE (expr), op0, op1);
+         if (ret)
+           goto out;
+         ret = expr;
+       }
       if (op0 != orig_op0 || op1 != orig_op1)
        ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
       if (ret != expr)
@@ -232,15 +290,18 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
          TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
          TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
        }
-      ret = fold (ret);
+      if (!lval)
+       ret = fold (ret);
       goto out;
 
-    case COMPOUND_EXPR:
     case MODIFY_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
+      op0_lval = true;
+      /* FALLTHRU */
+    case COMPOUND_EXPR:
     case PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR:
@@ -278,21 +339,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       orig_op0 = op0 = TREE_OPERAND (expr, 0);
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const,
+                                  op0_lval);
       STRIP_TYPE_NOPS (op0);
-      if (code != MODIFY_EXPR
-         && code != PREDECREMENT_EXPR
-         && code != PREINCREMENT_EXPR
-         && code != POSTDECREMENT_EXPR
-         && code != POSTINCREMENT_EXPR)
-       op0 = decl_constant_value_for_optimization (op0);
       /* The RHS of a MODIFY_EXPR was fully folded when building that
         expression for the sake of conversion warnings.  */
       if (code != MODIFY_EXPR)
        op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
-                                    maybe_const_itself, for_int_const);
+                                    maybe_const_itself, for_int_const, false);
       STRIP_TYPE_NOPS (op1);
-      op1 = decl_constant_value_for_optimization (op1);
 
       if (for_int_const && (TREE_CODE (op0) != INTEGER_CST
                            || TREE_CODE (op1) != INTEGER_CST))
@@ -370,6 +425,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
        warn_for_div_by_zero (loc, op1);
       goto out;
 
+    case ADDR_EXPR:
+      op0_lval = true;
+      goto unary;
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      op0_lval = lval;
+      /* FALLTHRU */
     case INDIRECT_REF:
     case FIX_TRUNC_EXPR:
     case FLOAT_EXPR:
@@ -380,17 +442,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
     case NEGATE_EXPR:
     case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
-    case ADDR_EXPR:
     case CONJ_EXPR:
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
+    unary:
       /* Unary operations.  */
       orig_op0 = op0 = TREE_OPERAND (expr, 0);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const,
+                                  op0_lval);
       STRIP_TYPE_NOPS (op0);
-      if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
-       op0 = decl_constant_value_for_optimization (op0);
 
       if (for_int_const && TREE_CODE (op0) != INTEGER_CST)
        goto out;
@@ -440,7 +499,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       orig_op0 = op0 = TREE_OPERAND (expr, 0);
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self,
-                                  for_int_const);
+                                  for_int_const, false);
       STRIP_TYPE_NOPS (op0);
 
       unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
@@ -448,7 +507,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
                          : truthvalue_true_node));
       c_disable_warnings (unused_p);
       op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self,
-                                  for_int_const);
+                                  for_int_const, false);
       STRIP_TYPE_NOPS (op1);
       c_enable_warnings (unused_p);
 
@@ -486,18 +545,18 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       orig_op2 = op2 = TREE_OPERAND (expr, 2);
       op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self,
-                                  for_int_const);
+                                  for_int_const, false);
 
       STRIP_TYPE_NOPS (op0);
       c_disable_warnings (op0 == truthvalue_false_node);
       op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self,
-                                  for_int_const);
+                                  for_int_const, false);
       STRIP_TYPE_NOPS (op1);
       c_enable_warnings (op0 == truthvalue_false_node);
 
       c_disable_warnings (op0 == truthvalue_true_node);
       op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self,
-                                  for_int_const);
+                                  for_int_const, false);
       STRIP_TYPE_NOPS (op2);
       c_enable_warnings (op0 == truthvalue_true_node);
 
@@ -540,13 +599,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       orig_op2 = op2 = TREE_OPERAND (expr, 2);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const, false);
       STRIP_TYPE_NOPS (op0);
       op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const, false);
       STRIP_TYPE_NOPS (op1);
       op2 = c_fully_fold_internal (op2, in_init, maybe_const_operands,
-                                  maybe_const_itself, for_int_const);
+                                  maybe_const_itself, for_int_const, false);
       STRIP_TYPE_NOPS (op2);
 
       if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
@@ -570,7 +629,8 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       if (!SAVE_EXPR_FOLDED_P (expr))
        {
          op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
-                                      maybe_const_itself, for_int_const);
+                                      maybe_const_itself, for_int_const,
+                                      false);
          TREE_OPERAND (expr, 0) = op0;
          SAVE_EXPR_FOLDED_P (expr) = true;
        }
@@ -604,28 +664,3 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
     }
   return ret;
 }
-
-/* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
-   return EXP.  Otherwise, return either EXP or its known constant
-   value (if it has one), but return EXP if EXP has mode BLKmode.  ???
-   Is the BLKmode test appropriate?  */
-
-tree
-decl_constant_value_for_optimization (tree exp)
-{
-  tree ret;
-
-  if (!optimize
-      || !VAR_P (exp)
-      || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
-      || DECL_MODE (exp) == BLKmode)
-    return exp;
-
-  ret = decl_constant_value (exp);
-  /* Avoid unwanted tree sharing between the initializer and current
-     function's body where the tree can be modified e.g. by the
-     gimplifier.  */
-  if (ret != exp && TREE_STATIC (exp))
-    ret = unshare_expr (ret);
-  return ret;
-}
index 3d90e28caad16aab94c8035a8fc94429eb8d098a..bd5dd5799a060c106807f7fa4f872722085a7d73 100644 (file)
@@ -15312,7 +15312,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
     case NOP_EXPR: /* atomic write */
       v = c_parser_cast_expression (parser, NULL).value;
       non_lvalue_p = !lvalue_p (v);
-      v = c_fully_fold (v, false, NULL);
+      v = c_fully_fold (v, false, NULL, true);
       if (v == error_mark_node)
        goto saw_error;
       if (non_lvalue_p)
@@ -15331,7 +15331,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
        {
          lhs = c_parser_cast_expression (parser, NULL).value;
          non_lvalue_p = !lvalue_p (lhs);
-         lhs = c_fully_fold (lhs, false, NULL);
+         lhs = c_fully_fold (lhs, false, NULL, true);
          if (lhs == error_mark_node)
            goto saw_error;
          if (non_lvalue_p)
@@ -15357,7 +15357,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
        {
          v = c_parser_cast_expression (parser, NULL).value;
          non_lvalue_p = !lvalue_p (v);
-         v = c_fully_fold (v, false, NULL);
+         v = c_fully_fold (v, false, NULL, true);
          if (v == error_mark_node)
            goto saw_error;
          if (non_lvalue_p)
@@ -15378,7 +15378,7 @@ restart:
   lhs = expr.value;
   expr = default_function_array_conversion (eloc, expr);
   unfolded_lhs = expr.value;
-  lhs = c_fully_fold (lhs, false, NULL);
+  lhs = c_fully_fold (lhs, false, NULL, true);
   orig_lhs = lhs;
   switch (TREE_CODE (lhs))
     {
@@ -15518,15 +15518,19 @@ restart:
              if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
                {
                  opcode = TREE_CODE (rhs1);
-                 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
-                 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
+                 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+                                     true);
+                 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
+                                      true);
                  goto stmt_done;
                }
              if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
                {
                  opcode = TREE_CODE (rhs1);
-                 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
-                 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
+                 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
+                                     true);
+                 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+                                      true);
                  swapped = !commutative_tree_code (opcode);
                  goto stmt_done;
                }
@@ -15545,7 +15549,7 @@ restart:
                  lhs = NULL_TREE;
                  expr = default_function_array_read_conversion (eloc, expr);
                  unfolded_lhs1 = expr.value;
-                 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL);
+                 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
                  rhs1 = NULL_TREE;
                  c_parser_consume_token (parser);
                  goto restart;
@@ -15554,7 +15558,7 @@ restart:
                {
                  opcode = NOP_EXPR;
                  expr = default_function_array_read_conversion (eloc, expr);
-                 rhs = c_fully_fold (expr.value, false, NULL);
+                 rhs = c_fully_fold (expr.value, false, NULL, true);
                  rhs1 = NULL_TREE;
                  goto stmt_done;
                }
@@ -15575,7 +15579,7 @@ restart:
       expr = c_parser_expression (parser);
       expr = default_function_array_read_conversion (eloc, expr);
       rhs = expr.value;
-      rhs = c_fully_fold (rhs, false, NULL);
+      rhs = c_fully_fold (rhs, false, NULL, true);
       break;
     }
 stmt_done:
@@ -15585,7 +15589,7 @@ stmt_done:
        goto saw_error;
       v = c_parser_cast_expression (parser, NULL).value;
       non_lvalue_p = !lvalue_p (v);
-      v = c_fully_fold (v, false, NULL);
+      v = c_fully_fold (v, false, NULL, true);
       if (v == error_mark_node)
        goto saw_error;
       if (non_lvalue_p)
@@ -15597,7 +15601,7 @@ stmt_done:
       lhs1 = expr.value;
       expr = default_function_array_read_conversion (eloc, expr);
       unfolded_lhs1 = expr.value;
-      lhs1 = c_fully_fold (lhs1, false, NULL);
+      lhs1 = c_fully_fold (lhs1, false, NULL, true);
       if (lhs1 == error_mark_node)
        goto saw_error;
       if (!lvalue_p (unfolded_lhs1))
index 11356476d840b7f8b95351bef82be01d85da86a0..5fb57f21bd19bf1e526366dc033b328248f15ebf 100644 (file)
@@ -770,8 +770,6 @@ set_c_expr_source_range (c_expr *expr,
                         source_range src_range);
 
 /* In c-fold.c */
-extern tree decl_constant_value_for_optimization (tree);
-
 extern vec<tree> incomplete_record_decls;
 
 #if CHECKING_P
index 4bdc48a9ea38d1e0e235b3b51cbf03090a182799..8a09ea2ea460963a2948901950d39199138e78b7 100644 (file)
@@ -4398,7 +4398,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
        }
 
       /* Ensure the argument is fully folded inside any SAVE_EXPR.  */
-      arg = c_fully_fold (arg, false, NULL);
+      arg = c_fully_fold (arg, false, NULL, true);
 
       bool atomic_op;
       atomic_op = really_atomic_lvalue (arg);
@@ -5822,7 +5822,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
 
   if (modifycode != NOP_EXPR)
     {
-      lhs = c_fully_fold (lhs, false, NULL);
+      lhs = c_fully_fold (lhs, false, NULL, true);
       lhs = stabilize_reference (lhs);
 
       /* Construct the RHS for any non-atomic compound assignemnt. */
@@ -7289,7 +7289,6 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
       inside_init = TREE_OPERAND (inside_init, 0);
     }
   inside_init = c_fully_fold (inside_init, require_constant, &maybe_const);
-  inside_init = decl_constant_value_for_optimization (inside_init);
 
   /* Initialization of an array of chars from a string constant
      optionally enclosed in braces.  */
@@ -9899,7 +9898,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
     {
       tree output = TREE_VALUE (tail);
 
-      output = c_fully_fold (output, false, NULL);
+      output = c_fully_fold (output, false, NULL, true);
 
       /* ??? Really, this should not be here.  Users should be using a
         proper lvalue, dammit.  But there's a long history of using casts
@@ -9957,7 +9956,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
             mark it addressable.  */
          if (!allows_reg && allows_mem)
            {
-             input = c_fully_fold (input, false, NULL);
+             input = c_fully_fold (input, false, NULL, true);
 
              /* Strip the nops as we allow this case.  FIXME, this really
                 should be rejected or made deprecated.  */
@@ -12723,7 +12722,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
        }
       if (tem)
        first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
-      first = c_fully_fold (first, false, NULL);
+      first = c_fully_fold (first, false, NULL, true);
       OMP_CLAUSE_DECL (c) = first;
     }
   else
index e0bb1b1ddd43c4538f83e53ffa6bf8aeadeace30..410b18b42fd8599855a9c90a024789738c4ef6ee 100644 (file)
@@ -1,3 +1,10 @@
+2017-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/66618
+       PR c/69960
+       * cp-gimplify.c (c_fully_fold): Add LVAL argument, call
+       cp_fold_maybe_rvalue instead of cp_fold_rvalue and pass it !LVAL.
+
 2017-11-16  Jason Merrill  <jason@redhat.com>
 
        PR c++/79092 - non-type args of different types are different
index 7c7c0409af8378769a6fd8420a70e23e1e63ee60..8849f9d3735ed18d9bbf3ff47d8b311e74354b53 100644 (file)
@@ -2048,11 +2048,9 @@ cp_fully_fold (tree x)
    C_MAYBE_CONST_EXPR.  */
 
 tree
-c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/)
+c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/, bool lval)
 {
-  /* c_fully_fold is only used on rvalues, and we need to fold CONST_DECL to
-     INTEGER_CST.  */
-  return cp_fold_rvalue (x);
+  return cp_fold_maybe_rvalue (x, !lval);
 }
 
 static GTY((deletable)) hash_map<tree, tree> *fold_cache;
index 25cb660fb385b1f8e505ea49284d08d1c107dbfc..705730b57067bc22cce6fab1d8a82c358f037d63 100644 (file)
@@ -1,3 +1,11 @@
+2017-11-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/66618
+       PR c/69960
+       * gcc.dg/pr69960.c: New test.
+       * gcc.dg/pr66618.c: New test.
+       * gcc.dg/pr66618-2.c: New test.
+
 2017-11-18  Janne Blomqvist  <jb@gcc.gnu.org>
 
        PR fortran/44292
diff --git a/gcc/testsuite/gcc.dg/pr66618-2.c b/gcc/testsuite/gcc.dg/pr66618-2.c
new file mode 100644 (file)
index 0000000..3cb2e44
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR c/66618 */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+int a = "foo"[2];
+int b = 1["bar"];
+int c = "baz"[__INT_MAX__ * -2];       /* { dg-error "initializer element is not constant" } */
+int d = "str"[3];                      /* { dg-warning "integer overflow in expression of type" "" { target *-*-* } .-1 } */
+int e = "str"[4];                      /* { dg-error "initializer element is not constant" } */
+int f = "str"[-1];                     /* { dg-error "initializer element is not constant" } */
diff --git a/gcc/testsuite/gcc.dg/pr66618.c b/gcc/testsuite/gcc.dg/pr66618.c
new file mode 100644 (file)
index 0000000..649d4f6
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR c/66618 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+int
+foo (void)
+{
+  const int a = 0;
+  static int b = a;    /* { dg-bogus "initializer element is not constant" } */
+  return b;
+}
diff --git a/gcc/testsuite/gcc.dg/pr69960.c b/gcc/testsuite/gcc.dg/pr69960.c
new file mode 100644 (file)
index 0000000..e339d30
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR c/69960 */
+/* { dg-do compile { target int32plus } } */
+
+#define TOLOWER(x) (x&~0x20)
+#define Word(s) \
+  s[1] ? s[2] ? s[3] ? \
+    (TOLOWER(s[0]) << 24) + (TOLOWER(s[1]) << 16) + (TOLOWER(s[2]) << 8) + TOLOWER(s[3]) : \
+    (TOLOWER(s[0]) << 16) + (TOLOWER(s[1]) << 8) + TOLOWER(s[2]) : \
+    (TOLOWER(s[0]) << 8) + TOLOWER(s[1]) : \
+    TOLOWER(s[0])
+
+const unsigned int _the = Word("the");