#include "real.h"
#include "cgraph.h"
#include "target-def.h"
+#include "fixed-value.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int,
bool *);
-static tree handle_gnu_inline_attribute (tree *, tree, tree, int,
- bool *);
+static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
+static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
+static tree handle_error_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
handle_always_inline_attribute },
{ "gnu_inline", 0, 0, true, false, false,
handle_gnu_inline_attribute },
+ { "artificial", 0, 0, true, false, false,
+ handle_artificial_attribute },
{ "flatten", 0, 0, true, false, false,
handle_flatten_attribute },
{ "used", 0, 0, true, false, false,
handle_cold_attribute },
{ "hot", 0, 0, true, false, false,
handle_hot_attribute },
+ { "warning", 1, 1, true, false, false,
+ handle_error_attribute },
+ { "error", 1, 1, true, false, false,
+ handle_error_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
{
const char *name = "top level";
char *namep;
- int vrb = 2;
+ int vrb = 2, len;
+ cpp_string cstr = { 0, 0 }, strname;
if (!pretty_p)
{
if (current_function_decl)
name = lang_hooks.decl_printable_name (current_function_decl, vrb);
- if (c_lex_string_translate)
- {
- int len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
- cpp_string cstr = { 0, 0 }, strname;
+ len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
- namep = XNEWVEC (char, len);
- snprintf (namep, len, "\"%s\"", name);
- strname.text = (unsigned char *) namep;
- strname.len = len - 1;
+ namep = XNEWVEC (char, len);
+ snprintf (namep, len, "\"%s\"", name);
+ strname.text = (unsigned char *) namep;
+ strname.len = len - 1;
- if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
- {
- XDELETEVEC (namep);
- return (const char *) cstr.text;
- }
+ if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
+ {
+ XDELETEVEC (namep);
+ return (const char *) cstr.text;
}
- else
- namep = xstrdup (name);
return namep;
}
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)
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;
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;
else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
{
+ /* Don't warn about unsigned char y = 0xff, x = (int) y; */
+ expr = get_unwidened (expr, 0);
+
/* Warn for integer types converted to smaller integer types. */
if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
give_warning = true;
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
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)
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);
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
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;
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))
{
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
? 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. */
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
bool both_p, bool fallback_p, bool nonansi_p,
tree fnattrs, bool implicit_p);
-/* Make a variant type in the proper way for C/C++, propagating qualifiers
- down to the element type of an array. */
-
-tree
-c_build_qualified_type (tree type, int type_quals)
-{
- if (type == error_mark_node)
- return type;
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree t;
- tree element_type = c_build_qualified_type (TREE_TYPE (type),
- type_quals);
-
- /* See if we already have an identically qualified type. */
- for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- {
- if (TYPE_QUALS (strip_array_types (t)) == type_quals
- && TYPE_NAME (t) == TYPE_NAME (type)
- && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
- && attribute_list_equal (TYPE_ATTRIBUTES (t),
- TYPE_ATTRIBUTES (type)))
- break;
- }
- if (!t)
- {
- tree domain = TYPE_DOMAIN (type);
-
- t = build_variant_type_copy (type);
- TREE_TYPE (t) = element_type;
-
- if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
- || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else if (TYPE_CANONICAL (element_type) != element_type
- || (domain && TYPE_CANONICAL (domain) != domain))
- {
- tree unqualified_canon
- = build_array_type (TYPE_CANONICAL (element_type),
- domain? TYPE_CANONICAL (domain)
- : NULL_TREE);
- TYPE_CANONICAL (t)
- = c_build_qualified_type (unqualified_canon, type_quals);
- }
- else
- TYPE_CANONICAL (t) = t;
- }
- return t;
- }
-
- /* A restrict-qualified pointer type must be a pointer to object or
- incomplete type. Note that the use of POINTER_TYPE_P also allows
- REFERENCE_TYPEs, which is appropriate for C++. */
- if ((type_quals & TYPE_QUAL_RESTRICT)
- && (!POINTER_TYPE_P (type)
- || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
- {
- error ("invalid use of %<restrict%>");
- type_quals &= ~TYPE_QUAL_RESTRICT;
- }
-
- return build_qualified_type (type, type_quals);
-}
/* Apply the TYPE_QUALS to the new DECL. */
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));
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))
{
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);
}
}
-
-/* Generate the RTL for the body of FNDECL. */
-
-void
-c_expand_body (tree fndecl)
-{
- tree_rest_of_compilation (fndecl);
-}
-
/* Hook used by staticp to handle language-specific tree codes. */
tree
{
if (TREE_CODE (*node) == FUNCTION_DECL)
{
- /* Do nothing else, just set the attribute. We'll get at
- it later with lookup_attribute. */
+ /* Set the attribute and mark it for disregarding inline
+ limits. */
+ DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
}
else
{
return NULL_TREE;
}
+/* Handle an "artificial" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_artificial_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
+ {
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "flatten" attribute; arguments as in
struct attribute_spec.handler. */
return NULL_TREE;
}
+/* Handle a "warning" or "error" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_error_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ ;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
/* Handle a "used" attribute; arguments as in
struct attribute_spec.handler. */
tree ARG_UNUSED (args), int flags,
bool *no_add_attrs)
{
- tree type = NULL;
+ tree type;
*no_add_attrs = true;
- if (DECL_P (*node))
- {
- if (TREE_CODE (*node) != TYPE_DECL)
- goto ignored;
- node = &TREE_TYPE (*node);
- type = *node;
- }
- else if (TYPE_P (*node))
- type = *node;
- else
- goto ignored;
+ if (TREE_CODE (*node) == TYPE_DECL)
+ node = &TREE_TYPE (*node);
+ type = *node;
if (TREE_CODE (type) == UNION_TYPE)
{
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;
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,
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)
{
|| 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);
hashcode);
main_type = type_hash_canon (hashcode, main_type);
+ /* Fix the canonical type. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
+ || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
+ SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+ else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
+ || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
+ != TYPE_DOMAIN (main_type)))
+ TYPE_CANONICAL (main_type)
+ = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
+ TYPE_CANONICAL (TYPE_DOMAIN (main_type)));
+ else
+ TYPE_CANONICAL (main_type) = main_type;
+
if (quals == 0)
type = main_type;
else
type = c_build_qualified_type (main_type, quals);
+ if (COMPLETE_TYPE_P (type)
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+ && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
+ {
+ error ("size of array is too large");
+ /* If we proceed with the array type as it is, we'll eventually
+ crash in tree_low_cst(). */
+ type = error_mark_node;
+ }
+
*ptype = type;
return failure;
}
{
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. */
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");
}