mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-28 16:01:00 +08:00
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
This commit is contained in:
parent
ae9dd7f3f8
commit
415594bb5c
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
25
gcc/cp/cvt.c
25
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);
|
||||
}
|
||||
|
6
gcc/testsuite/g++.dg/delayedfold/fwrapv1.C
Normal file
6
gcc/testsuite/g++.dg/delayedfold/fwrapv1.C
Normal file
@ -0,0 +1,6 @@
|
||||
// PR c++/69631
|
||||
// { dg-options -fwrapv }
|
||||
|
||||
struct C {
|
||||
static const unsigned short max = static_cast<unsigned short>((32767 * 2 + 1));
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user