From 70e41a6a27a6aad0abbe5598497b4b17ef3feb48 Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Wed, 22 Jun 2011 09:52:55 +0000 Subject: In gcc/: 2011-06-21 Nicola Pero In gcc/: 2011-06-21 Nicola Pero * 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. From-SVN: r175286 --- gcc/tree.c | 192 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 107 insertions(+), 85 deletions(-) (limited to 'gcc/tree.c') diff --git a/gcc/tree.c b/gcc/tree.c index 73126cf..d984ece 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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) -- cgit v1.1