Commit 415594bb by Jason Merrill Committed by Jason Merrill

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
parent ae9dd7f3
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> 2016-02-08 Bernd Schmidt <bschmidt@redhat.com>
PR rtl-optimization/68730 PR rtl-optimization/68730
......
...@@ -105,12 +105,12 @@ convert_to_pointer (tree type, tree expr) ...@@ -105,12 +105,12 @@ convert_to_pointer (tree type, tree expr)
} }
/* A wrapper around convert_to_pointer_1 that only folds the /* 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 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. /* Convert EXPR to some floating-point type TYPE.
...@@ -403,12 +403,12 @@ convert_to_real (tree type, tree expr) ...@@ -403,12 +403,12 @@ convert_to_real (tree type, tree expr)
} }
/* A wrapper around convert_to_real_1 that only folds the /* 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 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. /* Convert EXPR to some integer (or enum) type TYPE.
...@@ -669,6 +669,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) ...@@ -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 two narrow values can be combined in their narrow type even to
make a wider result--are handled by "shorten" in build_binary_op. */ make a wider result--are handled by "shorten" in build_binary_op. */
if (dofold)
switch (ex_form) switch (ex_form)
{ {
case RSHIFT_EXPR: case RSHIFT_EXPR:
...@@ -857,9 +858,6 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) ...@@ -857,9 +858,6 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
/* This is not correct for ABS_EXPR, /* This is not correct for ABS_EXPR,
since we must test the sign before truncation. */ since we must test the sign before truncation. */
{ {
if (!dofold)
break;
/* Do the arithmetic in type TYPEX, /* Do the arithmetic in type TYPEX,
then convert result to TYPE. */ then convert result to TYPE. */
tree typex = type; tree typex = type;
...@@ -895,7 +893,6 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) ...@@ -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 the conditional and never loses. A COND_EXPR may have a throw
as one operand, which then has void type. Just leave void as one operand, which then has void type. Just leave void
operands as they are. */ operands as they are. */
if (dofold)
return return
fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0),
VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))) VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))
...@@ -968,19 +965,13 @@ convert_to_integer (tree type, tree expr) ...@@ -968,19 +965,13 @@ convert_to_integer (tree type, tree expr)
return convert_to_integer_1 (type, expr, true); return convert_to_integer_1 (type, expr, true);
} }
/* Convert EXPR to some integer (or enum) type TYPE. /* A wrapper around convert_to_complex_1 that only folds the
expression if DOFOLD, or if it is CONSTANT_CLASS_P. */
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. */
tree 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 /* 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) ...@@ -1059,12 +1050,12 @@ convert_to_complex (tree type, tree expr)
} }
/* A wrapper around convert_to_complex_1 that only folds the /* 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 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. */ /* Convert EXPR to the vector type TYPE in the usual ways. */
......
...@@ -21,14 +21,23 @@ along with GCC; see the file COPYING3. If not see ...@@ -21,14 +21,23 @@ along with GCC; see the file COPYING3. If not see
#define GCC_CONVERT_H #define GCC_CONVERT_H
extern tree convert_to_integer (tree, tree); 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 (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 (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_fixed (tree, tree);
extern tree convert_to_complex (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 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 */ #endif /* GCC_CONVERT_H */
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> 2016-02-05 Martin Sebor <msebor@redhat.com>
PR c++/69662 PR c++/69662
......
...@@ -1953,7 +1953,13 @@ cp_fold (tree x) ...@@ -1953,7 +1953,13 @@ cp_fold (tree x)
loc = EXPR_LOCATION (x); loc = EXPR_LOCATION (x);
op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); 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) if (op0 == error_mark_node)
x = error_mark_node; x = error_mark_node;
......
...@@ -5019,10 +5019,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; ...@@ -5019,10 +5019,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
#define CONV_PRIVATE 16 #define CONV_PRIVATE 16
/* #define CONV_NONCONVERTING 32 */ /* #define CONV_NONCONVERTING 32 */
#define CONV_FORCE_TEMP 64 #define CONV_FORCE_TEMP 64
#define CONV_FOLD 128
#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ #define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET) | CONV_REINTERPRET)
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ #define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP) | 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 /* Used by build_expr_type_conversion to indicate which types are
acceptable as arguments to the expression under consideration. */ acceptable as arguments to the expression under consideration. */
......
...@@ -34,7 +34,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -34,7 +34,6 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h" #include "intl.h"
#include "convert.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 convert_to_pointer_force (tree, tree, tsubst_flags_t);
static tree build_type_conversion (tree, tree); static tree build_type_conversion (tree, tree);
static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); 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); ...@@ -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 Here is a list of all the functions that assume that widening and
narrowing is always done with a NOP_EXPR: 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), In c-typeck.c, build_binary_op_nodefault (boolean ops),
and c_common_truthvalue_conversion. and c_common_truthvalue_conversion.
In expr.c: expand_expr, for operands of a MULT_EXPR. 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); ...@@ -70,7 +69,8 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
else try C-style pointer conversion. */ else try C-style pointer conversion. */
static tree 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); tree intype = TREE_TYPE (expr);
enum tree_code form; enum tree_code form;
...@@ -185,7 +185,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) ...@@ -185,7 +185,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
{ {
if (TREE_CODE (expr) == PTRMEM_CST) if (TREE_CODE (expr) == PTRMEM_CST)
return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr), return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr),
complain); dofold, complain);
else if (TREE_CODE (expr) == OFFSET_REF) else if (TREE_CODE (expr) == OFFSET_REF)
{ {
tree object = TREE_OPERAND (expr, 0); tree object = TREE_OPERAND (expr, 0);
...@@ -237,7 +237,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) ...@@ -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))) gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
== GET_MODE_SIZE (TYPE_MODE (type))); == 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)) if (type_unknown_p (expr))
...@@ -296,7 +296,7 @@ convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain) ...@@ -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. /* 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, ...@@ -670,6 +670,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
const char *invalid_conv_diag; const char *invalid_conv_diag;
tree e1; tree e1;
location_t loc = EXPR_LOC_OR_LOC (expr, input_location); location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
bool dofold = (convtype & CONV_FOLD);
if (error_operand_p (e) || type == error_mark_node) if (error_operand_p (e) || type == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -706,7 +707,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, ...@@ -706,7 +707,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
/* For complex data types, we need to perform componentwise /* For complex data types, we need to perform componentwise
conversion. */ conversion. */
else if (TREE_CODE (type) == COMPLEX_TYPE) 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)) else if (VECTOR_TYPE_P (type))
return convert_to_vector (type, e); return convert_to_vector (type, e);
else if (TREE_CODE (e) == TARGET_EXPR) else if (TREE_CODE (e) == TARGET_EXPR)
...@@ -799,7 +800,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, ...@@ -799,7 +800,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
return cp_truthvalue_conversion (e); 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. */ /* Ignore any integer overflow caused by the conversion. */
return ignore_overflows (converted, e); return ignore_overflows (converted, e);
...@@ -811,7 +812,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, ...@@ -811,7 +812,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
return nullptr_node; return nullptr_node;
} }
if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) 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) if (code == VECTOR_TYPE)
{ {
tree in_vtype = TREE_TYPE (e); tree in_vtype = TREE_TYPE (e);
...@@ -842,9 +843,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags, ...@@ -842,9 +843,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
TREE_TYPE (e)); TREE_TYPE (e));
} }
if (code == REAL_TYPE) 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) 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 /* New C++ semantics: since assignment is now based on
...@@ -1460,7 +1461,7 @@ convert (tree type, tree expr) ...@@ -1460,7 +1461,7 @@ convert (tree type, tree expr)
if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype)) if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
return build_nop (type, expr); 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, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
tf_warning_or_error); tf_warning_or_error);
} }
......
// PR c++/69631
// { dg-options -fwrapv }
struct C {
static const unsigned short max = static_cast<unsigned short>((32767 * 2 + 1));
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment