]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/69631 (Bogus overflow in constant expression error)
authorJason Merrill <jason@redhat.com>
Mon, 8 Feb 2016 15:31:47 +0000 (10:31 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 8 Feb 2016 15:31:47 +0000 (10:31 -0500)
PR c++/69631

gcc/
* convert.c (convert_to_integer_1): Check dofold on truncation
distribution.
(convert_to_pointer_maybe_fold, convert_to_real_maybe_fold)
(convert_to_integer_maybe_fold, convert_to_complex_maybe_fold):
Rename from *_nofold.
* convert.h (convert_to_pointer_nofold, convert_to_integer_nofold)
(convert_to_real_nofold, convert_to_complex_nofold): New inlines.
gcc/cp/
* cp-tree.h (CONV_FOLD, CONV_BACKEND_CONVERT): New.
* cvt.c (convert): Pass CONV_BACKEND_CONVERT.
(ocp_convert): Use *_maybe_fold.
(cp_convert_to_pointer): Add dofold parameter.
* cp-gimplify.c (cp_fold) [CONVERT_EXPR]: Call convert.

From-SVN: r233216

gcc/ChangeLog
gcc/convert.c
gcc/convert.h
gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/testsuite/g++.dg/delayedfold/fwrapv1.C [new file with mode: 0644]

index 66deab1c410962e187381cabd31e63fd29ddc8c5..eef961c89638156d0848c4e8198e3e583c409ce0 100644 (file)
@@ -1,3 +1,14 @@
+2016-02-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/69631
+       * convert.c (convert_to_integer_1): Check dofold on truncation
+       distribution.
+       (convert_to_pointer_maybe_fold, convert_to_real_maybe_fold)
+       (convert_to_integer_maybe_fold, convert_to_complex_maybe_fold):
+       Rename from *_nofold.
+       * convert.h (convert_to_pointer_nofold, convert_to_integer_nofold)
+       (convert_to_real_nofold, convert_to_complex_nofold): New inlines.
+
 2016-02-08  Bernd Schmidt  <bschmidt@redhat.com>
 
        PR rtl-optimization/68730
index dd7d818b67bf1012db80dd37a8ceecec15232012..dca1d2b67d4252106656247b1d67ce872632e22e 100644 (file)
@@ -105,12 +105,12 @@ convert_to_pointer (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_pointer_1 that only folds the
-   expression if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
 
 tree
-convert_to_pointer_nofold (tree type, tree expr)
+convert_to_pointer_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_pointer_1 (type, expr, CONSTANT_CLASS_P (expr));
+  return convert_to_pointer_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
 }
 
 /* Convert EXPR to some floating-point type TYPE.
@@ -403,12 +403,12 @@ convert_to_real (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_real_1 that only folds the
-   expression if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
 
 tree
-convert_to_real_nofold (tree type, tree expr)
+convert_to_real_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_real_1 (type, expr, CONSTANT_CLASS_P (expr));
+  return convert_to_real_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
 }
 
 /* Convert EXPR to some integer (or enum) type TYPE.
@@ -669,6 +669,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
         two narrow values can be combined in their narrow type even to
         make a wider result--are handled by "shorten" in build_binary_op.  */
 
+      if (dofold)
       switch (ex_form)
        {
        case RSHIFT_EXPR:
@@ -857,9 +858,6 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
          /* This is not correct for ABS_EXPR,
             since we must test the sign before truncation.  */
          {
-           if (!dofold)
-             break;
-
            /* Do the arithmetic in type TYPEX,
               then convert result to TYPE.  */
            tree typex = type;
@@ -895,7 +893,6 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
             the conditional and never loses.  A COND_EXPR may have a throw
             as one operand, which then has void type.  Just leave void
             operands as they are.  */
-         if (dofold)
            return
              fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0),
                           VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))
@@ -968,19 +965,13 @@ convert_to_integer (tree type, tree expr)
   return convert_to_integer_1 (type, expr, true);
 }
 
-/* Convert EXPR to some integer (or enum) type TYPE.
-
-   EXPR must be pointer, integer, discrete (enum, char, or bool), float,
-   fixed-point or vector; in other cases error is called.
-
-   The result of this is always supposed to be a newly created tree node
-   not in use in any existing structure.  The tree node isn't folded,
-   beside EXPR is of constant class.  */
+/* A wrapper around convert_to_complex_1 that only folds the
+   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
 
 tree
-convert_to_integer_nofold (tree type, tree expr)
+convert_to_integer_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_integer_1 (type, expr, CONSTANT_CLASS_P (expr));
+  return convert_to_integer_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
 }
 
 /* Convert EXPR to the complex type TYPE in the usual ways.  If FOLD_P is
@@ -1059,12 +1050,12 @@ convert_to_complex (tree type, tree expr)
 }
 
 /* A wrapper around convert_to_complex_1 that only folds the
-   expression if it is CONSTANT_CLASS_P.  */
+   expression if DOFOLD, or if it is CONSTANT_CLASS_P.  */
 
 tree
