OSDN Git Service

In gcc/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Jun 2011 09:52:55 +0000 (09:52 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Jun 2011 09:52:55 +0000 (09:52 +0000)
2011-06-21  Nicola Pero  <nicola.pero@meta-innovation.com>

* attribs.c (register_attribute): Added assert to check that all
attribute specs are registered with a name that is not empty and
does not start with '_'.
(decl_attributes): Avoid the lookup of the "naked" attribute spec
if the function has no attributes.
* tree.c (is_attribute_with_length_p): Removed.
(is_attribute_p): Removed.
(private_is_attribute_p): New.
(private_lookup_attribute): New.
(lookup_attribute): Removed.
(lookup_ident_attribute): New.
(remove_attribute): Require the first argument to be in the form
'text', not '__text__'.  Updated asserts.
(merge_attributes): Use lookup_ident_attributes instead of
lookup_attribute.
(merge_dllimport_decl_attributes): Use remove_attribute.
(attribute_list_contained): Likewise.
(attribute_list_equal): Immediately return 1 if the arguments are
identical pointers.
* tree.h (is_attribute_p): Made inline.  Return a 'bool', not an
'int'.  Require the first argument to be in the form 'text', not
'__text__'.  Require the second argument to be an identifier.
(lookup_attribute): Made inline.  Require the first argument to be
in the form 'text', not '__text__'.
(private_is_attribute_p, private_lookup_attribute): New.
Updated comments.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175286 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/attribs.c
gcc/tree.c
gcc/tree.h

index 1dff45a..aa89cdd 100644 (file)
@@ -1,3 +1,32 @@
+2011-06-21  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * attribs.c (register_attribute): Added assert to check that all
+       attribute specs are registered with a name that is not empty and
+       does not start with '_'.
+       (decl_attributes): Avoid the lookup of the "naked" attribute spec
+       if the function has no attributes.
+       * tree.c (is_attribute_with_length_p): Removed.
+       (is_attribute_p): Removed.
+       (private_is_attribute_p): New.  
+       (private_lookup_attribute): New.
+       (lookup_attribute): Removed.
+       (lookup_ident_attribute): New.
+       (remove_attribute): Require the first argument to be in the form
+       'text', not '__text__'.  Updated asserts.
+       (merge_attributes): Use lookup_ident_attributes instead of
+       lookup_attribute.
+       (merge_dllimport_decl_attributes): Use remove_attribute.
+       (attribute_list_contained): Likewise.
+       (attribute_list_equal): Immediately return 1 if the arguments are
+       identical pointers.
+       * tree.h (is_attribute_p): Made inline.  Return a 'bool', not an
+       'int'.  Require the first argument to be in the form 'text', not
+       '__text__'.  Require the second argument to be an identifier.
+       (lookup_attribute): Made inline.  Require the first argument to be
+       in the form 'text', not '__text__'.
+       (private_is_attribute_p, private_lookup_attribute): New.
+       Updated comments.
+       
 2011-06-21  Andrew MacLeod  <amacleod@redhat.com>
 
        * builtins.c: Add sync_ or SYNC__ to builtin names.
index ce977d4..98a6310 100644 (file)
@@ -198,6 +198,11 @@ register_attribute (const struct attribute_spec *attr)
 
   str.str = attr->name;
   str.length = strlen (str.str);
+
+  /* Attribute names in the table must be in the form 'text' and not
+     in the form '__text__'.  */
+  gcc_assert (str.length > 0 && str.str[0] != '_');
+
   slot = htab_find_slot_with_hash (attribute_hash, &str,
                                   substring_hash (str.str, str.length),
                                   INSERT);
@@ -279,6 +284,7 @@ decl_attributes (tree *node, tree attributes, int flags)
   /* A "naked" function attribute implies "noinline" and "noclone" for
      those targets that support it.  */
   if (TREE_CODE (*node) == FUNCTION_DECL
+      && attributes
       && lookup_attribute_spec (get_identifier ("naked"))
       && lookup_attribute ("naked", attributes) != NULL)
     {
index 73126cf..d984ece 100644 (file)
@@ -5218,82 +5218,119 @@ struct simple_ipa_opt_pass pass_ipa_free_lang_data =
  }
 };
 
