diff options
author | chaoyingfu <chaoyingfu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-08-20 22:26:47 +0000 |
---|---|---|
committer | chaoyingfu <chaoyingfu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-08-20 22:26:47 +0000 |
commit | 9421ebb9b381242a1fa9d4b435babe0910a58118 (patch) | |
tree | 64870172714a26b5105facd128201e6fef2f87b8 /gcc/c-common.c | |
parent | a37e11205961890d4a52cca73615df79976171b2 (diff) | |
download | gcc-9421ebb9b381242a1fa9d4b435babe0910a58118.tar.gz |
* c-common.h (enum rid): Add new enumeration values of RID_SAT,
RID_FRACT, and RID_ACCUM. RID_SAT needs to be inserted before
RID_ONEWAY, so that it can be checked in declspecs_add_type.
(c_common_fixed_point_type_for_size): Declare.
* c-parser.c (reswords): Add _Fract, _Accum, and _Sat.
(c_token_starts_typename): Handle RID_FRACT, RID_ACCUM, and RID_SAT.
(c_token_starts_declspecs): Likewise.
(c_parser_declspecs): Likewise.
(c_parser_attributes): Likewise.
* c-tree.h (enum c_typespec_keyword): Add cts_fract and cts_accum.
(c_declspecs): Add saturating_p.
* c-decl.c (build_null_declspecs): Initialize saturating_p.
(declspecs_add_type): Avoid using complex with _Fract, _Accum, or _Sat.
Handle RID_SAT.
Avoid using void, bool, char, int, float, double, _Decimal32,
_Decimal64, _Decimal128, and complex with _Sat.
Handle RID_FRACT and RID_ACCUM.
Make sure _Sat is used with _Fract or _Accum.
(finish_declspecs): Handle cts_fract and cts_accum.
* c-common.c (fixed-value.h): New include.
(constant_expression_warning): Handle FIXED_CST.
(overflow_warning): Likewise.
(warnings_for_convert_and_check): Likewise.
(c_common_fixed_point_type_for_size): New.
(c_common_type_for_mode): Handle fixed-point modes to
return various saturating/non-saturating, signed/unsigned types.
(c_common_signed_or_unsigned_type): Support fixed-point types.
(shorten_compare): Check fixed-point zero.
Handle FIXED_POINT_TYPE.
(c_common_truthvalue_conversion): Handle FIXED_CST.
Handle FIXED_POINT_TYPE.
(c_common_nodes_and_builtins): Record builtin types for fixed-point
types.
(handle_mode_attribute): Handle fixed-point modes. Need to check
if the signness of base type and fixed-point modes are consistent.
(handle_vector_size_attribute): Handle fixed-point modes.
(same_scalar_type_ignoring_signedness): Handle FIXED_POINT_TYPE.
(warn_for_div_by_zero): Check fixed-point zero.
* c-typeck.c (c_common_type): Check FIXED_POINT_TYPE. Build
a common fixed-point type based on fbit, ibit, sign, and saturation.
(build_unary_op): Allow FIXED_POINT_TYPE for CONVERT_EXPR,
NEGATE_EXPR, TRUTH_NOT_EXPR, PREINCREMENT_EXPR, POSTINCREMENT_EXPR,
PREDECREMENT_EXPR, and POSTDECREMENT_EXPR.
(convert_for_assignment): Support FIXED_POINT_TYPE.
(digest_init): Handle FIXED_POINT_TYPE.
(build_binary_op): Support FIXED_POINT_TYPE in *_DIV_EXPR,
TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR, TRUTH_AND_EXPR, TRUTH_OR_EXPR,
TRUTH_XOR_EXPR, RSHIFT_EXPR, LSHIFT_EXPR, EQ_EXPR, NE_EXPR, LE_EXPR,
GE_EXPR, LT_EXPR, GT_EXPR.
* target-def.h (TARGET_FIXED_POINT_SUPPORTED_P): New.
(TARGET_INITIALIZER): Add TARGET_FIXED_POINT_SUPPORTED_P.
* target.h (gcc_target): Add fixed_point_supported_p.
* targhooks.c (default_scalar_mode_supported_p): Handle MODE_FRACT,
MODE_UFRACT, MODE_ACCUM, and MODE_UACCUM.
(default_fixed_point_supported_p): Define.
* targhooks.h (default_fixed_point_supported_p): Declare.
* doc/tm.texi (TARGET_FIXED_POINT_SUPPORTED_P): Add.
* doc/install.texi (Configuration): Add --enable-fixed-point.
* configure.ac (--enable-fixed-point): New to enable fixed-point
arithmetic extension to C. For mips targets, we enable it by default.
* configure, config.in: Regenerate.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127652 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 296 |
1 files changed, 286 insertions, 10 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index d2ff7b88279..6c088302e46 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "real.h" #include "cgraph.h" #include "target-def.h" +#include "fixed-value.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -929,6 +930,7 @@ void constant_expression_warning (tree value) { if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST + || TREE_CODE (value) == FIXED_CST || TREE_CODE (value) == VECTOR_CST || TREE_CODE (value) == COMPLEX_CST) && TREE_OVERFLOW (value) @@ -963,6 +965,10 @@ overflow_warning (tree value) warning (OPT_Woverflow, "floating point overflow in expression"); break; + case FIXED_CST: + warning (OPT_Woverflow, "fixed-point overflow in expression"); + break; + case VECTOR_CST: warning (OPT_Woverflow, "vector overflow in expression"); break; @@ -1360,7 +1366,8 @@ warnings_for_convert_and_check (tree type, tree expr, tree result) else conversion_warning (type, expr); } - else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result)) + else if ((TREE_CODE (result) == INTEGER_CST + || TREE_CODE (result) == FIXED_CST) && TREE_OVERFLOW (result)) warning (OPT_Woverflow, "overflow in implicit constant conversion"); else @@ -1928,13 +1935,44 @@ c_common_type_for_size (unsigned int bits, int unsignedp) return 0; } +/* Return a fixed-point type that has at least IBIT ibits and FBIT fbits + that is unsigned if UNSIGNEDP is nonzero, otherwise signed; + and saturating if SATP is nonzero, otherwise not saturating. */ + +tree +c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit, + int unsignedp, int satp) +{ + enum machine_mode mode; + if (ibit == 0) + mode = unsignedp ? UQQmode : QQmode; + else + mode = unsignedp ? UHAmode : HAmode; + + for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) + if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit) + break; + + if (mode == VOIDmode || !targetm.scalar_mode_supported_p (mode)) + { + sorry ("GCC cannot support operators with integer types and " + "fixed-point types that have too many integral and " + "fractional bits together"); + return 0; + } + + return c_common_type_for_mode (mode, satp); +} + /* Used for communication between c_common_type_for_mode and c_register_builtin_type. */ static GTY(()) tree registered_builtin_types; /* Return a data type that has machine mode MODE. If the mode is an integer, - then UNSIGNEDP selects between signed and unsigned types. */ + then UNSIGNEDP selects between signed and unsigned types. + If the mode is a fixed-point mode, + then UNSIGNEDP selects between saturating and nonsaturating types. */ tree c_common_type_for_mode (enum machine_mode mode, int unsignedp) @@ -2034,6 +2072,95 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) if (mode == TYPE_MODE (dfloat128_type_node)) return dfloat128_type_node; + if (ALL_SCALAR_FIXED_POINT_MODE_P (mode)) + { + if (mode == TYPE_MODE (short_fract_type_node)) + return unsignedp ? sat_short_fract_type_node : short_fract_type_node; + if (mode == TYPE_MODE (fract_type_node)) + return unsignedp ? sat_fract_type_node : fract_type_node; + if (mode == TYPE_MODE (long_fract_type_node)) + return unsignedp ? sat_long_fract_type_node : long_fract_type_node; + if (mode == TYPE_MODE (long_long_fract_type_node)) + return unsignedp ? sat_long_long_fract_type_node + : long_long_fract_type_node; + + if (mode == TYPE_MODE (unsigned_short_fract_type_node)) + return unsignedp ? sat_unsigned_short_fract_type_node + : unsigned_short_fract_type_node; + if (mode == TYPE_MODE (unsigned_fract_type_node)) + return unsignedp ? sat_unsigned_fract_type_node + : unsigned_fract_type_node; + if (mode == TYPE_MODE (unsigned_long_fract_type_node)) + return unsignedp ? sat_unsigned_long_fract_type_node + : unsigned_long_fract_type_node; + if (mode == TYPE_MODE (unsigned_long_long_fract_type_node)) + return unsignedp ? sat_unsigned_long_long_fract_type_node + : unsigned_long_long_fract_type_node; + + if (mode == TYPE_MODE (short_accum_type_node)) + return unsignedp ? sat_short_accum_type_node : short_accum_type_node; + if (mode == TYPE_MODE (accum_type_node)) + return unsignedp ? sat_accum_type_node : accum_type_node; + if (mode == TYPE_MODE (long_accum_type_node)) + return unsignedp ? sat_long_accum_type_node : long_accum_type_node; + if (mode == TYPE_MODE (long_long_accum_type_node)) + return unsignedp ? sat_long_long_accum_type_node + : long_long_accum_type_node; + + if (mode == TYPE_MODE (unsigned_short_accum_type_node)) + return unsignedp ? sat_unsigned_short_accum_type_node + : unsigned_short_accum_type_node; + if (mode == TYPE_MODE (unsigned_accum_type_node)) + return unsignedp ? sat_unsigned_accum_type_node + : unsigned_accum_type_node; + if (mode == TYPE_MODE (unsigned_long_accum_type_node)) + return unsignedp ? sat_unsigned_long_accum_type_node + : unsigned_long_accum_type_node; + if (mode == TYPE_MODE (unsigned_long_long_accum_type_node)) + return unsignedp ? sat_unsigned_long_long_accum_type_node + : unsigned_long_long_accum_type_node; + + if (mode == QQmode) + return unsignedp ? sat_qq_type_node : qq_type_node; + if (mode == HQmode) + return unsignedp ? sat_hq_type_node : hq_type_node; + if (mode == SQmode) + return unsignedp ? sat_sq_type_node : sq_type_node; + if (mode == DQmode) + return unsignedp ? sat_dq_type_node : dq_type_node; + if (mode == TQmode) + return unsignedp ? sat_tq_type_node : tq_type_node; + + if (mode == UQQmode) + return unsignedp ? sat_uqq_type_node : uqq_type_node; + if (mode == UHQmode) + return unsignedp ? sat_uhq_type_node : uhq_type_node; + if (mode == USQmode) + return unsignedp ? sat_usq_type_node : usq_type_node; + if (mode == UDQmode) + return unsignedp ? sat_udq_type_node : udq_type_node; + if (mode == UTQmode) + return unsignedp ? sat_utq_type_node : utq_type_node; + + if (mode == HAmode) + return unsignedp ? sat_ha_type_node : ha_type_node; + if (mode == SAmode) + return unsignedp ? sat_sa_type_node : sa_type_node; + if (mode == DAmode) + return unsignedp ? sat_da_type_node : da_type_node; + if (mode == TAmode) + return unsignedp ? sat_ta_type_node : ta_type_node; + + if (mode == UHAmode) + return unsignedp ? sat_uha_type_node : uha_type_node; + if (mode == USAmode) + return unsignedp ? sat_usa_type_node : usa_type_node; + if (mode == UDAmode) + return unsignedp ? sat_uda_type_node : uda_type_node; + if (mode == UTAmode) + return unsignedp ? sat_uta_type_node : uta_type_node; + } + for (t = registered_builtin_types; t; t = TREE_CHAIN (t)) if (TYPE_MODE (TREE_VALUE (t)) == mode) return TREE_VALUE (t); @@ -2095,6 +2222,54 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type) if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node) return unsignedp ? unsigned_intQI_type_node : intQI_type_node; +#define C_COMMON_FIXED_TYPES(SAT,NAME) \ + if (type1 == SAT ## short_ ## NAME ## _type_node \ + || type1 == SAT ## unsigned_short_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_short_ ## NAME ## _type_node \ + : SAT ## short_ ## NAME ## _type_node; \ + if (type1 == SAT ## NAME ## _type_node \ + || type1 == SAT ## unsigned_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_ ## NAME ## _type_node \ + : SAT ## NAME ## _type_node; \ + if (type1 == SAT ## long_ ## NAME ## _type_node \ + || type1 == SAT ## unsigned_long_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_long_ ## NAME ## _type_node \ + : SAT ## long_ ## NAME ## _type_node; \ + if (type1 == SAT ## long_long_ ## NAME ## _type_node \ + || type1 == SAT ## unsigned_long_long_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_long_long_ ## NAME ## _type_node \ + : SAT ## long_long_ ## NAME ## _type_node; + +#define C_COMMON_FIXED_MODE_TYPES(SAT,NAME) \ + if (type1 == SAT ## NAME ## _type_node \ + || type1 == SAT ## u ## NAME ## _type_node) \ + return unsignedp ? SAT ## u ## NAME ## _type_node \ + : SAT ## NAME ## _type_node; + + C_COMMON_FIXED_TYPES (, fract); + C_COMMON_FIXED_TYPES (sat_, fract); + C_COMMON_FIXED_TYPES (, accum); + C_COMMON_FIXED_TYPES (sat_, accum); + + C_COMMON_FIXED_MODE_TYPES (, qq); + C_COMMON_FIXED_MODE_TYPES (, hq); + C_COMMON_FIXED_MODE_TYPES (, sq); + C_COMMON_FIXED_MODE_TYPES (, dq); + C_COMMON_FIXED_MODE_TYPES (, tq); + C_COMMON_FIXED_MODE_TYPES (sat_, qq); + C_COMMON_FIXED_MODE_TYPES (sat_, hq); + C_COMMON_FIXED_MODE_TYPES (sat_, sq); + C_COMMON_FIXED_MODE_TYPES (sat_, dq); + C_COMMON_FIXED_MODE_TYPES (sat_, tq); + C_COMMON_FIXED_MODE_TYPES (, ha); + C_COMMON_FIXED_MODE_TYPES (, sa); + C_COMMON_FIXED_MODE_TYPES (, da); + C_COMMON_FIXED_MODE_TYPES (, ta); + C_COMMON_FIXED_MODE_TYPES (sat_, ha); + C_COMMON_FIXED_MODE_TYPES (sat_, sa); + C_COMMON_FIXED_MODE_TYPES (sat_, da); + C_COMMON_FIXED_MODE_TYPES (sat_, ta); + /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not the precision; they have precision set to match their range, but may use a wider mode to match an ABI. If we change modes, we may @@ -2323,7 +2498,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, the second arg is 0. */ if (TREE_CONSTANT (primop0) - && !integer_zerop (primop1) && !real_zerop (primop1)) + && !integer_zerop (primop1) && !real_zerop (primop1) + && !fixed_zerop (primop1)) { tree tem = primop0; int temi = unsignedp0; @@ -2378,6 +2554,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, and see if that preserves the constant's value. */ if (!real1 && !real2 + && TREE_CODE (TREE_TYPE (primop0)) != FIXED_POINT_TYPE && TREE_CODE (primop1) == INTEGER_CST && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)) { @@ -2783,6 +2960,12 @@ c_common_truthvalue_conversion (tree expr) ? truthvalue_true_node : truthvalue_false_node; + case FIXED_CST: + return fixed_compare (NE_EXPR, &TREE_FIXED_CST (expr), + &FCONST0 (TYPE_MODE (TREE_TYPE (expr)))) + ? truthvalue_true_node + : truthvalue_false_node; + case FUNCTION_DECL: expr = build_unary_op (ADDR_EXPR, expr, 0); /* Fall through. */ @@ -2883,6 +3066,14 @@ c_common_truthvalue_conversion (tree expr) 0)); } + if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE) + { + tree fixed_zero_node = build_fixed (TREE_TYPE (expr), + FCONST0 (TYPE_MODE + (TREE_TYPE (expr)))); + return build_binary_op (NE_EXPR, expr, fixed_zero_node, 1); + } + return build_binary_op (NE_EXPR, expr, integer_zero_node, 1); } @@ -3594,6 +3785,67 @@ c_common_nodes_and_builtins (void) record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node); } + if (targetm.fixed_point_supported_p ()) + { + record_builtin_type (RID_MAX, "short _Fract", short_fract_type_node); + record_builtin_type (RID_FRACT, NULL, fract_type_node); + record_builtin_type (RID_MAX, "long _Fract", long_fract_type_node); + record_builtin_type (RID_MAX, "long long _Fract", + long_long_fract_type_node); + record_builtin_type (RID_MAX, "unsigned short _Fract", + unsigned_short_fract_type_node); + record_builtin_type (RID_MAX, "unsigned _Fract", + unsigned_fract_type_node); + record_builtin_type (RID_MAX, "unsigned long _Fract", + unsigned_long_fract_type_node); + record_builtin_type (RID_MAX, "unsigned long long _Fract", + unsigned_long_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat short _Fract", + sat_short_fract_type_node); + record_builtin_type (RID_MAX, "_Sat _Fract", sat_fract_type_node); + record_builtin_type (RID_MAX, "_Sat long _Fract", + sat_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat long long _Fract", + sat_long_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned short _Fract", + sat_unsigned_short_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned _Fract", + sat_unsigned_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long _Fract", + sat_unsigned_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long long _Fract", + sat_unsigned_long_long_fract_type_node); + record_builtin_type (RID_MAX, "short _Accum", short_accum_type_node); + record_builtin_type (RID_ACCUM, NULL, accum_type_node); + record_builtin_type (RID_MAX, "long _Accum", long_accum_type_node); + record_builtin_type (RID_MAX, "long long _Accum", + long_long_accum_type_node); + record_builtin_type (RID_MAX, "unsigned short _Accum", + unsigned_short_accum_type_node); + record_builtin_type (RID_MAX, "unsigned _Accum", + unsigned_accum_type_node); + record_builtin_type (RID_MAX, "unsigned long _Accum", + unsigned_long_accum_type_node); + record_builtin_type (RID_MAX, "unsigned long long _Accum", + unsigned_long_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat short _Accum", + sat_short_accum_type_node); + record_builtin_type (RID_MAX, "_Sat _Accum", sat_accum_type_node); + record_builtin_type (RID_MAX, "_Sat long _Accum", + sat_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat long long _Accum", + sat_long_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned short _Accum", + sat_unsigned_short_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned _Accum", + sat_unsigned_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long _Accum", + sat_unsigned_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long long _Accum", + sat_unsigned_long_long_accum_type_node); + + } + lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), complex_integer_type_node)); @@ -5013,6 +5265,10 @@ handle_mode_attribute (tree *node, tree name, tree args, case MODE_PARTIAL_INT: case MODE_FLOAT: case MODE_DECIMAL_FLOAT: + case MODE_FRACT: + case MODE_UFRACT: + case MODE_ACCUM: + case MODE_UACCUM: valid_mode = targetm.scalar_mode_supported_p (mode); break; @@ -5023,6 +5279,10 @@ handle_mode_attribute (tree *node, tree name, tree args, case MODE_VECTOR_INT: case MODE_VECTOR_FLOAT: + case MODE_VECTOR_FRACT: + case MODE_VECTOR_UFRACT: + case MODE_VECTOR_ACCUM: + case MODE_VECTOR_UACCUM: warning (OPT_Wattributes, "specifying vector types with " "__attribute__ ((mode)) is deprecated"); warning (OPT_Wattributes, @@ -5056,7 +5316,20 @@ handle_mode_attribute (tree *node, tree name, tree args, typefm = fn (TREE_TYPE (type), mode, false); } else - typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type)); + { + /* For fixed-point modes, we need to test if the signness of type + and the machine mode are consistent. */ + if (ALL_FIXED_POINT_MODE_P (mode) + && TYPE_UNSIGNED (type) != UNSIGNED_FIXED_POINT_MODE_P (mode)) + { + error ("signness of type and machine mode %qs don't match", p); + return NULL_TREE; + } + /* For fixed-point modes, we need to pass saturating info. */ + typefm = lang_hooks.types.type_for_mode (mode, + ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type) + : TYPE_UNSIGNED (type)); + } if (typefm == NULL_TREE) { @@ -5805,7 +6078,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args, || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == VECTOR_TYPE || (!SCALAR_FLOAT_MODE_P (orig_mode) - && GET_MODE_CLASS (orig_mode) != MODE_INT) + && GET_MODE_CLASS (orig_mode) != MODE_INT + && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode)) || !host_integerp (TYPE_SIZE_UNIT (type), 1)) { error ("invalid vector type for attribute %qE", name); @@ -6938,8 +7212,9 @@ same_scalar_type_ignoring_signedness (tree t1, tree t2) { enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2); - gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE) - && (c2 == INTEGER_TYPE || c2 == REAL_TYPE)); + gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE) + && (c2 == INTEGER_TYPE || c2 == REAL_TYPE + || c2 == FIXED_POINT_TYPE)); /* Equality works here because c_common_signed_type uses TYPE_MAIN_VARIANT. */ @@ -7104,11 +7379,12 @@ struct gcc_targetcm targetcm = TARGETCM_INITIALIZER; void warn_for_div_by_zero (tree divisor) { - /* If DIVISOR is zero, and has integral type, issue a warning about - division by zero. Do not issue a warning if DIVISOR has a + /* If DIVISOR is zero, and has integral or fixed-point type, issue a warning + about division by zero. Do not issue a warning if DIVISOR has a floating-point type, since we consider 0.0/0.0 a valid way of generating a NaN. */ - if (skip_evaluation == 0 && integer_zerop (divisor)) + if (skip_evaluation == 0 + && (integer_zerop (divisor) || fixed_zerop (divisor))) warning (OPT_Wdiv_by_zero, "division by zero"); } |