> The problem is that it won't be as simple as that. You'll have to extend > the C++ parser to accept those new RID_ values that it was previously never > expecting to see in those contexts, I would think (but haven't verified > against the source yet). The C++ parser is a hand-coded recursive-descent > parser, so I wouldn't expect it to be generically able to deal with > previously-unknown token types suddenly appearing in its input stream at > arbitrary points. > > cheers, > DaveK >
I went through the c++ parser and added support for fixed point there. Everything seems to be working, and I am able to use fixed-point numbers in c++. The c++ parser is kind of complex and it is possible I missed something. I would love to get feedback on this patch, and hopefully it can get committed to gcc. Sean
Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 157409) +++ gcc/builtins.c (working copy) @@ -1708,6 +1708,7 @@ case INTEGER_TYPE: return integer_type_class; case ENUMERAL_TYPE: return enumeral_type_class; case BOOLEAN_TYPE: return boolean_type_class; + case FIXED_POINT_TYPE: return fixed_point_type_class; case POINTER_TYPE: return pointer_type_class; case REFERENCE_TYPE: return reference_type_class; case OFFSET_TYPE: return offset_type_class; Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 157409) +++ gcc/fold-const.c (working copy) @@ -12303,6 +12303,11 @@ if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0) return NULL_TREE; + /* Since fixed point types cannot perform bitwise and, or, etc.. + don't try to convert to an expression with them. */ + if (TREE_CODE(type) == FIXED_POINT_TYPE) + return NULL_TREE; + /* Turn (a OP c1) OP c2 into a OP (c1+c2). */ if (TREE_CODE (op0) == code && host_integerp (arg1, false) && TREE_INT_CST_LOW (arg1) < TYPE_PRECISION (type) Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 157409) +++ gcc/cp/typeck.c (working copy) @@ -316,6 +316,91 @@ if (code2 == REAL_TYPE && code1 != REAL_TYPE) return build_type_attribute_variant (t2, attributes); + /* 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)) + { + enum mode_class mclass = (enum mode_class) 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)) + { + enum mode_class mclass = (enum mode_class) 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)) return build_type_attribute_variant (t1, attributes); @@ -3734,9 +3819,11 @@ case ROUND_DIV_EXPR: case EXACT_DIV_EXPR: if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) + || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE + || code0 == VECTOR_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) + || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE + || code1 == VECTOR_TYPE)) { enum tree_code tcode0 = code0, tcode1 = code1; @@ -3906,9 +3993,11 @@ build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == COMPLEX_TYPE || code0 == ENUMERAL_TYPE) + || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE + || code0 == ENUMERAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE)) + || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE + || code1 == ENUMERAL_TYPE)) short_compare = 1; else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1))) @@ -4109,8 +4198,10 @@ case MAX_EXPR: case MIN_EXPR: - 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)) shorten = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (type0, type1, op0, op1, @@ -4129,8 +4220,10 @@ } build_type = boolean_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) result_type = composite_pointer_type (type0, type1, op0, op1, @@ -4181,9 +4274,10 @@ } if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == ENUMERAL_TYPE) + || code0 == ENUMERAL_TYPE || code0 == FIXED_POINT_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE))) + || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE + || code1 == FIXED_POINT_TYPE))) arithmetic_types_p = 1; else { Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 157409) +++ gcc/cp/decl.c (working copy) @@ -7692,7 +7692,7 @@ namespace scope. */ tree in_namespace = NULL_TREE; cp_storage_class storage_class; - bool unsigned_p, signed_p, short_p, long_p, thread_p; + bool unsigned_p, signed_p, short_p, long_p, thread_p, saturating_p; bool type_was_error_mark_node = false; bool parameter_pack_p = declarator? declarator->parameter_pack_p : false; bool template_type_arg = false; @@ -7706,6 +7706,7 @@ long_p = declspecs->specs[(int)ds_long]; longlong = declspecs->specs[(int)ds_long] >= 2; thread_p = declspecs->specs[(int)ds_thread]; + saturating_p = declspecs->specs[(int)ds_sat]; if (decl_context == FUNCDEF) funcdef_flag = true, decl_context = NORMAL; @@ -8023,21 +8024,24 @@ /* Check all other uses of type modifiers. */ - if (unsigned_p || signed_p || long_p || short_p) + if (unsigned_p || signed_p || long_p || short_p || saturating_p) { int ok = 0; - if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE) + if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != FIXED_POINT_TYPE) error ("%<signed%> or %<unsigned%> invalid for %qs", name); else if (signed_p && unsigned_p) error ("%<signed%> and %<unsigned%> specified together for %qs", name); - else if (longlong && TREE_CODE (type) != INTEGER_TYPE) + else if (longlong && TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != FIXED_POINT_TYPE) error ("%<long long%> invalid for %qs", name); else if (long_p && TREE_CODE (type) == REAL_TYPE) error ("%<long%> invalid for %qs", name); else if (short_p && TREE_CODE (type) == REAL_TYPE) error ("%<short%> invalid for %qs", name); - else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE) + else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != FIXED_POINT_TYPE) error ("%<long%> or %<short%> invalid for %qs", name); else if ((long_p || short_p) && explicit_char) error ("%<long%> or %<short%> specified with char for %qs", name); @@ -8050,6 +8054,12 @@ else if (short_p || long_p) error ("%<short%> or %<long%> invalid for %qs", name); } + else if (saturating_p && TREE_CODE (type) != FIXED_POINT_TYPE) + { + error ("%<_Sat%> specified for non fixed-point type %qs", name); + if (!targetm.fixed_point_supported_p ()) + error ("fixed-point types not supported for this target"); + } else { ok = 1; @@ -8071,12 +8081,126 @@ long_p = false; short_p = false; longlong = 0; + saturating_p = false; } } + /* Determine correct fixed-point mode. */ + if (TREE_CODE (type) == FIXED_POINT_TYPE) + { + if (!targetm.fixed_point_supported_p ()) + error ("fixed-point types not supported for this target"); + + if (unsigned_p) + { + if (TYPE_MAIN_VARIANT (type) == fract_type_node) + { + if (saturating_p) + { + if (longlong) + type = sat_unsigned_long_long_fract_type_node; + else if (long_p) + type = sat_unsigned_long_fract_type_node; + else if (short_p) + type = sat_unsigned_short_fract_type_node; + else + type = sat_unsigned_fract_type_node; + } + else + { + if (longlong) + type = unsigned_long_long_fract_type_node; + else if (long_p) + type = unsigned_long_fract_type_node; + else if (short_p) + type = unsigned_short_fract_type_node; + else + type = unsigned_fract_type_node; + } + } + else + { + if (saturating_p) + { + if (longlong) + type = sat_unsigned_long_long_accum_type_node; + else if (long_p) + type = sat_unsigned_long_accum_type_node; + else if (short_p) + type = sat_unsigned_short_accum_type_node; + else + type = sat_unsigned_accum_type_node; + } + else + { + if (longlong) + type = unsigned_long_long_accum_type_node; + else if (long_p) + type = unsigned_long_accum_type_node; + else if (short_p) + type = unsigned_short_accum_type_node; + else + type = unsigned_accum_type_node; + } + } + } + else /* It is a signed fixed point type. */ + { + if (TYPE_MAIN_VARIANT (type) == fract_type_node) + { + if (saturating_p) + { + if (longlong) + type = sat_long_long_fract_type_node; + else if (long_p) + type = sat_long_fract_type_node; + else if (short_p) + type = sat_short_fract_type_node; + else + type = sat_fract_type_node; + } + else + { + if (longlong) + type = long_long_fract_type_node; + else if (long_p) + type = long_fract_type_node; + else if (short_p) + type = short_fract_type_node; + else + type = fract_type_node; + } + } + else + { + if (saturating_p) + { + if (longlong) + type = sat_long_long_accum_type_node; + else if (long_p) + type = sat_long_accum_type_node; + else if (short_p) + type = sat_short_accum_type_node; + else + type = sat_accum_type_node; + } + else + { + if (longlong) + type = long_long_accum_type_node; + else if (long_p) + type = long_accum_type_node; + else if (short_p) + type = short_accum_type_node; + else + type = accum_type_node; + } + } + } + } /* Decide whether an integer type is signed or not. Optionally treat bitfields as signed by default. */ - if (unsigned_p + else if (unsigned_p /* [class.bit] It is implementation-defined whether a plain (neither Index: gcc/cp/rtti.c =================================================================== --- gcc/cp/rtti.c (revision 157409) +++ gcc/cp/rtti.c (working copy) @@ -1034,6 +1034,7 @@ case INTEGER_TYPE: case BOOLEAN_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: case VOID_TYPE: return true; @@ -1452,6 +1453,22 @@ &long_long_integer_type_node, &long_long_unsigned_type_node, &float_type_node, &double_type_node, &long_double_type_node, &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node, + &short_fract_type_node, &unsigned_short_fract_type_node, + &fract_type_node, &unsigned_fract_type_node, + &long_fract_type_node, &unsigned_long_fract_type_node, + &long_long_fract_type_node, &unsigned_long_long_fract_type_node, + &sat_short_fract_type_node, &sat_unsigned_short_fract_type_node, + &sat_fract_type_node, &sat_unsigned_fract_type_node, + &sat_long_fract_type_node, &sat_unsigned_long_fract_type_node, + &sat_long_long_fract_type_node, &sat_unsigned_long_long_fract_type_node, + &short_accum_type_node, &unsigned_short_accum_type_node, + &accum_type_node, &unsigned_accum_type_node, + &long_accum_type_node, &unsigned_long_accum_type_node, + &long_long_accum_type_node, &unsigned_long_long_accum_type_node, + &sat_short_accum_type_node, &sat_unsigned_short_accum_type_node, + &sat_accum_type_node, &sat_unsigned_accum_type_node, + &sat_long_accum_type_node, &sat_unsigned_long_accum_type_node, + &sat_long_long_accum_type_node, &sat_unsigned_long_long_accum_type_node, 0 }; int ix; Index: gcc/cp/error.c =================================================================== --- gcc/cp/error.c (revision 157409) +++ gcc/cp/error.c (working copy) @@ -2169,6 +2169,7 @@ case INTEGER_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: + case FIXED_POINT_TYPE: pp_type_specifier_seq (cxx_pp, t); break; Index: gcc/cp/typeck2.c =================================================================== --- gcc/cp/typeck2.c (revision 157409) +++ gcc/cp/typeck2.c (working copy) @@ -755,7 +755,7 @@ if (DECL_P (init)) init = decl_constant_value (init); - if (TREE_CODE (type) == INTEGER_TYPE + if ((TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == FIXED_POINT_TYPE) && TREE_CODE (ftype) == REAL_TYPE) ok = false; else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype) Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 157409) +++ gcc/cp/pt.c (working copy) @@ -9942,6 +9942,7 @@ case REAL_TYPE: case COMPLEX_TYPE: case VECTOR_TYPE: + case FIXED_POINT_TYPE: case BOOLEAN_TYPE: case INTEGER_CST: case REAL_CST: @@ -14845,6 +14846,7 @@ case VECTOR_TYPE: case INTEGER_TYPE: case BOOLEAN_TYPE: + case FIXED_POINT_TYPE: case ENUMERAL_TYPE: case VOID_TYPE: if (TREE_CODE (arg) != TREE_CODE (parm)) Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 157409) +++ gcc/cp/parser.c (working copy) @@ -570,6 +570,9 @@ /* GNU extensions. */ case RID_ATTRIBUTE: case RID_TYPEOF: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: /* C++0x extensions. */ case RID_DECLTYPE: return true; @@ -3203,10 +3206,11 @@ case CPP_WCHAR: case CPP_NUMBER: token = cp_lexer_consume_token (parser->lexer); - if (TREE_CODE (token->u.value) == FIXED_CST) - { - error_at (token->location, - "fixed-point types not supported in C++"); + if (TREE_CODE (token->u.value) == FIXED_CST + && !targetm.fixed_point_supported_p ()) + { + error_at (token->location, + "fixed-point types not supported for this target"); return error_mark_node; } /* Floating-point literals are only allowed in an integral @@ -11950,6 +11954,17 @@ ++decl_specs->specs[(int) ds_unsigned]; type = unsigned_type_node; break; + case RID_FRACT: + type = fract_type_node; + break; + case RID_ACCUM: + type = accum_type_node; + break; + case RID_SAT: + if (decl_specs) + ++decl_specs->specs[(int) ds_sat]; + type = long_integer_type_node; /* must set accum or fract */ + break; case RID_FLOAT: type = float_type_node; break; @@ -12004,7 +12019,8 @@ && (token->keyword != RID_SIGNED && token->keyword != RID_UNSIGNED && token->keyword != RID_SHORT - && token->keyword != RID_LONG)) + && token->keyword != RID_LONG + && token->keyword != RID_SAT)) cp_parser_set_decl_spec_type (decl_specs, type, token->location, Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 157409) +++ gcc/cp/call.c (working copy) @@ -929,7 +929,8 @@ /* As an extension, allow conversion to complex type. */ else if (ARITHMETIC_TYPE_P (to)) { - if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE) + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE + || fcode == FIXED_POINT_TYPE) || SCOPED_ENUM_P (from)) return NULL; conv = build_conv (ck_std, to, conv); @@ -1848,7 +1849,8 @@ integral types plus floating types. */ return ((CP_INTEGRAL_TYPE_P (type) && same_type_p (type_promotes_to (type), type)) - || TREE_CODE (type) == REAL_TYPE); + || TREE_CODE (type) == REAL_TYPE + || TREE_CODE (type) == FIXED_POINT_TYPE); } /* Create any builtin operator overload candidates for the operator in Index: gcc/cp/cvt.c =================================================================== --- gcc/cp/cvt.c (revision 157409) +++ gcc/cp/cvt.c (working copy) @@ -662,7 +662,8 @@ /* enum = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype) - || TREE_CODE (intype) == REAL_TYPE) + || TREE_CODE (intype) == REAL_TYPE + || TREE_CODE (intype) == FIXED_POINT_TYPE) && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { @@ -736,6 +737,21 @@ else if (code == COMPLEX_TYPE) return fold_if_not_in_template (convert_to_complex (type, e)); } + if (code == FIXED_POINT_TYPE) + { + if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e))) + { + tree rval; + rval = build_type_conversion (type, e); + if (rval) + return rval; + else + if (flags & LOOKUP_COMPLAIN) + error ("%q#T used where a fixed point value was expected", + TREE_TYPE (e)); + } + return fold_if_not_in_template (convert_to_fixed (type, e)); + } /* New C++ semantics: since assignment is now based on memberwise copying, if the rhs type is derived from the @@ -1163,6 +1179,8 @@ return (desires & WANT_ENUM) ? expr : NULL_TREE; case REAL_TYPE: return (desires & WANT_FLOAT) ? expr : NULL_TREE; + case FIXED_POINT_TYPE: + return (desires & WANT_FIXED_POINT) ? expr : NULL_TREE; case POINTER_TYPE: return (desires & WANT_POINTER) ? expr : NULL_TREE; @@ -1225,6 +1243,8 @@ win = (desires & WANT_ENUM); break; case REAL_TYPE: win = (desires & WANT_FLOAT); break; + case FIXED_POINT_TYPE: + win = (desires & WANT_FIXED_POINT); break; case POINTER_TYPE: win = (desires & WANT_POINTER); break; Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 157409) +++ gcc/cp/mangle.c (working copy) @@ -1818,6 +1818,7 @@ if (TREE_CODE (type) != VOID_TYPE && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE + && TREE_CODE (type) != FIXED_POINT_TYPE && TREE_CODE (type) != BOOLEAN_TYPE) add_substitution (type); return; Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 157409) +++ gcc/cp/cp-tree.h (working copy) @@ -2985,13 +2985,14 @@ Integral and floating types are collectively called arithmetic types. - As a GNU extension, we also accept complex types. + As a GNU extension, we also accept complex and fixed-point types. Keep these checks in ascending code order. */ #define ARITHMETIC_TYPE_P(TYPE) \ (CP_INTEGRAL_TYPE_P (TYPE) \ || TREE_CODE (TYPE) == REAL_TYPE \ - || TREE_CODE (TYPE) == COMPLEX_TYPE) + || TREE_CODE (TYPE) == COMPLEX_TYPE \ + || TREE_CODE (TYPE) == FIXED_POINT_TYPE) /* [basic.types] @@ -4168,7 +4169,9 @@ #define WANT_POINTER 8 /* pointer types */ #define WANT_NULL 16 /* null pointer constant */ #define WANT_VECTOR_OR_COMPLEX 32 /* vector or complex types */ -#define WANT_ARITH (WANT_INT | WANT_FLOAT | WANT_VECTOR_OR_COMPLEX) +#define WANT_FIXED_POINT 64 /* fixed point types */ +#define WANT_ARITH (WANT_INT | WANT_FLOAT | \ + WANT_VECTOR_OR_COMPLEX | WANT_FIXED_POINT) /* Used with comptypes, and related functions, to guide type comparison. */ @@ -4343,6 +4346,7 @@ ds_constexpr, ds_complex, ds_thread, + ds_sat, ds_last } cp_decl_spec; Index: gcc/cse.c =================================================================== --- gcc/cse.c (revision 157409) +++ gcc/cse.c (working copy) @@ -3703,9 +3703,10 @@ && exact_log2 (- INTVAL (const_arg1)) >= 0))) break; - /* ??? Vector mode shifts by scalar + /* ??? Vector and Fixed Point shifts by scalar shift operand are not supported yet. */ - if (is_shift && VECTOR_MODE_P (mode)) + if (is_shift && (VECTOR_MODE_P (mode) + || ALL_FIXED_POINT_MODE_P (mode))) break; if (is_shift Index: gcc/typeclass.h =================================================================== --- gcc/typeclass.h (revision 157409) +++ gcc/typeclass.h (working copy) @@ -31,7 +31,7 @@ { no_type_class = -1, void_type_class, integer_type_class, char_type_class, - enumeral_type_class, boolean_type_class, + enumeral_type_class, boolean_type_class, fixed_point_type_class, pointer_type_class, reference_type_class, offset_type_class, real_type_class, complex_type_class, function_type_class, method_type_class, Index: gcc/varasm.c =================================================================== --- gcc/varasm.c (revision 157409) +++ gcc/varasm.c (working copy) @@ -2670,7 +2670,7 @@ else mclass = MODE_INT; - omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0); + omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0); imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0); for (i = 0; i < size; i += subsize) Index: gcc/c-common.c =================================================================== --- gcc/c-common.c (revision 157409) +++ gcc/c-common.c (working copy) @@ -561,9 +561,9 @@ { "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT }, { "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT }, { "_Decimal128", RID_DFLOAT128, D_CONLY | D_EXT }, - { "_Fract", RID_FRACT, D_CONLY | D_EXT }, - { "_Accum", RID_ACCUM, D_CONLY | D_EXT }, - { "_Sat", RID_SAT, D_CONLY | D_EXT }, + { "_Fract", RID_FRACT, D_EXT }, + { "_Accum", RID_ACCUM, D_EXT }, + { "_Sat", RID_SAT, D_EXT }, { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, { "__alignof", RID_ALIGNOF, 0 },