-/* Return nonzero if IDENT is a valid name for attribute ATTR,
-   or zero if not.
-
-   We try both `text' and `__text__', ATTR may be either one.  */
-/* ??? It might be a reasonable simplification to require ATTR to be only
-   `text'.  One might then also require attribute lists to be stored in
-   their canonicalized form.  */
-
-static int
-is_attribute_with_length_p (const char *attr, int attr_len, const_tree ident)
+/* The backbone of is_attribute_p().  ATTR_LEN is the string length of
+   ATTR_NAME.  Also used internally by remove_attribute().  */
+bool
+private_is_attribute_p (const char *attr_name, size_t attr_len, const_tree ident)
 {
-  int ident_len;
-  const char *p;
+  size_t ident_len = IDENTIFIER_LENGTH (ident);
 
-  if (TREE_CODE (ident) != IDENTIFIER_NODE)
-    return 0;
-
-  p = IDENTIFIER_POINTER (ident);
-  ident_len = IDENTIFIER_LENGTH (ident);
-
-  if (ident_len == attr_len
-      && strcmp (attr, p) == 0)
-    return 1;
-
-  /* If ATTR is `__text__', IDENT must be `text'; and vice versa.  */
-  if (attr[0] == '_')
+  if (ident_len == attr_len)
     {
-      gcc_assert (attr[1] == '_');
-      gcc_assert (attr[attr_len - 2] == '_');
-      gcc_assert (attr[attr_len - 1] == '_');
-      if (ident_len == attr_len - 4
-         && strncmp (attr + 2, p, attr_len - 4) == 0)
-       return 1;
+      if (strcmp (attr_name, IDENTIFIER_POINTER (ident)) == 0)
+       return true;
     }
-  else
+  else if (ident_len == attr_len + 4)
     {
-      if (ident_len == attr_len + 4
-         && p[0] == '_' && p[1] == '_'
+      /* There is the possibility that ATTR is 'text' and IDENT is
+        '__text__'.  */
+      const char *p = IDENTIFIER_POINTER (ident);      
+      if (p[0] == '_' && p[1] == '_'
          && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
-         && strncmp (attr, p + 2, attr_len) == 0)
-       return 1;
+         && strncmp (attr_name, p + 2, attr_len) == 0)
+       return true;
     }
 
-  return 0;
+  return false;
 }
 
-/* Return nonzero if IDENT is a valid name for attribute ATTR,
-   or zero if not.
+/* The backbone of lookup_attribute().  ATTR_LEN is the string length
+   of ATTR_NAME, and LIST is not NULL_TREE.  */
+tree
+private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
+{
+  while (list)
+    {
+      size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list));
 
-   We try both `text' and `__text__', ATTR may be either one.  */
+      if (ident_len == attr_len)
+       {
+         if (strcmp (attr_name, IDENTIFIER_POINTER (TREE_PURPOSE (list))) == 0)
+           break;
+       }
+      /* TODO: If we made sure that attributes were stored in the
+        canonical form without '__...__' (ie, as in 'text' as opposed
+        to '__text__') then we could avoid the following case.  */
+      else if (ident_len == attr_len + 4)
+       {
+         const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
+         if (p[0] == '_' && p[1] == '_'
+             && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
+             && strncmp (attr_name, p + 2, attr_len) == 0)
+           break;
+       }
+      list = TREE_CHAIN (list);
+    }
 
-int
-is_attribute_p (const char *attr, const_tree ident)
-{
-  return is_attribute_with_length_p (attr, strlen (attr), ident);
+  return list;
 }
 