-convert_to_complex_nofold (tree type, tree expr)
+convert_to_complex_maybe_fold (tree type, tree expr, bool dofold)
 {
-  return convert_to_complex_1 (type, expr, CONSTANT_CLASS_P (expr));
+  return convert_to_complex_1 (type, expr, dofold || CONSTANT_CLASS_P (expr));
 }
 
 /* Convert EXPR to the vector type TYPE in the usual ways.  */
index aa8fb9b8a0281ec36be03383c34f3761cd8f238d..bee280de78b52913358dbea15a03688fa10aacc8 100644 (file)
@@ -21,14 +21,23 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_CONVERT_H
 
 extern tree convert_to_integer (tree, tree);
-extern tree convert_to_integer_nofold (tree, tree);
+extern tree convert_to_integer_maybe_fold (tree, tree, bool);
 extern tree convert_to_pointer (tree, tree);
-extern tree convert_to_pointer_nofold (tree, tree);
+extern tree convert_to_pointer_maybe_fold (tree, tree, bool);
 extern tree convert_to_real (tree, tree);
-extern tree convert_to_real_nofold (tree, tree);
+extern tree convert_to_real_maybe_fold (tree, tree, bool);
 extern tree convert_to_fixed (tree, tree);
 extern tree convert_to_complex (tree, tree);
-extern tree convert_to_complex_nofold (tree, tree);
+extern tree convert_to_complex_maybe_fold (tree, tree, bool);
 extern tree convert_to_vector (tree, tree);
 
+extern inline tree convert_to_integer_nofold (tree t, tree x)
+{ return convert_to_integer_maybe_fold (t, x, false); }
+extern inline tree convert_to_pointer_nofold (tree t, tree x)
+{ return convert_to_pointer_maybe_fold (t, x, false); }
+extern inline tree convert_to_real_nofold (tree t, tree x)
+{ return convert_to_real_maybe_fold (t, x, false); }
+extern inline tree convert_to_complex_nofold (tree t, tree x)
+{ return convert_to_complex_maybe_fold (t, x, false); }
+
 #endif /* GCC_CONVERT_H */
index 427425ae17a9c13057d6f4628bbcc3f4d820e16b..470d82536f466a5744d22dc12d1d21d10f517c07 100644 (file)
@@ -1,3 +1,11 @@
+2016-02-08  Jason Merrill  <jason@redhat.com>
+
+       * cp-tree.h (CONV_FOLD, CONV_BACKEND_CONVERT): New.
+       * cvt.c (convert): Pass CONV_BACKEND_CONVERT.
+       (ocp_convert): Use *_maybe_fold.
+       (cp_convert_to_pointer): Add dofold parameter.
+       * cp-gimplify.c (cp_fold) [CONVERT_EXPR]: Call convert.
+
 2016-02-05  Martin Sebor  <msebor@redhat.com>
 
        PR c++/69662
index bb815340dddd9bb9f5027f45c1c7001961814681..d83e9deed07acd8e8ed098ebae75f10debc2888b 100644 (file)
@@ -1953,7 +1953,13 @@ cp_fold (tree x)
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
 
-      if (op0 != TREE_OPERAND (x, 0))
+      if (code == CONVERT_EXPR
+         && SCALAR_TYPE_P (TREE_TYPE (x))
+         && op0 != void_node)
+       /* During parsing we used convert_to_*_nofold; re-convert now using the
+          folding variants, since fold() doesn't do those transformations.  */
+       x = fold (convert (TREE_TYPE (x), op0));
+      else if (op0 != TREE_OPERAND (x, 0))
        {
          if (op0 == error_mark_node)
            x = error_mark_node;
index 0aeee578f7e5a58be0a1d235fb3efb0079489f97..786927b51ac2589b7e39a8084455290d51a4e29a 100644 (file)
@@ -5019,10 +5019,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 #define CONV_PRIVATE    16
 /* #define CONV_NONCONVERTING 32 */
 #define CONV_FORCE_TEMP  64
+#define CONV_FOLD       128
 #define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
                          | CONV_REINTERPRET)
 #define CONV_C_CAST      (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
                          | CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
