OSDN Git Service

2007-09-07 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index f4b5560..a922081 100644 (file)
@@ -7,7 +7,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* This file is part of the C front end.
@@ -75,12 +74,12 @@ static int missing_braces_mentioned;
 static int require_constant_value;
 static int require_constant_elements;
 
-static bool null_pointer_constant_p (tree);
+static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (tree, tree);
+static int tagged_types_tu_compatible_p (const_tree, const_tree);
 static int comp_target_types (tree, tree);
-static int function_types_compatible_p (tree, tree);
-static int type_lists_compatible_p (tree, tree);
+static int function_types_compatible_p (const_tree, const_tree);
+static int type_lists_compatible_p (const_tree, const_tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree lookup_field (tree, tree);
 static int convert_arguments (int, tree *, tree, tree, tree, tree);
@@ -103,15 +102,15 @@ static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
 static void readonly_error (tree, enum lvalue_use);
-static int lvalue_or_else (tree, enum lvalue_use);
-static int lvalue_p (tree);
+static int lvalue_or_else (const_tree, enum lvalue_use);
+static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (tree, tree);
+static int comptypes_internal (const_tree, const_tree);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
 static bool
-null_pointer_constant_p (tree expr)
+null_pointer_constant_p (const_tree expr)
 {
   /* This should really operate on c_expr structures, but they aren't
      yet available everywhere required.  */
@@ -128,8 +127,8 @@ null_pointer_constant_p (tree expr)
 
 struct tagged_tu_seen_cache {
   const struct tagged_tu_seen_cache * next;
-  tree t1;
-  tree t2;
+  const_tree t1;
+  const_tree t2;
   /* The return value of tagged_types_tu_compatible_p if we had seen
      these two types already.  */
   int val;
@@ -162,7 +161,7 @@ require_complete_type (tree value)
    and TYPE is the type that was invalid.  */
 
 void
-c_incomplete_type_error (tree value, tree type)
+c_incomplete_type_error (const_tree value, const_tree type)
 {
   const char *type_code_string;
 
@@ -257,7 +256,7 @@ qualify_type (tree type, tree like)
 /* Return true iff the given tree T is a variable length array.  */
 
 bool
-c_vla_type_p (tree t)
+c_vla_type_p (const_tree t)
 {
   if (TREE_CODE (t) == ARRAY_TYPE
       && C_TYPE_VARIABLE_SIZE (t))
@@ -605,9 +604,11 @@ c_common_type (tree t1, tree t2)
   code2 = TREE_CODE (t2);
 
   gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
-             || code1 == REAL_TYPE || code1 == INTEGER_TYPE);
+             || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
+             || code1 == INTEGER_TYPE);
   gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
-             || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
+             || code2 == FIXED_POINT_TYPE || code2 == REAL_TYPE
+             || code2 == INTEGER_TYPE);
 
   /* When one operand is a decimal float type, the other operand cannot be
      a generic float type or a complex type.  We also disallow vector types
@@ -682,6 +683,91 @@ c_common_type (tree t1, tree t2)
        return dfloat32_type_node;
     }
 
+  /* Deal with fixed-point types.  */
+  if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
+    {
+      unsigned int unsignedp = 0, satp = 0;
+      enum machine_mode m1, m2;
+      unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
+
+      m1 = TYPE_MODE (t1);
+      m2 = TYPE_MODE (t2);
+
+      /* If one input type is saturating, the result type is saturating.  */
+      if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
+       satp = 1;
+
+      /* If both fixed-point types are unsigned, the result type is unsigned.
+        When mixing fixed-point and integer types, follow the sign of the
+        fixed-point type.
+        Otherwise, the result type is signed.  */
+      if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2)
+          && code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE)
+         || (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t1))
+         || (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t2)))
+       unsignedp = 1;
+
+      /* The result type is signed.  */
+      if (unsignedp == 0)
+       {
+         /* If the input type is unsigned, we need to convert to the
+            signed type.  */
+         if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
+           {
+             unsigned char mclass = 0;
+             if (GET_MODE_CLASS (m1) == MODE_UFRACT)
+               mclass = MODE_FRACT;
+             else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
+           }
+         if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
+           {
+             unsigned char mclass = 0;
+             if (GET_MODE_CLASS (m2) == MODE_UFRACT)
+               mclass = MODE_FRACT;
+             else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
+           }
+       }
+
+      if (code1 == FIXED_POINT_TYPE)
+       {
+         fbit1 = GET_MODE_FBIT (m1);
+         ibit1 = GET_MODE_IBIT (m1);
+       }
+      else
+       {
+         fbit1 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1));
+       }
+
+      if (code2 == FIXED_POINT_TYPE)
+       {
+         fbit2 = GET_MODE_FBIT (m2);
+         ibit2 = GET_MODE_IBIT (m2);
+       }
+      else
+       {
+         fbit2 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2));
+       }
+
+      max_ibit = ibit1 >= ibit2 ?  ibit1 : ibit2;
+      max_fbit = fbit1 >= fbit2 ?  fbit1 : fbit2;
+      return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp,
+                                                satp);
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
@@ -783,10 +869,10 @@ comptypes (tree type1, tree type2)
    differs from comptypes, in that we don't free the seen types.  */
 
 static int
