aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-02-08 10:31:47 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-02-08 10:31:47 -0500
commit415594bb5c49d69f5350401d07abac62bce8656a (patch)
treefffcfe2c7dae6ee698e378ab02e9cdf2d86a254e
parentae9dd7f3f8219057b459356c8234bf4aa73f7e1e (diff)
downloadgcc-415594bb5c49d69f5350401d07abac62bce8656a.zip
gcc-415594bb5c49d69f5350401d07abac62bce8656a.tar.gz
gcc-415594bb5c49d69f5350401d07abac62bce8656a.tar.bz2
re PR c++/69631 (Bogus overflow in constant expression error)
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
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/convert.c37
-rw-r--r--gcc/convert.h17
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-gimplify.c8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/cvt.c25
-rw-r--r--gcc/testsuite/g++.dg/delayedfold/fwrapv1.C6
8 files changed, 74 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 66deab1..eef961c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/convert.c b/gcc/convert.c
index dd7d818..dca1d2b 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -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. */
diff --git a/gcc/convert.h b/gcc/convert.h
index aa8fb9b..bee280d 100644
--- a/gcc/convert.h
+++ b/gcc/convert.h
@@ -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 */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 427425a..470d825 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index bb81534..d83e9de 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0aeee57..786927b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index f381f9b..60362fd 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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
index 0000000..412535c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/fwrapv1.C
@@ -0,0 +1,6 @@
+// PR c++/69631
+// { dg-options -fwrapv }
+
+struct C {
+ static const unsigned short max = static_cast<unsigned short>((32767 * 2 + 1));
+};