+#define CONV_BACKEND_CONVERT (CONV_OLD_CONVERT | CONV_FOLD)
 
 /* Used by build_expr_type_conversion to indicate which types are
    acceptable as arguments to the expression under consideration.  */
index f381f9b380063b274cb80e1a9fe9cc68130e406d..60362fd73c4989b8e847958d633e5b9f16c7fdaf 100644 (file)
@@ -34,7 +34,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "convert.h"
 
-static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t);
 static tree convert_to_pointer_force (tree, tree, tsubst_flags_t);
 static tree build_type_conversion (tree, tree);
 static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t);
@@ -50,7 +49,7 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
 
    Here is a list of all the functions that assume that widening and
    narrowing is always done with a NOP_EXPR:
-     In convert.c, convert_to_integer[_nofold].
+     In convert.c, convert_to_integer[_maybe_fold].
      In c-typeck.c, build_binary_op_nodefault (boolean ops),
        and c_common_truthvalue_conversion.
      In expr.c: expand_expr, for operands of a MULT_EXPR.
@@ -70,7 +69,8 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
    else try C-style pointer conversion.  */
 
 static tree
-cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
+cp_convert_to_pointer (tree type, tree expr, bool dofold,
+                      tsubst_flags_t complain)
 {
   tree intype = TREE_TYPE (expr);
   enum tree_code form;
@@ -185,7 +185,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
        {
          if (TREE_CODE (expr) == PTRMEM_CST)
            return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr),
-                                         complain);
+                                         dofold, complain);
          else if (TREE_CODE (expr) == OFFSET_REF)
            {
              tree object = TREE_OPERAND (expr, 0);
@@ -237,7 +237,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
       gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
                  == GET_MODE_SIZE (TYPE_MODE (type)));
 
-      return convert_to_pointer_nofold (type, expr);
+      return convert_to_pointer_maybe_fold (type, expr, dofold);
     }
 
   if (type_unknown_p (expr))
@@ -296,7 +296,7 @@ convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain)
        }
     }
 
-  return cp_convert_to_pointer (type, expr, complain);
+  return cp_convert_to_pointer (type, expr, /*fold*/false, complain);
 }
 
 /* We are passing something to a function which requires a reference.
@@ -670,6 +670,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
   const char *invalid_conv_diag;
   tree e1;
   location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  bool dofold = (convtype & CONV_FOLD);
 
   if (error_operand_p (e) || type == error_mark_node)
     return error_mark_node;
@@ -706,7 +707,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       /* For complex data types, we need to perform componentwise
         conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
-       return convert_to_complex_nofold (type, e);
+       return convert_to_complex_maybe_fold (type, e, dofold);
       else if (VECTOR_TYPE_P (type))
        return convert_to_vector (type, e);
       else if (TREE_CODE (e) == TARGET_EXPR)
@@ -799,7 +800,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
          return cp_truthvalue_conversion (e);
        }
 
-      converted = convert_to_integer_nofold (type, e);
+      converted = convert_to_integer_maybe_fold (type, e, dofold);
 
       /* Ignore any integer overflow caused by the conversion.  */
       return ignore_overflows (converted, e);
@@ -811,7 +812,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       return nullptr_node;
     }
   if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
-    return cp_convert_to_pointer (type, e, complain);
+    return cp_convert_to_pointer (type, e, dofold, complain);
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
@@ -842,9 +843,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
                      TREE_TYPE (e));
        }
       if (code == REAL_TYPE)
-       return convert_to_real_nofold (type, e);
+       return convert_to_real_maybe_fold (type, e, dofold);
       else if (code == COMPLEX_TYPE)
-       return convert_to_complex_nofold (type, e);
+       return convert_to_complex_maybe_fold (type, e, dofold);
     }
 
   /* New C++ semantics:  since assignment is now based on
@@ -1460,7 +1461,7 @@ convert (tree type, tree expr)
   if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
     return build_nop (type, expr);
 
-  return ocp_convert (type, expr, CONV_OLD_CONVERT,
+  return ocp_convert (type, expr, CONV_BACKEND_CONVERT,
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
                      tf_warning_or_error);
 }
diff --git a/gcc/testsuite/g++.dg/delayedfold/fwrapv1.C b/gcc/testsuite/g++.dg/delayedfold/fwrapv1.C
new file mode 100644 (file)
index 0000000..412535c
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/69631
+// { dg-options -fwrapv }
+
+struct C {
+  static const unsigned short max = static_cast<unsigned short>((32767 * 2 + 1));
+};