Commit 70e41a6a by Nicola Pero Committed by Nicola Pero

In gcc/: 2011-06-21 Nicola Pero <nicola.pero@meta-innovation.com>

In gcc/:
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.

From-SVN: r175286
parent 637c11bd
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.
......
......@@ -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)
{
......
......@@ -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)
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment