This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: fixed-point support in c++
> 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 },