OSDN Git Service

2007-08-26 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 8d20efd..30d3816 100644 (file)
@@ -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;
@@ -1043,9 +1049,9 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
         {
           /* warn_strict_aliasing >= 3.   This includes the default (3).  
              Only warn if the cast is dereferenced immediately.  */
-          HOST_WIDE_INT set1 =
+          alias_set_type set1 =
            get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
-          HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+          alias_set_type set2 = get_alias_set (TREE_TYPE (type));
 
           if (!alias_sets_conflict_p (set1, set2))
            {
@@ -1069,9 +1075,9 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
            not taken in the same statement.  This will likely produce many
            false positives, but could be useful to pinpoint problems that
            are not revealed at higher levels.  */
-        HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (otype));
-        HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
-        if (!COMPLETE_TYPE_P(type)
+        alias_set_type set1 = get_alias_set (TREE_TYPE (otype));
+        alias_set_type set2 = get_alias_set (TREE_TYPE (type));
+        if (!COMPLETE_TYPE_P (type)
             || !alias_sets_must_conflict_p (set1, set2))
          {
             warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
@@ -1166,7 +1172,7 @@ check_main_parameter_types (tree decl)
    in effect, emit a note telling the user about that option if such
    a note has not previously been emitted.  */
 bool
-vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note)
+vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
 {
   static bool emitted_lax_note = false;
   bool convertible_lax;
@@ -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))
     {
@@ -2719,7 +2896,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
    NULL.  */
 
 bool
-decl_with_nonnull_addr_p (tree expr)
+decl_with_nonnull_addr_p (const_tree expr)
 {
   return (DECL_P (expr)
          && (TREE_CODE (expr) == PARM_DECL
@@ -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);
 }
 \f
@@ -3048,7 +3239,7 @@ static GTY((param_is (union tree_node))) htab_t type_hash_table;
 /* Return the typed-based alias set for T, which may be an expression
    or a type.  Return -1 if we don't do anything special.  */
 
-HOST_WIDE_INT
+alias_set_type
 c_common_get_alias_set (tree t)
 {
   tree u;
@@ -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));
@@ -3845,7 +4097,7 @@ def_builtin_1 (enum built_in_function fncode,
    integral promotions defined in ISO C99 6.3.1.1/2.  */
 
 bool
-c_promoting_integer_type_p (tree t)
+c_promoting_integer_type_p (const_tree t)
 {
   switch (TREE_CODE (t))
     {
@@ -3875,9 +4127,9 @@ c_promoting_integer_type_p (tree t)
    and none of their types is affected by default promotions.  */
 
 int
-self_promoting_args_p (tree parms)
+self_promoting_args_p (const_tree parms)
 {
-  tree t;
+  const_tree t;
   for (t = parms; t; t = TREE_CHAIN (t))
     {
       tree type = TREE_VALUE (t);
@@ -3912,6 +4164,15 @@ strip_array_types (tree type)
   return type;
 }
 
+const_tree
+const_strip_array_types (const_tree type)
+{
+  while (TREE_CODE (type) == ARRAY_TYPE)
+    type = TREE_TYPE (type);
+
+  return type;
+}
+
 /* Recursively remove any '*' or '&' operator from TYPE.  */
 tree
 strip_pointer_operator (tree t)
@@ -5004,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;
 
@@ -5014,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,
@@ -5047,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)
        {
@@ -5796,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);
@@ -6929,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.  */
@@ -7095,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");
 }