-/* Given an attribute name and a list of attributes, return a pointer to the
-   attribute's list element if the attribute is part of the list, or NULL_TREE
-   if not found.  If the attribute appears more than once, this only
-   returns the first occurrence; the TREE_CHAIN of the return value should
-   be passed back in if further occurrences are wanted.  */
+/* A variant of lookup_attribute() that can be used with an identifier
+   as the first argument, and where the identifier can be either
+   'text' or '__text__'.
 
-tree
-lookup_attribute (const char *attr_name, tree list)
+   Given an attribute ATTR_IDENTIFIER, and a list of attributes LIST,
+   return a pointer to the attribute's list element if the attribute
+   is part of the list, or NULL_TREE if not found.  If the attribute
+   appears more than once, this only returns the first occurrence; the
+   TREE_CHAIN of the return value should be passed back in if further
+   occurrences are wanted.  ATTR_IDENTIFIER must be an identifier but
+   can be in the form 'text' or '__text__'.  */
+static tree
+lookup_ident_attribute (tree attr_identifier, tree list)
 {
-  tree l;
-  size_t attr_len = strlen (attr_name);
+  gcc_checking_assert (TREE_CODE (attr_identifier) == IDENTIFIER_NODE);
 
-  for (l = list; l; l = TREE_CHAIN (l))
+  while (list)
     {
-      gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
-      if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
-       return l;
+      gcc_checking_assert (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE);
+
+      /* Identifiers can be compared directly for equality.  */
+      if (attr_identifier == TREE_PURPOSE (list))
+       break;
+
+      /* If they are not equal, they may still be one in the form
+        'text' while the other one is in the form '__text__'.  TODO:
+        If we were storing attributes in normalized 'text' form, then
+        this could all go away and we could take full advantage of
+        the fact that we're comparing identifiers. :-)  */
+      {
+       size_t attr_len = IDENTIFIER_LENGTH (attr_identifier);
+       size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list));
+
+       if (ident_len == attr_len + 4)
+         {
+           const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
+           const char *q = IDENTIFIER_POINTER (attr_identifier);
+           if (p[0] == '_' && p[1] == '_'
+               && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
+               && strncmp (q, p + 2, attr_len) == 0)
+             break;
+         }
+       else if (ident_len + 4 == attr_len)
+         {
+           const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
+           const char *q = IDENTIFIER_POINTER (attr_identifier);
+           if (q[0] == '_' && q[1] == '_'
+               && q[attr_len - 2] == '_' && q[attr_len - 1] == '_'
+               && strncmp (q + 2, p, ident_len) == 0)
+             break;
+         }
+      }
+      list = TREE_CHAIN (list);
     }
-  return NULL_TREE;
+
+  return list;
 }
 
 /* Remove any instances of attribute ATTR_NAME in LIST and return the
@@ -5305,11 +5342,14 @@ remove_attribute (const char *attr_name, tree list)
   tree *p;
   size_t attr_len = strlen (attr_name);
 
+  gcc_checking_assert (attr_name[0] != '_');
+
   for (p = &list; *p; )
     {
       tree l = *p;
-      gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
-      if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
+      /* TODO: If we were storing attributes in normalized form, here
+        we could use a simple strcmp().  */
+      if (private_is_attribute_p (attr_name, attr_len, TREE_PURPOSE (l)))
        *p = TREE_CHAIN (l);
       else
        p = &TREE_CHAIN (l);
@@ -5346,11 +5386,9 @@ merge_attributes (tree a1, tree a2)
          for (; a2 != 0; a2 = TREE_CHAIN (a2))
            {
              tree a;
-             for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
-                                        attributes);
+             for (a = lookup_ident_attribute (TREE_PURPOSE (a2), attributes);
                   a != NULL_TREE && !attribute_value_equal (a, a2);
-                  a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
-                                        TREE_CHAIN (a)))
+                  a = lookup_ident_attribute (TREE_PURPOSE (a2), TREE_CHAIN (a)))
                ;
              if (a == NULL_TREE)
                {
@@ -5449,24 +5487,7 @@ merge_dllimport_decl_attributes (tree old, tree new_tree)
   a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
 
   if (delete_dllimport_p)
-    {
-      tree prev, t;
-      const size_t attr_len = strlen ("dllimport");
-
-      /* Scan the list for dllimport and delete it.  */
-      for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
-       {
-         if (is_attribute_with_length_p ("dllimport", attr_len,
-                                         TREE_PURPOSE (t)))
-           {
-             if (prev == NULL_TREE)
-               a = TREE_CHAIN (a);
-             else
-               TREE_CHAIN (prev) = TREE_CHAIN (t);
-             break;
-           }
-       }
-    }
+    a = remove_attribute ("dllimport", a);
 
   return a;
 }