-comptypes_internal (tree type1, tree type2)
+comptypes_internal (const_tree type1, const_tree type2)
 {
-  tree t1 = type1;
-  tree t2 = type2;
+  const_tree t1 = type1;
+  const_tree t2 = type2;
   int attrval, val;
 
   /* Suppress errors caused by previously reported errors.  */
@@ -959,7 +1045,7 @@ comp_target_types (tree ttl, tree ttr)
    being parsed, so if two trees have context chains ending in null,
    they're in the same translation unit.  */
 int
-same_translation_unit_p (tree t1, tree t2)
+same_translation_unit_p (const_tree t1, const_tree t2)
 {
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t1)))
@@ -991,7 +1077,7 @@ same_translation_unit_p (tree t1, tree t2)
 /* Allocate the seen two types, assuming that they are compatible. */
 
 static struct tagged_tu_seen_cache *
-alloc_tagged_tu_seen_cache (tree t1, tree t2)
+alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2)
 {
   struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
   tu->next = tagged_tu_seen_base;
@@ -1024,10 +1110,10 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
   const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
   while (tu != tu_til)
     {
-      const struct tagged_tu_seen_cache *tu1
-       = (const struct tagged_tu_seen_cache*)tu;
+      const struct tagged_tu_seen_cache *const tu1
+       = (const struct tagged_tu_seen_cache *) tu;
       tu = tu1->next;
-      free ((void *)tu1);
+      free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
     }
   tagged_tu_seen_base = tu_til;
 }
@@ -1039,7 +1125,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
    rules.  */
 
 static int
-tagged_types_tu_compatible_p (tree t1, tree t2)
+tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1253,7 +1339,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
    Otherwise, the argument types must match.  */
 
 static int
-function_types_compatible_p (tree f1, tree f2)
+function_types_compatible_p (const_tree f1, const_tree f2)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1316,7 +1402,7 @@ function_types_compatible_p (tree f1, tree f2)
    or 2 for compatible with warning.  */
 
 static int
-type_lists_compatible_p (tree args1, tree args2)
+type_lists_compatible_p (const_tree args1, const_tree args2)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1417,7 +1503,7 @@ type_lists_compatible_p (tree args1, tree args2)
 /* Compute the size to increment a pointer by.  */
 
 static tree
