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
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/>. */
#include "config.h"
#include "system.h"
#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;
{
/* warn_strict_aliasing >= 3. This includes the default (3).
Only warn if the cast is dereferenced immediately. */
- HOST_WIDE_INT set1 =
+ alias_set_type set1 =
get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
- HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+ alias_set_type set2 = get_alias_set (TREE_TYPE (type));
if (!alias_sets_conflict_p (set1, set2))
{
not taken in the same statement. This will likely produce many
false positives, but could be useful to pinpoint problems that
are not revealed at higher levels. */
- HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (otype));
- HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
- if (!COMPLETE_TYPE_P(type)
+ alias_set_type set1 = get_alias_set (TREE_TYPE (otype));
+ alias_set_type set2 = get_alias_set (TREE_TYPE (type));
+ if (!COMPLETE_TYPE_P (type)
|| !alias_sets_must_conflict_p (set1, set2))
{
warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
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. */
/* Return the typed-based alias set for T, which may be an expression
or a type. Return -1 if we don't do anything special. */
-HOST_WIDE_INT
+alias_set_type
c_common_get_alias_set (tree t)
{
tree u;
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");
}