Commit 2a3c15b5 by Doug Evans

(attribute_hash_list): New function.

(build_type_attribute_variant): Call it.
(valid_machine_attribute): Handle attributes with arguments.
(is_attribute_p): New function.
(lookup_attribute): New function.
(attribute_in_list): Deleted.
(attribute_list_contained): Check TREE_PURPOSE and TREE_VALUE.

From-SVN: r9520
parent 9c130398
......@@ -1645,7 +1645,7 @@ really_constant_p (exp)
}
/* Return first list element whose TREE_VALUE is ELEM.
Return 0 if ELEM is not it LIST. */
Return 0 if ELEM is not in LIST. */
tree
value_member (elem, list)
......@@ -1661,7 +1661,7 @@ value_member (elem, list)
}
/* Return first list element whose TREE_PURPOSE is ELEM.
Return 0 if ELEM is not it LIST. */
Return 0 if ELEM is not in LIST. */
tree
purpose_member (elem, list)
......@@ -1677,7 +1677,7 @@ purpose_member (elem, list)
}
/* Return first list element whose BINFO_TYPE is ELEM.
Return 0 if ELEM is not it LIST. */
Return 0 if ELEM is not in LIST. */
tree
binfo_member (elem, list)
......@@ -1710,6 +1710,9 @@ chain_member (elem, chain)
/* Return nonzero if ELEM is equal to TREE_VALUE (CHAIN) for any piece of
chain CHAIN. */
/* ??? This function was added for machine specific attributes but is no
longer used. It could be deleted if we could confirm all front ends
don't use it. */
int
chain_member_value (elem, chain)
......@@ -1727,12 +1730,14 @@ chain_member_value (elem, chain)
/* Return nonzero if ELEM is equal to TREE_PURPOSE (CHAIN)
for any piece of chain CHAIN. */
/* ??? This function was added for machine specific attributes but is no
longer used. It could be deleted if we could confirm all front ends
don't use it. */
int
chain_member_purpose (elem, chain)
tree elem, chain;
{
while (chain)
{
if (elem == TREE_PURPOSE (chain))
......@@ -2896,7 +2901,7 @@ build_type_attribute_variant (ttype, attribute)
hashcode = TYPE_HASH (TREE_CODE (ntype))
+ TYPE_HASH (TREE_TYPE (ntype))
+ type_hash_list (attribute);
+ attribute_hash_list (attribute);
switch (TREE_CODE (ntype))
{
......@@ -2936,20 +2941,25 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
tree decl_attr_list = decl != 0 ? DECL_MACHINE_ATTRIBUTES (decl) : 0;
tree type_attr_list = TYPE_ATTRIBUTES (type);
/* For now, we don't support args. */
if (attr_args != 0)
return 0;
if (TREE_CODE (attr_name) != IDENTIFIER_NODE)
abort ();
#ifdef VALID_MACHINE_DECL_ATTRIBUTE
if (decl != 0
&& VALID_MACHINE_DECL_ATTRIBUTE (decl, decl_attr_list, attr_name))
&& VALID_MACHINE_DECL_ATTRIBUTE (decl, decl_attr_list, attr_name, attr_args))
{
if (! attribute_in_list (attr_name, decl_attr_list))
{
decl_attr_list = tree_cons (NULL_TREE, attr_name, decl_attr_list);
tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
decl_attr_list);
/* Declarations are unique, build_decl_attribute_variant modifies
the existing decl in situ. */
if (attr != NULL_TREE)
{
/* Override existing arguments. Declarations are unique so we can
modify this in place. */
TREE_VALUE (attr) = attr_args;
}
else
{
decl_attr_list = tree_cons (attr_name, attr_args, decl_attr_list);
decl = build_decl_attribute_variant (decl, decl_attr_list);
}
......@@ -2958,11 +2968,22 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
#endif
#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name))
if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name, attr_args))
{
if (! attribute_in_list (attr_name, type_attr_list))
tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
type_attr_list);
if (attr != NULL_TREE)
{
type_attr_list = tree_cons (NULL_TREE, attr_name, type_attr_list);
/* Override existing arguments.
??? This currently works since attribute arguments are not
included in `attribute_hash_list'. Something more complicated
may be needed in the future. */
TREE_VALUE (attr) = attr_args;
}
else
{
type_attr_list = tree_cons (attr_name, attr_args, type_attr_list);
type = build_type_attribute_variant (type, type_attr_list);
}
if (decl != 0)
......@@ -2973,6 +2994,77 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
return valid;
}
/* Return non-zero 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. */
int
is_attribute_p (attr, ident)
char *attr;
tree ident;
{
int ident_len, attr_len;
char *p;
if (TREE_CODE (ident) != IDENTIFIER_NODE)
return 0;
if (strcmp (attr, IDENTIFIER_POINTER (ident)) == 0)
return 1;
p = IDENTIFIER_POINTER (ident);
ident_len = strlen (p);
attr_len = strlen (attr);
/* If ATTR is `__text__', IDENT must be `text'; and vice versa. */
if (attr[0] == '_')
{
if (attr[1] != '_'
|| attr[attr_len - 2] != '_'
|| attr[attr_len - 1] != '_')
abort ();
if (ident_len == attr_len - 4
&& strncmp (attr + 2, p, attr_len - 4) == 0)
return 1;
}
else
{
if (ident_len == attr_len + 4
&& p[0] == '_' && p[1] == '_'
&& p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
&& strncmp (attr, p + 2, attr_len) == 0)
return 1;
}
return 0;
}
/* 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. */
tree
lookup_attribute (attr_name, list)
char *attr_name;
tree list;
{
tree l;
for (l = list; l; l = TREE_CHAIN (l))
{
if (TREE_CODE (TREE_PURPOSE (l)) != IDENTIFIER_NODE)
abort ();
if (is_attribute_p (attr_name, TREE_PURPOSE (l)))
return l;
}
return NULL_TREE;
}
/* Return a type like TYPE except that its TYPE_READONLY is CONSTP
and its TYPE_VOLATILE is VOLATILEP.
......@@ -3196,39 +3288,20 @@ type_hash_canon (hashcode, type)
return type;
}
/* Given an attribute and a list of attributes, return true if the attribute
is part of the list. */
/* Compute a hash code for a list of attributes (chain of TREE_LIST nodes
with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots),
by adding the hash codes of the individual attributes. */
int
attribute_in_list (attribute, list)
tree attribute, list;
attribute_hash_list (list)
tree list;
{
register tree purpose, chain;
/* Perform a quick check. */
if (value_member (attribute, list))
return 1;
/* If it's not a TREE_LIST, we should have had a match by now. */
if (TREE_CODE (attribute) != TREE_LIST)
return 0;
purpose = TREE_PURPOSE (attribute);
chain = TREE_CHAIN (attribute);
for (; list; list = TREE_CHAIN (list))
{
register tree value;
value = TREE_VALUE (list);
if (TREE_CODE (value) == TREE_LIST
&& TREE_PURPOSE (value) == purpose
&& simple_cst_equal (TREE_CHAIN (value), chain) == 1)
return 1;
}
return 0;
register int hashcode;
register tree tail;
for (hashcode = 0, tail = list; tail; tail = TREE_CHAIN (tail))
/* ??? Do we want to add in TREE_VALUE too? */
hashcode += TYPE_HASH (TREE_PURPOSE (tail));
return hashcode;
}
/* Given two lists of attributes, return true if list l2 is
......@@ -3242,8 +3315,13 @@ attribute_list_equal (l1, l2)
&& attribute_list_contained (l2, l1);
}
/* Given two lists of attributes, return true if list l2 is
completely contained within l1. */
/* Given two lists of attributes, return true if list L2 is
completely contained within L1. */
/* ??? This would be faster if attribute names were stored in a canonicalized
form. Otherwise, if L1 uses `foo' and L2 uses `__foo__', the long method
must be used to show these elements are equivalent (which they are). */
/* ??? It's not clear that attributes with arguments will always be handled
correctly. */
int
attribute_list_contained (l1, l2)
......@@ -3255,9 +3333,10 @@ attribute_list_contained (l1, l2)
if (l1 == l2)
return 1;
/* Then check the obvious, maybe the lists are similar. */
/* Maybe the lists are similar. */
for (t1 = l1, t2 = l2;
t1 && t2
&& TREE_PURPOSE (t1) == TREE_PURPOSE (t2)
&& TREE_VALUE (t1) == TREE_VALUE (t2);
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2));
......@@ -3266,8 +3345,14 @@ attribute_list_contained (l1, l2)
return 1;
for (; t2; t2 = TREE_CHAIN (t2))
if (! attribute_in_list (TREE_VALUE (t2), l1))
{
tree attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
if (attr == NULL_TREE)
return 0;
if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1)
return 0;
}
return 1;
}
......
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