-c_size_in_bytes (tree type)
+c_size_in_bytes (const_tree type)
 {
   enum tree_code code = TREE_CODE (type);
 
@@ -2809,7 +2895,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
         is enough to prevent anybody from looking inside for
         associativity, but won't generate any code.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE
+           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
            || typecode == VECTOR_TYPE))
        {
          error ("wrong type argument to unary plus");
@@ -2822,7 +2908,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
     case NEGATE_EXPR:
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE
+           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
            || typecode == VECTOR_TYPE))
        {
          error ("wrong type argument to unary minus");
@@ -2833,7 +2919,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case BIT_NOT_EXPR:
-      if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE)
+      /* ~ works on integer types and non float vectors. */
+      if (typecode == INTEGER_TYPE
+         || (typecode == VECTOR_TYPE
+             && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
        {
          if (!noconvert)
            arg = default_conversion (arg);
@@ -2876,7 +2965,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case TRUTH_NOT_EXPR:
-      if (typecode != INTEGER_TYPE
+      if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
          && typecode != REAL_TYPE && typecode != POINTER_TYPE
          && typecode != COMPLEX_TYPE)
        {
@@ -2929,7 +3018,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
       /* Report invalid types.  */
 
-      if (typecode != POINTER_TYPE
+      if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
          if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
@@ -2973,6 +3062,25 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
            inc = c_size_in_bytes (TREE_TYPE (result_type));
            inc = fold_convert (sizetype, inc);
          }
+       else if (FRACT_MODE_P (TYPE_MODE (result_type)))
+         {
+           /* For signed fract types, we invert ++ to -- or
+              -- to ++, and change inc from 1 to -1, because
+              it is not possible to represent 1 in signed fract constants.
+              For unsigned fract types, the result always overflows and
+              we get an undefined (original) or the maximum value.  */
+           if (code == PREINCREMENT_EXPR)
+             code = PREDECREMENT_EXPR;
+           else if (code == PREDECREMENT_EXPR)
+             code = PREINCREMENT_EXPR;
+           else if (code == POSTINCREMENT_EXPR)
+             code = POSTDECREMENT_EXPR;
+           else /* code == POSTDECREMENT_EXPR  */
+             code = POSTINCREMENT_EXPR;
+
+           inc = integer_minus_one_node;
+           inc = convert (argtype, inc);
+         }
        else
          {
            inc = integer_one_node;
@@ -3090,9 +3198,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
    Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
 static int
-lvalue_p (tree ref)
+lvalue_p (const_tree ref)
 {
-  enum tree_code code = TREE_CODE (ref);
+  const enum tree_code code = TREE_CODE (ref);
 
   switch (code)
     {
@@ -3153,10 +3261,11 @@ readonly_error (tree arg, enum lvalue_use use)
                         G_("read-only variable %qD used as %<asm%> output")),
           arg);
   else
-    error (READONLY_MSG (G_("assignment of read-only location"),
-                        G_("increment of read-only location"),
-                        G_("decrement of read-only location"),
-                        G_("read-only location used as %<asm%> output")));
+    error (READONLY_MSG (G_("assignment of read-only location %qE"),
+                        G_("increment of read-only location %qE"),
+                        G_("decrement of read-only location %qE"),
+                        G_("read-only location %qE used as %<asm%> output")),
+          arg);
 }
 
 
@@ -3165,7 +3274,7 @@ readonly_error (tree arg, enum lvalue_use use)
    how the lvalue is being used and so selects the error message.  */
 
 static int
-lvalue_or_else (tree ref, enum lvalue_use use)
+lvalue_or_else (const_tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
@@ -3557,12 +3666,12 @@ build_c_cast (tree type, tree expr)
                 && TREE_CODE (in_otype) == POINTER_TYPE);
 
          if (added)
-           warning (0, "cast adds new qualifiers to function type");
+           warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
 
          if (discarded)
            /* There are qualifiers present in IN_OTYPE that are not
               present in IN_TYPE.  */
-           warning (0, "cast discards qualifiers from pointer target type");
+           warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
        }
 
       /* Warn about possible alignment problems.  */
@@ -3921,9 +4030,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
+           || codel == FIXED_POINT_TYPE
            || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
            || codel == BOOLEAN_TYPE)
           && (coder == INTEGER_TYPE || coder == REAL_TYPE
+              || coder == FIXED_POINT_TYPE
               || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
               || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
@@ -4036,6 +4147,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
          if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
            pedwarn ("ISO C prohibits argument conversion to union type");
 
+         rhs = fold_convert (TREE_TYPE (memb), rhs);
          return build_constructor_single (type, memb, rhs);
        }
     }
@@ -4742,9 +4854,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
   /* Handle scalar types, including conversions.  */
 
-  if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
-      || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
-      || code == VECTOR_TYPE)
+  if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
+      || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
+      || code == COMPLEX_TYPE || code == VECTOR_TYPE)
     {
       if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
          && (TREE_CODE (init) == STRING_CST
@@ -7858,8 +7970,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       warn_for_div_by_zero (op1);
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE
              || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
          enum tree_code tcode0 = code0, tcode1 = code1;
@@ -7869,7 +7983,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
            tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
 
-         if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
+         if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
+             || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
            resultcode = RDIV_EXPR;
          else
            /* Although it would be tempting to shorten always here, that
@@ -7889,7 +8004,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case BIT_XOR_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        shorten = -1;
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+      /* Allow vector types which are not floating point types.   */
+      else if (code0 == VECTOR_TYPE
+              && code1 == VECTOR_TYPE
+              && !VECTOR_FLOAT_TYPE_P (type0)
+              && !VECTOR_FLOAT_TYPE_P (type1))
        common = 1;
       break;
 
@@ -7916,9 +8035,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
       if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
-          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+          || code0 == FIXED_POINT_TYPE)
          && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
-             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+             || code1 == FIXED_POINT_TYPE))
        {
          /* Result of these operations is always an int,
             but that does not mean the operands should be
@@ -7935,7 +8056,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
@@ -7963,7 +8085,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
 
     case LSHIFT_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
@@ -7994,9 +8117,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
         but don't convert the args to int!  */
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == COMPLEX_TYPE)
+          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == COMPLEX_TYPE))
+             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -8064,8 +8187,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case LT_EXPR:
     case GT_EXPR:
       build_type = integer_type_node;
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -8126,10 +8251,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     }
 
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
-       || code0 == VECTOR_TYPE)
+       || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE)
       &&
       (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
-       || code1 == VECTOR_TYPE))
+       || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
     {
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
@@ -8226,8 +8351,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                       < TYPE_PRECISION (result_type))
                   && (type
                       = c_common_signed_or_unsigned_type (unsigned1,
-                                                          TREE_TYPE (arg1)),
-                      int_fits_type_p (arg0, type)))
+                                                          TREE_TYPE (arg1)))
+                  && !POINTER_TYPE_P (type)
+                  && int_fits_type_p (arg0, type))
            result_type = type;
          else if (TREE_CODE (arg1) == INTEGER_CST
                   && (unsigned0 || !uns)
@@ -8235,8 +8361,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                       < TYPE_PRECISION (result_type))
                   && (type
                       = c_common_signed_or_unsigned_type (unsigned0,
-                                                          TREE_TYPE (arg0)),
-                      int_fits_type_p (arg1, type)))
+                                                          TREE_TYPE (arg0)))
+                  && !POINTER_TYPE_P (type)
+                  && int_fits_type_p (arg1, type))
            result_type = type;
        }