c-decl.c (finish_enum): Simplify code to determine minimum and maximum values of the enum...
2000-01-05 11:25 -0800 Zack Weinberg <zack@rabi.columbia.edu> * c-decl.c (finish_enum): Simplify code to determine minimum and maximum values of the enum, and calculate the type. Remove check for FUNCTION_DECLs in the values list, which cannot happen. Replace the DECL_INITIAL of each enumeration constant with a copy converted to the enumeration type. When updating variant types, don't bother updating the type itself. * c-typeck.c (build_binary_op): Simplify conditional expressions when weeding out spurious signed-unsigned warnings. Add new spurious warning category: if the unsigned quantity is an enum and its maximum value fits in signed_type(result_type). Update commentary. (build_conditional_expr): Warn here if one alternative is signed and the other is unsigned. From-SVN: r31244
This commit is contained in:
parent
28b487d7fe
commit
cb3ca04ee1
@ -1,3 +1,20 @@
|
||||
2000-01-05 11:25 -0800 Zack Weinberg <zack@rabi.columbia.edu>
|
||||
|
||||
* c-decl.c (finish_enum): Simplify code to determine minimum and
|
||||
maximum values of the enum, and calculate the type. Remove check
|
||||
for FUNCTION_DECLs in the values list, which cannot happen. Replace
|
||||
the DECL_INITIAL of each enumeration constant with a copy converted
|
||||
to the enumeration type. When updating variant types, don't bother
|
||||
updating the type itself.
|
||||
|
||||
* c-typeck.c (build_binary_op): Simplify conditional expressions
|
||||
when weeding out spurious signed-unsigned warnings. Add new
|
||||
spurious warning category: if the unsigned quantity is an enum
|
||||
and its maximum value fits in signed_type(result_type). Update
|
||||
commentary.
|
||||
(build_conditional_expr): Warn here if one alternative is signed
|
||||
and the other is unsigned.
|
||||
|
||||
2000-01-05 Nick Clifton <nickc@cygnus.com>
|
||||
|
||||
* config/fr30/fr30.h: Remove extraneous comments.
|
||||
|
101
gcc/c-decl.c
101
gcc/c-decl.c
@ -5664,8 +5664,8 @@ finish_enum (enumtype, values, attributes)
|
||||
{
|
||||
register tree pair, tem;
|
||||
tree minnode = 0, maxnode = 0;
|
||||
int lowprec, highprec, precision;
|
||||
int toplevel = global_binding_level == current_binding_level;
|
||||
int precision, unsign;
|
||||
int toplevel = (global_binding_level == current_binding_level);
|
||||
|
||||
if (in_parm_level_p ())
|
||||
warning ("enum defined inside parms");
|
||||
@ -5677,67 +5677,62 @@ finish_enum (enumtype, values, attributes)
|
||||
if (values == error_mark_node)
|
||||
minnode = maxnode = integer_zero_node;
|
||||
else
|
||||
for (pair = values; pair; pair = TREE_CHAIN (pair))
|
||||
{
|
||||
tree value = TREE_VALUE (pair);
|
||||
if (pair == values)
|
||||
minnode = maxnode = TREE_VALUE (pair);
|
||||
else
|
||||
{
|
||||
if (tree_int_cst_lt (maxnode, value))
|
||||
maxnode = value;
|
||||
if (tree_int_cst_lt (value, minnode))
|
||||
minnode = value;
|
||||
}
|
||||
}
|
||||
{
|
||||
minnode = maxnode = TREE_VALUE (values);
|
||||
for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
|
||||
{
|
||||
tree value = TREE_VALUE (pair);
|
||||
if (tree_int_cst_lt (maxnode, value))
|
||||
maxnode = value;
|
||||
if (tree_int_cst_lt (value, minnode))
|
||||
minnode = value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the final type of this enumeration. It is the same
|
||||
as one of the integral types - the narrowest one that fits, except
|
||||
that normally we only go as narrow as int - and signed iff any of
|
||||
the values are negative. */
|
||||
unsign = (tree_int_cst_sgn (minnode) >= 0);
|
||||
precision = MAX (min_precision (minnode, unsign),
|
||||
min_precision (maxnode, unsign));
|
||||
if (!TYPE_PACKED (enumtype))
|
||||
precision = MAX (precision, TYPE_PRECISION (integer_type_node));
|
||||
if (type_for_size (precision, unsign) == 0)
|
||||
{
|
||||
warning ("enumeration values exceed range of largest integer");
|
||||
precision = TYPE_PRECISION (long_long_integer_type_node);
|
||||
}
|
||||
|
||||
TYPE_MIN_VALUE (enumtype) = minnode;
|
||||
TYPE_MAX_VALUE (enumtype) = maxnode;
|
||||
|
||||
/* An enum can have some negative values; then it is signed. */
|
||||
TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
|
||||
|
||||
/* Determine the precision this type needs. */
|
||||
|
||||
lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype));
|
||||
highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype));
|
||||
precision = MAX (lowprec, highprec);
|
||||
|
||||
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
|
||||
{
|
||||
tree narrowest = type_for_size (precision, 1);
|
||||
if (narrowest == 0)
|
||||
{
|
||||
warning ("enumeration values exceed range of largest integer");
|
||||
narrowest = long_long_integer_type_node;
|
||||
}
|
||||
|
||||
TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest);
|
||||
}
|
||||
else
|
||||
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
|
||||
|
||||
TYPE_PRECISION (enumtype) = precision;
|
||||
TREE_UNSIGNED (enumtype) = unsign;
|
||||
TYPE_SIZE (enumtype) = 0;
|
||||
layout_type (enumtype);
|
||||
|
||||
if (values != error_mark_node)
|
||||
{
|
||||
/* Change the type of the enumerators to be the enum type.
|
||||
Formerly this was done only for enums that fit in an int,
|
||||
but the comment said it was done only for enums wider than int.
|
||||
It seems necessary to do this for wide enums,
|
||||
and best not to change what's done for ordinary narrower ones. */
|
||||
/* Change the type of the enumerators to be the enum type. We
|
||||
need to do this irrespective of the size of the enum, for
|
||||
proper type checking. Replace the DECL_INITIALs of the
|
||||
enumerators, and the value slots of the list, with copies
|
||||
that have the enum type; they cannot be modified in place
|
||||
because they may be shared (e.g. integer_zero_node) Finally,
|
||||
change the purpose slots to point to the names of the decls. */
|
||||
for (pair = values; pair; pair = TREE_CHAIN (pair))
|
||||
{
|
||||
TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
|
||||
DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
|
||||
if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
|
||||
DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
|
||||
}
|
||||
tree enu = TREE_PURPOSE (pair);
|
||||
|
||||
/* Replace the decl nodes in VALUES with their names. */
|
||||
for (pair = values; pair; pair = TREE_CHAIN (pair))
|
||||
TREE_PURPOSE (pair) = DECL_NAME (TREE_PURPOSE (pair));
|
||||
TREE_TYPE (enu) = enumtype;
|
||||
DECL_SIZE (enu) = TYPE_SIZE (enumtype);
|
||||
DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
|
||||
DECL_MODE (enu) = TYPE_MODE (enumtype);
|
||||
DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
|
||||
|
||||
TREE_PURPOSE (pair) = DECL_NAME (enu);
|
||||
TREE_VALUE (pair) = DECL_INITIAL (enu);
|
||||
}
|
||||
|
||||
TYPE_VALUES (enumtype) = values;
|
||||
}
|
||||
@ -5745,6 +5740,8 @@ finish_enum (enumtype, values, attributes)
|
||||
/* Fix up all variant types of this enum type. */
|
||||
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
|
||||
{
|
||||
if (tem == enumtype)
|
||||
continue;
|
||||
TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
|
||||
TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
|
||||
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
|
||||
|
@ -2390,8 +2390,6 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
|
||||
tree primop0 = get_narrower (op0, &unsignedp0);
|
||||
tree primop1 = get_narrower (op1, &unsignedp1);
|
||||
|
||||
/* Avoid spurious warnings for comparison with enumerators. */
|
||||
|
||||
xop0 = orig_op0;
|
||||
xop1 = orig_op1;
|
||||
STRIP_TYPE_NOPS (xop0);
|
||||
@ -2407,28 +2405,41 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
|
||||
all the values of the unsigned type. */
|
||||
if (! TREE_UNSIGNED (result_type))
|
||||
/* OK */;
|
||||
/* Do not warn if both operands are unsigned. */
|
||||
/* Do not warn if both operands are the same signedness. */
|
||||
else if (op0_signed == op1_signed)
|
||||
/* OK */;
|
||||
/* Do not warn if the signed quantity is an unsuffixed
|
||||
integer literal (or some static constant expression
|
||||
involving such literals) and it is non-negative. */
|
||||
else if ((op0_signed && TREE_CODE (xop0) == INTEGER_CST
|
||||
&& tree_int_cst_sgn (xop0) >= 0)
|
||||
|| (op1_signed && TREE_CODE (xop1) == INTEGER_CST
|
||||
&& tree_int_cst_sgn (xop1) >= 0))
|
||||
/* OK */;
|
||||
/* Do not warn if the comparison is an equality operation,
|
||||
the unsigned quantity is an integral constant and it does
|
||||
not use the most significant bit of result_type. */
|
||||
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
|
||||
&& ((op0_signed && TREE_CODE (xop1) == INTEGER_CST
|
||||
&& int_fits_type_p (xop1, signed_type (result_type)))
|
||||
|| (op1_signed && TREE_CODE (xop0) == INTEGER_CST
|
||||
&& int_fits_type_p (xop0, signed_type (result_type)))))
|
||||
/* OK */;
|
||||
else
|
||||
warning ("comparison between signed and unsigned");
|
||||
{
|
||||
tree sop, uop;
|
||||
if (op0_signed)
|
||||
sop = xop0, uop = xop1;
|
||||
else
|
||||
sop = xop1, uop = xop0;
|
||||
|
||||
/* Do not warn if the signed quantity is an unsuffixed
|
||||
integer literal (or some static constant expression
|
||||
involving such literals) and it is non-negative. */
|
||||
if (TREE_CODE (sop) == INTEGER_CST
|
||||
&& tree_int_cst_sgn (sop) >= 0)
|
||||
/* OK */;
|
||||
/* Do not warn if the comparison is an equality operation,
|
||||
the unsigned quantity is an integral constant, and it
|
||||
would fit in the result if the result were signed. */
|
||||
else if (TREE_CODE (uop) == INTEGER_CST
|
||||
&& (resultcode == EQ_EXPR || resultcode == NE_EXPR)
|
||||
&& int_fits_type_p (uop, signed_type (result_type)))
|
||||
/* OK */;
|
||||
/* Do not warn if the unsigned quantity is an enumeration
|
||||
constant and its maximum value would fit in the result
|
||||
if the result were signed. */
|
||||
else if (TREE_CODE (uop) == INTEGER_CST
|
||||
&& TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
|
||||
&& int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE(uop)),
|
||||
signed_type (result_type)))
|
||||
/* OK */;
|
||||
else
|
||||
warning ("comparison between signed and unsigned");
|
||||
}
|
||||
|
||||
/* Warn if two unsigned values are being compared in a size
|
||||
larger than their original size, and one (and only one) is the
|
||||
@ -3362,6 +3373,37 @@ build_conditional_expr (ifexp, op1, op2)
|
||||
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
|
||||
{
|
||||
result_type = common_type (type1, type2);
|
||||
|
||||
/* If -Wsign-compare, warn here if type1 and type2 have
|
||||
different signedness. We'll promote the signed to unsigned
|
||||
and later code won't know it used to be different.
|
||||
Do this check on the original types, so that explicit casts
|
||||
will be considered, but default promotions won't. */
|
||||
if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare)
|
||||
&& !skip_evaluation)
|
||||
{
|
||||
int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1));
|
||||
int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2));
|
||||
|
||||
if (unsigned_op1 ^ unsigned_op2)
|
||||
{
|
||||
/* Do not warn if the result type is signed, since the
|
||||
signed type will only be chosen if it can represent
|
||||
all the values of the unsigned type. */
|
||||
if (! TREE_UNSIGNED (result_type))
|
||||
/* OK */;
|
||||
/* Do not warn if the signed quantity is an unsuffixed
|
||||
integer literal (or some static constant expression
|
||||
involving such literals) and it is non-negative. */
|
||||
else if ((unsigned_op2 && TREE_CODE (op1) == INTEGER_CST
|
||||
&& tree_int_cst_sgn (op1) >= 0)
|
||||
|| (unsigned_op1 && TREE_CODE (op2) == INTEGER_CST
|
||||
&& tree_int_cst_sgn (op2) >= 0))
|
||||
/* OK */;
|
||||
else
|
||||
warning ("signed and unsigned type in conditional expression");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
|
||||
{
|
||||
|
@ -4,23 +4,36 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wsign-compare" } */
|
||||
|
||||
int target_flags = 1;
|
||||
int tf = 1;
|
||||
|
||||
enum machine_mode
|
||||
/* This enumeration has an explicit negative value and is therefore signed. */
|
||||
enum mm1
|
||||
{
|
||||
VOIDmode , PQImode , QImode , PHImode , HImode ,
|
||||
PSImode , SImode , PDImode , DImode , TImode , OImode , QFmode ,
|
||||
HFmode , TQFmode , SFmode , DFmode , XFmode , TFmode , QCmode ,
|
||||
HCmode , SCmode , DCmode , XCmode , TCmode , CQImode , CHImode ,
|
||||
CSImode , CDImode , CTImode , COImode , BLKmode , CCmode , CCXmode,
|
||||
CC_NOOVmode, CCX_NOOVmode, CCFPmode, CCFPEmode , MAX_MACHINE_MODE
|
||||
VOID, SI, DI, MAX = -1
|
||||
};
|
||||
|
||||
#define Pmode ( target_flags ? DImode : SImode )
|
||||
|
||||
int main()
|
||||
/* This enumeration fits entirely in a signed int, but is unsigned anyway. */
|
||||
enum mm2
|
||||
{
|
||||
enum machine_mode mode = DImode;
|
||||
VOID2, SI2, DI2, MAX2
|
||||
};
|
||||
|
||||
return (mode == Pmode); /* { dg-bogus "warning:" "comparison between signed and unsigned" } */
|
||||
int f(enum mm1 x)
|
||||
{
|
||||
return x == (tf?DI:SI); /* { dg-bogus "signed and unsigned" "case 1" } */
|
||||
}
|
||||
|
||||
int g(enum mm1 x)
|
||||
{
|
||||
return x == (tf?DI:-1); /* { dg-bogus "signed and unsigned" "case 2" } */
|
||||
}
|
||||
|
||||
int h(enum mm2 x)
|
||||
{
|
||||
return x == (tf?DI2:SI2); /* { dg-bogus "signed and unsigned" "case 3" } */
|
||||
}
|
||||
|
||||
int i(enum mm2 x)
|
||||
{
|
||||
return x == (tf?DI2:-1); /* { dg-warning "signed and unsigned" "case 4" } */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user