#include "tree-iterator.h"
#include "hashtab.h"
#include "tree-mudflap.h"
+#include "opts.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
unit. It will inform the ObjC runtime that class definition(s) herein
contained are to replace one(s) previously loaded. */
int flag_replace_objc_classes = 0;
-
+
/* C/ObjC language option variables. */
};
static int constant_fits_type_p (tree, tree);
+static tree check_case_value (tree);
+static bool check_case_bounds (tree, tree, tree *, tree *);
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
handle_deprecated_attribute },
{ "vector_size", 1, 1, false, true, false,
handle_vector_size_attribute },
- { "visibility", 1, 1, true, false, false,
+ { "visibility", 1, 1, false, false, false,
handle_visibility_attribute },
{ "tls_model", 1, 1, true, false, false,
handle_tls_model_attribute },
int len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
cpp_string cstr = { 0, 0 }, strname;
- namep = xmalloc (len);
+ namep = XNEWVEC (char, len);
snprintf (namep, len, "\"%s\"", name);
strname.text = (unsigned char *) namep;
strname.len = len - 1;
expand_anon_union_decl (decl, NULL_TREE,
DECL_ANON_UNION_ELEMS (decl));
}
- else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
- make_rtl_for_local_static (decl);
else
return 0;
{
return targetm.vector_opaque_p (t1)
|| targetm.vector_opaque_p (t2)
- || TYPE_MODE (t1) == TYPE_MODE (t2);
+ || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ && INTEGRAL_TYPE_P (TREE_TYPE (t1))
+ == INTEGRAL_TYPE_P (TREE_TYPE (t2)));
}
/* Convert EXPR to TYPE, warning about conversion problems with constants.
new_tlist (struct tlist *next, tree t, tree writer)
{
struct tlist *l;
- l = obstack_alloc (&tlist_obstack, sizeof *l);
+ l = XOBNEW (&tlist_obstack, struct tlist);
l->next = next;
l->expr = t;
l->writer = writer;
{
struct tlist *tmp_before, *tmp_nosp, *tmp_list2, *tmp_list3;
enum tree_code code;
- char class;
+ char cl;
/* X may be NULL if it is the operand of an empty statement expression
({ }). */
restart:
code = TREE_CODE (x);
- class = TREE_CODE_CLASS (code);
+ cl = TREE_CODE_CLASS (code);
if (warning_candidate_p (x))
{
if (! t)
{
- t = obstack_alloc (&tlist_obstack, sizeof *t);
+ t = XOBNEW (&tlist_obstack, struct tlist_cache);
t->next = save_expr_cache;
t->expr = x;
save_expr_cache = t;
break;
}
- if (class == '1')
+ if (cl == '1')
{
if (first_rtl_op (code) == 0)
return;
goto restart;
}
- switch (class)
+ switch (cl)
{
case 'r':
case '<':
if (tlist_firstobj == 0)
{
gcc_obstack_init (&tlist_obstack);
- tlist_firstobj = obstack_alloc (&tlist_obstack, 0);
+ tlist_firstobj = (char *) obstack_alloc (&tlist_obstack, 0);
}
verify_tree (expr, &before_sp, &after_sp, 0);
\f
/* Validate the expression after `case' and apply default promotions. */
-tree
+static tree
check_case_value (tree value)
{
if (value == NULL_TREE)
return value;
}
\f
+/* See if the case values LOW and HIGH are in the range of the original
+ type (ie. before the default conversion to int) of the switch testing
+ expression.
+ TYPE is the promoted type of the testing expression, and ORIG_TYPE is
+ the type before promiting it. CASE_LOW_P is a pointer to the lower
+ bound of the case label, and CASE_HIGH_P is the upper bound or NULL
+ if the case is not a case range.
+ The caller has to make sure that we are not called with NULL for
+ CASE_LOW_P (ie. the defualt case).
+ Returns true if the case label is in range of ORIG_TYPE (satured or
+ untouched) or false if the label is out of range. */
+
+static bool
+check_case_bounds (tree type, tree orig_type,
+ tree *case_low_p, tree *case_high_p)
+{
+ tree min_value, max_value;
+ tree case_low = *case_low_p;
+ tree case_high = case_high_p ? *case_high_p : case_low;
+
+ /* If there was a problem with the original type, do nothing. */
+ if (orig_type == error_mark_node)
+ return true;
+
+ min_value = TYPE_MIN_VALUE (orig_type);
+ max_value = TYPE_MAX_VALUE (orig_type);
+
+ /* Case label is less than minimum for type. */
+ if (tree_int_cst_compare (case_low, min_value) < 0
+ && tree_int_cst_compare (case_high, min_value) < 0)
+ {
+ warning ("case label value is less than minimum value for type");
+ return false;
+ }
+
+ /* Case value is greater than maximum for type. */
+ if (tree_int_cst_compare (case_low, max_value) > 0
+ && tree_int_cst_compare (case_high, max_value) > 0)
+ {
+ warning ("case label value exceeds maximum value for type");
+ return false;
+ }
+
+ /* Saturate lower case label value to minimum. */
+ if (tree_int_cst_compare (case_high, min_value) >= 0
+ && tree_int_cst_compare (case_low, min_value) < 0)
+ {
+ warning ("lower value in case label range"
+ " less than minimum value for type");
+ case_low = min_value;
+ }
+
+ /* Saturate upper case label value to maximum. */
+ if (tree_int_cst_compare (case_low, max_value) <= 0
+ && tree_int_cst_compare (case_high, max_value) > 0)
+ {
+ warning ("upper value in case label range"
+ " exceeds maximum value for type");
+ case_high = max_value;
+ }
+
+ if (*case_low_p != case_low)
+ *case_low_p = convert (type, case_low);
+ if (case_high_p && *case_high_p != case_high)
+ *case_high_p = convert (type, case_high);
+
+ return true;
+}
+\f
/* Return an integer type with BITS bits of precision,
that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
if (mode == TYPE_MODE (void_type_node))
return void_type_node;
-
+
if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
|| TYPE_UNSIGNED (type) == unsignedp)
return type;
- /* Must check the mode of the types, not the precision. Enumeral types
- in C++ have precision set to match their range, but may use a wider
- mode to match an ABI. If we change modes, we may wind up with bad
- conversions. */
-
- if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node))
+ /* 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
+ wind up with bad conversions. For INTEGER_TYPEs in C, must check
+ the precision as well, so as to yield correct results for
+ bit-field types. C++ does not have these separate bit-field
+ types, and producing a signed or unsigned variant of an
+ ENUMERAL_TYPE may cause other problems as well. */
+
+#define TYPE_OK(node) \
+ (TYPE_MODE (type) == TYPE_MODE (node) \
+ && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
+ if (TYPE_OK (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (integer_type_node))
+ if (TYPE_OK (integer_type_node))
return unsignedp ? unsigned_type_node : integer_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node))
+ if (TYPE_OK (short_integer_type_node))
return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node))
+ if (TYPE_OK (long_integer_type_node))
return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node))
+ if (TYPE_OK (long_long_integer_type_node))
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
- if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node))
+ if (TYPE_OK (widest_integer_literal_type_node))
return (unsignedp ? widest_unsigned_literal_type_node
: widest_integer_literal_type_node);
#if HOST_BITS_PER_WIDE_INT >= 64
- if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node))
+ if (TYPE_OK (intTI_type_node))
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
#endif
- if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node))
+ if (TYPE_OK (intDI_type_node))
return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node))
+ if (TYPE_OK (intSI_type_node))
return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node))
+ if (TYPE_OK (intHI_type_node))
return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node))
+ if (TYPE_OK (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+#undef TYPE_OK
- return type;
+ if (c_dialect_cxx ())
+ return type;
+ else
+ return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}
/* The C version of the register_builtin_type langhook. */
*restype_ptr = c_common_signed_type (*restype_ptr);
if (TREE_TYPE (primop1) != *restype_ptr)
- primop1 = convert (*restype_ptr, primop1);
+ {
+ tree tmp = convert (*restype_ptr, primop1);
+ TREE_OVERFLOW (tmp) = TREE_OVERFLOW (primop1);
+ TREE_CONSTANT_OVERFLOW (tmp) = TREE_CONSTANT_OVERFLOW (primop1);
+ primop1 = tmp;
+ }
if (type != *restype_ptr)
{
minval = convert (*restype_ptr, minval);
break;
case MODIFY_EXPR:
- if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
+ if (warn_parentheses && !TREE_NO_WARNING (expr))
warning ("suggest parentheses around assignment used as truth value");
break;
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
}
\f
-static tree builtin_function_2 (const char *, const char *, tree, tree,
- int, enum built_in_class, int, int,
- tree);
+static tree builtin_function_2 (const char *builtin_name, const char *name,
+ tree builtin_type, tree type,
+ enum built_in_function function_code,
+ enum built_in_class cl, int library_name_p,
+ bool nonansi_p,
+ tree attrs);
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
{
if (type == error_mark_node)
return type;
-
+
if (TREE_CODE (type) == ARRAY_TYPE)
return build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
c_apply_type_quals_to_decl (int type_quals, tree decl)
{
tree type = TREE_TYPE (decl);
-
+
if (type == error_mark_node)
return;
return -1;
/* Save time if there's only one input file. */
- if (!current_file_decl || TREE_CHAIN (current_file_decl) == NULL_TREE)
+ if (num_in_fnames == 1)
return -1;
/* Pointers need special handling if they point to any type that
{
tree t2;
/* Find bottom type under any nested POINTERs. */
- for (t2 = TREE_TYPE (t);
+ for (t2 = TREE_TYPE (t);
TREE_CODE (t2) == POINTER_TYPE;
t2 = TREE_TYPE (t2))
;
- if (TREE_CODE (t2) != RECORD_TYPE
+ if (TREE_CODE (t2) != RECORD_TYPE
&& TREE_CODE (t2) != ENUMERAL_TYPE
&& TREE_CODE (t2) != QUAL_UNION_TYPE
&& TREE_CODE (t2) != UNION_TYPE)
return -1;
}
/* These are the only cases that need special handling. */
- if (TREE_CODE (t) != RECORD_TYPE
+ if (TREE_CODE (t) != RECORD_TYPE
&& TREE_CODE (t) != ENUMERAL_TYPE
&& TREE_CODE (t) != QUAL_UNION_TYPE
&& TREE_CODE (t) != UNION_TYPE
if (TYPE_SIZE (t) == 0)
return -1;
- /* Look up t in hash table. Only one of the compatible types within each
+ /* Look up t in hash table. Only one of the compatible types within each
alias set is recorded in the table. */
if (!type_hash_table)
type_hash_table = htab_create (1021, c_type_hash,
NULL);
slot = htab_find_slot (type_hash_table, t, INSERT);
if (*slot != NULL)
- return TYPE_ALIAS_SET ((tree)*slot);
+ {
+ TYPE_ALIAS_SET (t) = TYPE_ALIAS_SET ((tree)*slot);
+ return TYPE_ALIAS_SET ((tree)*slot);
+ }
else
/* Our caller will assign and record (in t) a new alias set; all we need
to do is remember t in the hash table. */
else if (!COMPLETE_TYPE_P (type))
{
if (complain)
- error ("invalid application of `%s' to incomplete type `%T' ",
+ error ("invalid application of `%s' to incomplete type `%T' ",
op_name, type);
value = size_zero_node;
}
else
{
- if (op == SIZEOF_EXPR)
+ if (op == (enum tree_code) SIZEOF_EXPR)
/* Convert in case a char is more than one unit. */
value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
size_int (TYPE_PRECISION (char_type_node)
abort (); \
\
if (!BOTH_P) \
- decl = builtin_function (NAME, builtin_types[TYPE], ENUM, \
+ decl = lang_hooks.builtin_function (NAME, builtin_types[TYPE], \
+ ENUM, \
CLASS, \
(FALLBACK_P \
? (NAME + strlen ("__builtin_")) \
error ("cannot disable built-in function `%s'", name);
else
{
- disabled_builtin *new = xmalloc (sizeof (disabled_builtin));
- new->name = name;
- new->next = disabled_builtins;
- disabled_builtins = new;
+ disabled_builtin *new_disabled_builtin = XNEW (disabled_builtin);
+ new_disabled_builtin->name = name;
+ new_disabled_builtin->next = disabled_builtins;
+ disabled_builtins = new_disabled_builtin;
}
}
BUILTIN_TYPE is the type of the __builtin_-prefixed function;
TYPE is the type of the function with the ordinary name. These
may differ if the ordinary name is declared with a looser type to avoid
- conflicts with headers. FUNCTION_CODE and CLASS are as for
+ conflicts with headers. FUNCTION_CODE and CL are as for
builtin_function. If LIBRARY_NAME_P is nonzero, NAME is passed as
the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
- If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name;
+ If NONANSI_P is true, the name NAME is treated as a non-ANSI name;
ATTRS is the tree list representing the builtin's function attributes.
Returns the declaration of BUILTIN_NAME, if any, otherwise
the declaration of NAME. Does not declare NAME if flag_no_builtin,
static tree
builtin_function_2 (const char *builtin_name, const char *name,
- tree builtin_type, tree type, int function_code,
- enum built_in_class class, int library_name_p,
- int nonansi_p, tree attrs)
+ tree builtin_type, tree type,
+ enum built_in_function function_code,
+ enum built_in_class cl, int library_name_p,
+ bool nonansi_p, tree attrs)
{
tree bdecl = NULL_TREE;
tree decl = NULL_TREE;
if (builtin_name != 0)
- bdecl = builtin_function (builtin_name, builtin_type, function_code,
- class, library_name_p ? name : NULL, attrs);
+ bdecl = lang_hooks.builtin_function (builtin_name, builtin_type,
+ function_code, cl,
+ library_name_p ? name : NULL, attrs);
if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
&& !(nonansi_p && flag_no_nonansi_builtin))
- decl = builtin_function (name, type, function_code, class, NULL, attrs);
+ decl = lang_hooks.builtin_function (name, type, function_code, cl,
+ NULL, attrs);
return (bdecl != 0 ? bdecl : decl);
}
ERROR_MARK_NODE if no CASE_LABEL_EXPR is created. */
tree
-c_add_case_label (splay_tree cases, tree cond, tree low_value,
- tree high_value)
+c_add_case_label (splay_tree cases, tree cond, tree orig_type,
+ tree low_value, tree high_value)
{
tree type;
tree label;
&& !tree_int_cst_lt (low_value, high_value))
warning ("empty range specified");
+ /* See if the case is in range of the type of the original testing
+ expression. If both low_value and high_value are out of range,
+ don't insert the case label and return NULL_TREE. */
+ if (low_value
+ && ! check_case_bounds (type, orig_type,
+ &low_value, high_value ? &high_value : NULL))
+ return NULL_TREE;
+
/* Look up the LOW_VALUE in the table of case labels we already
have. */
node = splay_tree_lookup (cases, (splay_tree_key) low_value);
match_case_to_enum (splay_tree_node node, void *data)
{
tree label = (tree) node->value;
- tree type = data;
+ tree type = (tree) data;
/* Skip default case. */
if (!CASE_LOW (label))
void
c_do_switch_warnings (splay_tree cases, tree switch_stmt)
{
- splay_tree_node default_node;
+ splay_tree_node default_node;
location_t switch_location;
tree type;
tree chain;
/* The time complexity here is O(N*lg(N)) worst case, but for the
- common case of monotonically increasing enumerators, it is
+ common case of monotonically increasing enumerators, it is
O(N), since the nature of the splay tree will keep the next
element adjacent to the root at all times. */
if (node)
{
/* Mark the CASE_LOW part of the case entry as seen, so
- that we save time later. Choose TREE_ADDRESSABLE
+ that we save time later. Choose TREE_ADDRESSABLE
randomly as a bit that won't have been set to-date. */
tree label = (tree) node->value;
TREE_ADDRESSABLE (label) = 1;
The time complexity here is O(N**2) worst case, since we've
not sorted the enumeration values. However, in the absence
- of case ranges this is O(N), since all single cases that
+ of case ranges this is O(N), since all single cases that
corresponded to enumerations have been marked above. */
splay_tree_foreach (cases, match_case_to_enum, type);
}
/* Hook used by expand_expr to expand language-specific tree codes. */
-/* The only things that should go here are bits needed to expand
+/* The only things that should go here are bits needed to expand
constant initializers. Everything else should be handled by the
gimplification routines. */
rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
+c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
int modifier /* Actually enum_modifier. */,
rtx *alt_rtl)
{
}
}
-/* Hook used by unsafe_for_reeval to handle language-specific tree codes. */
-
-int
-c_common_unsafe_for_reeval (tree exp)
-{
- /* Statement expressions may not be reevaluated, likewise compound
- literals. */
- if (TREE_CODE (exp) == STMT_EXPR
- || TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
- return 2;
-
- /* Walk all other expressions. */
- return -1;
-}
-
/* Hook used by staticp to handle language-specific tree codes. */
-int
+bool
c_staticp (tree exp)
{
if (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
&& TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
- return 1;
- return 0;
+ return true;
+ return false;
}
\f
builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
+ builtin_define_with_value ("__INTMAX_TYPE__", INTMAX_TYPE, 0);
+ builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
}
static void
struct attribute_spec.handler. */
static tree
-handle_packed_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
int flags, bool *no_add_attrs)
{
if (TYPE_P (*node))
{
/* If it is the main variant, then pack the other variants
too. This happens in,
-
+
struct Foo {
struct Foo const *ptr; // creates a variant w/o packed flag
} __ attribute__((packed)); // packs it now.
*/
tree probe;
-
+
for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
TYPE_PACKED (probe) = 1;
}
-
+
}
else if (TREE_CODE (*node) == FIELD_DECL)
DECL_PACKED (*node) = 1;
static tree
handle_nocommon_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == VAR_DECL)
DECL_COMMON (*node) = 0;
struct attribute_spec.handler. */
static tree
-handle_common_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == VAR_DECL)
DECL_COMMON (*node) = 1;
struct attribute_spec.handler. */
static tree
-handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = TREE_TYPE (*node);
static tree
handle_noinline_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
DECL_UNINLINABLE (*node) = 1;
static tree
handle_always_inline_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
struct attribute_spec.handler. */
static tree
-handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree node = *pnode;
struct attribute_spec.handler. */
static tree
-handle_unused_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int flags, bool *no_add_attrs)
{
if (DECL_P (*node))
{
struct attribute_spec.handler. */
static tree
-handle_const_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = TREE_TYPE (*node);
static tree
handle_transparent_union_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED, int flags,
+ tree ARG_UNUSED (args), int flags,
bool *no_add_attrs)
{
tree decl = NULL_TREE;
static tree
handle_constructor_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
static tree
handle_destructor_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
struct attribute_spec.handler. */
static tree
-handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_mode_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = *node;
if (len > 4 && p[0] == '_' && p[1] == '_'
&& p[len - 1] == '_' && p[len - 2] == '_')
{
- char *newp = alloca (len - 1);
+ char *newp = (char *) alloca (len - 1);
strcpy (newp, &p[2]);
newp[len - 4] = '\0';
struct attribute_spec.handler. */
static tree
-handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
struct attribute_spec.handler. */
static tree
-handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
+handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
int flags, bool *no_add_attrs)
{
tree decl = NULL_TREE;
struct attribute_spec.handler. */
static tree
-handle_weak_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs ATTRIBUTE_UNUSED)
+handle_weak_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
{
declare_weak (*node);
static tree
handle_alias_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
static tree
handle_visibility_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED,
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
*no_add_attrs = true;
- if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
+ if (TYPE_P (*node))
+ {
+ if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
+ {
+ warning ("`%s' attribute ignored on non-class types",
+ IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+ }
+ else if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
return NULL_TREE;
return NULL_TREE;
}
+ /* If this is a type, set the visibility on the type decl. */
+ if (TYPE_P (decl))
+ {
+ decl = TYPE_NAME (decl);
+ if (! decl)
+ return NULL_TREE;
+ }
+
if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
else
error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+
+ /* For decls only, go ahead and attach the attribute to the node as well.
+ This is needed so we can determine whether we have VISIBILITY_DEFAULT
+ because the visibility was not specified, or because it was explicitly
+ overridden from the class visibility. */
+ if (DECL_P (*node))
+ *no_add_attrs = false;
return NULL_TREE;
}
+/* Determine the ELF symbol visibility for DECL, which is either a
+ variable or a function. It is an error to use this function if a
+ definition of DECL is not available in this translation unit.
+ Returns true if the final visibility has been determined by this
+ function; false if the caller is free to make additional
+ modifications. */
+
+bool
+c_determine_visibility (tree decl)
+{
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL,
+ 20040805);
+
+ /* If the user explicitly specified the visibility with an
+ attribute, honor that. DECL_VISIBILITY will have been set during
+ the processing of the attribute. We check for an explicit
+ attribute, rather than just checking DECL_VISIBILITY_SPECIFIED,
+ to distinguish the use of an attribute from the use of a "#pragma
+ GCC visibility push(...)"; in the latter case we still want other
+ considerations to be able to overrule the #pragma. */
+ if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
+ return true;
+
+ /* Anything that is exported must have default visibility. */
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ {
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ return true;
+ }
+
+ return false;
+}
+
/* Handle an "tls_model" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_tls_model_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
static tree
handle_no_instrument_function_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
struct attribute_spec.handler. */
static tree
-handle_malloc_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
DECL_IS_MALLOC (*node) = 1;
static tree
handle_no_limit_stack_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
struct attribute_spec.handler. */
static tree
-handle_pure_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
DECL_IS_PURE (*node) = 1;
static tree
handle_deprecated_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED, int flags,
+ tree ARG_UNUSED (args), int flags,
bool *no_add_attrs)
{
tree type = NULL_TREE;
static tree
handle_vector_size_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED,
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
unsigned HOST_WIDE_INT vecsize, nunits;
- enum machine_mode mode, orig_mode, new_mode;
+ enum machine_mode orig_mode;
tree type = *node, new_type, size;
*no_add_attrs = true;
/* Calculate how many units fit in the vector. */
nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
-
- /* Find a suitably sized vector. */
- new_mode = VOIDmode;
- for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
- ? MODE_VECTOR_INT
- : MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (vecsize == GET_MODE_SIZE (mode)
- && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
- {
- new_mode = mode;
- break;
- }
-
- if (new_mode == VOIDmode)
+ if (nunits & (nunits - 1))
{
- error ("no vector mode with the size and type specified could be found");
+ error ("number of components of the vector not a power of two");
return NULL_TREE;
}
- new_type = build_vector_type_for_mode (type, new_mode);
+ new_type = build_vector_type (type, nunits);
/* Build back pointers if needed. */
*node = reconstruct_complex_type (*node, new_type);
/* Handle the "nonnull" attribute. */
static tree
-handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
- tree args, int flags ATTRIBUTE_UNUSED,
+handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree type = *node;
via check_function_arguments_recurse. */
static void
-check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param,
+check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
unsigned HOST_WIDE_INT param_num)
{
/* Just skip checking the argument if it's not a pointer. This can
struct attribute_spec.handler. */
static tree
-handle_nothrow_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
TREE_NOTHROW (*node) = 1;
static tree
handle_cleanup_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
tree cleanup_id, cleanup_decl;
static tree
handle_warn_unused_result_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
/* Ignore the attribute for functions not returning any value. */
if (VOID_TYPE_P (TREE_TYPE (*node)))
int
field_decl_cmp (const void *x_p, const void *y_p)
{
- const tree *const x = x_p;
- const tree *const y = y_p;
+ const tree *const x = (const tree *const) x_p;
+ const tree *const y = (const tree *const) y_p;
+
if (DECL_NAME (*x) == DECL_NAME (*y))
/* A nontype is "greater" than a type. */
return (TREE_CODE (*y) == TYPE_DECL) - (TREE_CODE (*x) == TYPE_DECL);
static int
resort_field_decl_cmp (const void *x_p, const void *y_p)
{
- const tree *const x = x_p;
- const tree *const y = y_p;
+ const tree *const x = (const tree *const) x_p;
+ const tree *const y = (const tree *const) y_p;
if (DECL_NAME (*x) == DECL_NAME (*y))
/* A nontype is "greater" than a type. */
void
resort_sorted_fields (void *obj,
- void *orig_obj ATTRIBUTE_UNUSED ,
+ void * ARG_UNUSED (orig_obj),
gt_pointer_operator new_value,
void *cookie)
{
- struct sorted_fields_type *sf = obj;
+ struct sorted_fields_type *sf = (struct sorted_fields_type *) obj;
resort_data.new_value = new_value;
resort_data.cookie = cookie;
qsort (&sf->elts[0], sf->len, sizeof (tree),
/* Walk a gimplified function and warn for functions whose return value is
ignored and attribute((warn_unused_result)) is set. This is done before
- inlining, so we don't have to worry about that. */
-
+ inlining, so we don't have to worry about that. */
+
void
c_warn_unused_result (tree *top_p)
{
break;
case CALL_EXPR:
+ if (TREE_USED (t))
+ break;
+
/* This is a naked call, as opposed to a CALL_EXPR nested inside
a MODIFY_EXPR. All calls whose value is ignored should be
represented like this. Look for the attribute. */