]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/attribs.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / attribs.cc
index 8ad9b3b234903cfd0d0d5b0bdc59d1fcc65fd0eb..4df5d2410dad159a9d917422799274dc3cf6c6c1 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #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"
@@ -102,6 +103,19 @@ static const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
 
 static bool attributes_initialized = false;
 
+/* Do not use directly; go through get_gnu_namespace instead.  */
+static GTY(()) tree gnu_namespace_cache;
+
+/* Return the IDENTIFIER_NODE for the gnu namespace.  */
+
+static tree
+get_gnu_namespace ()
+{
+  if (!gnu_namespace_cache)
+    gnu_namespace_cache = get_identifier ("gnu");
+  return gnu_namespace_cache;
+}
+
 /* Return base name of the attribute.  Ie '__attr__' is turned into 'attr'.
    To avoid need for copying, we simply return length of the string.  */
 
@@ -289,7 +303,7 @@ handle_ignored_attributes_option (vec<char *> *v)
          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 ());
     }
@@ -301,7 +315,7 @@ void
 free_attr_data ()
 {
   for (auto x : ignored_attributes_table)
-    delete[] x;
+    delete x;
   ignored_attributes_table.release ();
 }
 
@@ -403,7 +417,7 @@ lookup_attribute_spec (const_tree name)
       name = TREE_VALUE (name);
     }
   else
-    ns = get_identifier ("gnu");
+    ns = get_gnu_namespace ();
   return lookup_scoped_attribute_spec (ns, name);
 }
 
@@ -420,7 +434,7 @@ get_attribute_namespace (const_tree attr)
 {
   if (cxx11_attribute_p (attr))
     return TREE_PURPOSE (TREE_PURPOSE (attr));
-  return get_identifier ("gnu");
+  return get_gnu_namespace ();
 }
 
 /* Check LAST_DECL and NODE of the same symbol for attributes that are
@@ -570,6 +584,36 @@ attribute_ignored_p (const attribute_spec *const as)
   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.  */
+
+static tree
+find_same_attribute (const_tree attr, tree list)
+{
+  if (list == NULL_TREE)
+    return NULL_TREE;
+  tree ns = get_attribute_namespace (attr);
+  tree name = get_attribute_name (attr);
+  return private_lookup_attribute (ns ? IDENTIFIER_POINTER (ns) : nullptr,
+                                  IDENTIFIER_POINTER (name),
+                                  ns ? IDENTIFIER_LENGTH (ns) : 0,
+                                  IDENTIFIER_LENGTH (name), list);
+}
+
 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
    it should be modified in place; if a TYPE, a copy should be created
@@ -631,7 +675,8 @@ decl_attributes (tree *node, tree attributes, int flags,
      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);
@@ -759,8 +804,8 @@ decl_attributes (tree *node, tree attributes, int flags,
          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)))
@@ -875,7 +920,24 @@ decl_attributes (tree *node, tree attributes, int flags,
              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);
@@ -902,9 +964,9 @@ decl_attributes (tree *node, tree attributes, int flags,
          else
            old_attrs = TYPE_ATTRIBUTES (*anode);
 
-         for (a = lookup_attribute (spec->name, old_attrs);
+         for (a = find_same_attribute (attr, old_attrs);
               a != NULL_TREE;
-              a = lookup_attribute (spec->name, TREE_CHAIN (a)))
+              a = find_same_attribute (attr, TREE_CHAIN (a)))
            {
              if (simple_cst_equal (TREE_VALUE (a), args) == 1)
                break;
@@ -935,8 +997,8 @@ decl_attributes (tree *node, tree attributes, int flags,
                          if (TYPE_ATTRIBUTES (variant) == old_attrs)
                            TYPE_ATTRIBUTES (variant)
                              = TYPE_ATTRIBUTES (*anode);
-                         else if (!lookup_attribute
-                                  (spec->name, TYPE_ATTRIBUTES (variant)))
+                         else if (!find_same_attribute
+                                  (attr, TYPE_ATTRIBUTES (variant)))
                            TYPE_ATTRIBUTES (variant) = tree_cons
                              (name, args, TYPE_ATTRIBUTES (variant));
                        }
@@ -1215,8 +1277,9 @@ make_dispatcher_decl (const tree decl)
   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)
@@ -1445,11 +1508,11 @@ comp_type_attributes (const_tree type1, const_tree type2)
       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;
 
-      attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
+      attr = find_same_attribute (a, CONST_CAST_TREE (a2));
       if (!attr || !attribute_value_equal (a, attr))
        break;
     }
@@ -1459,11 +1522,11 @@ comp_type_attributes (const_tree type1, const_tree type2)
        {
          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 (as->name, CONST_CAST_TREE (a1)))
+         if (!find_same_attribute (a, CONST_CAST_TREE (a1)))
            break;
          /* We don't need to compare trees again, as we did this
             already in first loop.  */
@@ -1478,9 +1541,20 @@ comp_type_attributes (const_tree type1, const_tree type2)
   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:
@@ -1501,8 +1575,7 @@ remove_attributes_matching (tree attrs, Predicate predicate)
   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;
@@ -2692,3 +2765,5 @@ attribs_cc_tests ()
 } /* namespace selftest */
 
 #endif /* CHECKING_P */
+
+#include "gt-attribs.h"