@@ -6254,6 +6275,9 @@ attribute_hash_list (const_tree list, hashval_t hashcode)
 int
 attribute_list_equal (const_tree l1, const_tree l2)
 {
+  if (l1 == l2)
+    return 1;
+
   return attribute_list_contained (l1, l2)
         && attribute_list_contained (l2, l1);
 }
@@ -6292,11 +6316,9 @@ attribute_list_contained (const_tree l1, const_tree l2)
       /* This CONST_CAST is okay because lookup_attribute does not
         modify its argument and the return value is assigned to a
         const_tree.  */
-      for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-                                   CONST_CAST_TREE(l1));
+      for (attr = lookup_ident_attribute (TREE_PURPOSE (t2), CONST_CAST_TREE(l1));
           attr != NULL_TREE && !attribute_value_equal (t2, attr);
-          attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-                                   TREE_CHAIN (attr)))
+          attr = lookup_ident_attribute (TREE_PURPOSE (t2), TREE_CHAIN (attr)))
        ;
 
       if (attr == NULL_TREE)
index f55574d..3840fed 100644 (file)
@@ -4498,18 +4498,54 @@ enum attribute_flags
 extern tree merge_decl_attributes (tree, tree);
 extern tree merge_type_attributes (tree, tree);
 
-/* Given a tree node and a string, return nonzero if the tree node is
-   a valid attribute name for the string.  */
+/* This function is a private implementation detail of lookup_attribute()
+   and you should never call it directly.  */
+extern tree private_lookup_attribute (const char *, size_t, tree);
+
+/* Given an attribute name ATTR_NAME and a list of attributes LIST,
+   return a pointer to the attribute's list element if the attribute
+   is part of the list, or NULL_TREE if not found.  If the attribute
+   appears more than once, this only returns the first occurrence; the
+   TREE_CHAIN of the return value should be passed back in if further
+   occurrences are wanted.  ATTR_NAME must be in the form 'text' (not
+   '__text__').  */
 
-extern int is_attribute_p (const char *, const_tree);
+static inline tree
+lookup_attribute (const char *attr_name, tree list)
+{
+  gcc_checking_assert (attr_name[0] != '_');  
+  /* In most cases, list is NULL_TREE.  */
+  if (list == NULL_TREE)
+    return NULL_TREE;
+  else
+    /* Do the strlen() before calling the out-of-line implementation.
+       In most cases attr_name is a string constant, and the compiler
+       will optimize the strlen() away.  */
+    return private_lookup_attribute (attr_name, strlen (attr_name), list);
+}
 
-/* Given an attribute name and a list of attributes, return the list element
-   of the attribute or NULL_TREE if not found.  */
+/* This function is a private implementation detail of
+   is_attribute_p() and you should never call it directly.  */
+extern bool private_is_attribute_p (const char *, size_t, const_tree);
 
-extern tree lookup_attribute (const char *, tree);
+/* Given an identifier node IDENT and a string ATTR_NAME, return true
+   if the identifier node is a valid attribute name for the string.
+   ATTR_NAME must be in the form 'text' (not '__text__').  IDENT could
+   be the identifier for 'text' or for '__text__'.  */
+
+static inline bool
+is_attribute_p (const char *attr_name, const_tree ident)
+{
+  gcc_checking_assert (attr_name[0] != '_');
+  /* Do the strlen() before calling the out-of-line implementation.
+     In most cases attr_name is a string constant, and the compiler
+     will optimize the strlen() away.  */
+  return private_is_attribute_p (attr_name, strlen (attr_name), ident);
+}
 
 /* Remove any instances of attribute ATTR_NAME in LIST and return the
-   modified list.  */
+   modified list.  ATTR_NAME must be in the form 'text' (not
+   '__text__').  */
 
 extern tree remove_attribute (const char *, tree);