/* Functions dealing with attribute handling, used by most front ends.
- Copyright (C) 1992-2023 Free Software Foundation, Inc.
+ Copyright (C) 1992-2024 Free Software Foundation, Inc.
This file is part of GCC.
#include "diagnostic-core.h"
#include "attribs.h"
#include "fold-const.h"
+#include "ipa-strub.h"
#include "stor-layout.h"
#include "langhooks.h"
#include "plugin.h"
attrs = { table, 1 };
}
const scoped_attribute_specs scoped_specs = {
- IDENTIFIER_POINTER (vendor_id), attrs
+ IDENTIFIER_POINTER (vendor_id), { attrs }
};
register_scoped_attributes (scoped_specs, attrs.empty ());
}
free_attr_data ()
{
for (auto x : ignored_attributes_table)
- delete[] x;
+ delete x;
ignored_attributes_table.release ();
}
return as->max_length == -2;
}
+/* Return true if the ATTRS chain contains at least one attribute which
+ is not ignored. */
+
+bool
+any_nonignored_attribute_p (tree attrs)
+{
+ for (tree attr = attrs; attr; attr = TREE_CHAIN (attr))
+ if (!attribute_ignored_p (attr))
+ return true;
+
+ return false;
+}
+
/* See whether LIST contains at least one instance of attribute ATTR
(possibly with different arguments). Return the first such attribute
if so, otherwise return null. */
options to the attribute((target(...))) list. */
if (TREE_CODE (*node) == FUNCTION_DECL
&& current_target_pragma
- && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
+ && targetm.target_option.valid_attribute_p (*node,
+ get_identifier ("target"),
current_target_pragma, 0))
{
tree cur_attr = lookup_attribute ("target", attributes);
flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
}
- if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
- && TREE_CODE (*anode) != METHOD_TYPE)
+ if (spec->function_type_required
+ && !FUNC_OR_METHOD_TYPE_P (*anode))
{
if (TREE_CODE (*anode) == POINTER_TYPE
&& FUNC_OR_METHOD_TYPE_P (TREE_TYPE (*anode)))
TYPE_NAME (tt) = *node;
}
- *anode = cur_and_last_decl[0];
+ if (*anode != cur_and_last_decl[0])
+ {
+ /* Even if !spec->function_type_required, allow the attribute
+ handler to request the attribute to be applied to the function
+ type, rather than to the function pointer type, by setting
+ cur_and_last_decl[0] to the function type. */
+ if (!fn_ptr_tmp
+ && POINTER_TYPE_P (*anode)
+ && TREE_TYPE (*anode) == cur_and_last_decl[0]
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (*anode)))
+ {
+ fn_ptr_tmp = TREE_TYPE (*anode);
+ fn_ptr_quals = TYPE_QUALS (*anode);
+ anode = &fn_ptr_tmp;
+ }
+ *anode = cur_and_last_decl[0];
+ }
+
if (ret == error_mark_node)
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
return func_decl;
}
-/* Returns true if decl is multi-versioned and DECL is the default function,
- that is it is not tagged with target specific optimization. */
+/* Returns true if DECL is multi-versioned using the target attribute, and this
+ is the default version. This function can only be used for targets that do
+ not support the "target_version" attribute. */
bool
is_function_default_version (const tree decl)
const struct attribute_spec *as;
const_tree attr;
- as = lookup_attribute_spec (get_attribute_name (a));
+ as = lookup_attribute_spec (TREE_PURPOSE (a));
if (!as || as->affects_type_identity == false)
continue;
{
const struct attribute_spec *as;
- as = lookup_attribute_spec (get_attribute_name (a));
+ as = lookup_attribute_spec (TREE_PURPOSE (a));
if (!as || as->affects_type_identity == false)
continue;
if ((lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type1)) != NULL)
^ (lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type2)) != NULL))
return 0;
+ int strub_ret = strub_comptypes (CONST_CAST_TREE (type1),
+ CONST_CAST_TREE (type2));
+ if (strub_ret == 0)
+ return strub_ret;
/* As some type combinations - like default calling-convention - might
be compatible, we have to call the target hook to get the final result. */
- return targetm.comp_type_attributes (type1, type2);
+ int target_ret = targetm.comp_type_attributes (type1, type2);
+ if (target_ret == 0)
+ return target_ret;
+ if (strub_ret == 2 || target_ret == 2)
+ return 2;
+ if (strub_ret == 1 && target_ret == 1)
+ return 1;
+ gcc_unreachable ();
}
/* PREDICATE acts as a function of type:
const_tree start = attrs;
for (const_tree attr = attrs; attr; attr = TREE_CHAIN (attr))
{
- tree name = get_attribute_name (attr);
- const attribute_spec *as = lookup_attribute_spec (name);
+ const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attr));
const_tree end;
if (!predicate (attr, as))
end = attr;