From 2a3c15b553af7e9a5c3ae07c54c88d3ce0ad3332 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Fri, 28 Apr 1995 01:08:30 +0000 Subject: [PATCH] (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 --- gcc/tree.c | 187 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 136 insertions(+), 51 deletions(-) diff --git a/gcc/tree.c b/gcc/tree.c index 1858e3fcf41..fcbfd5373c7 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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; } -- 2.30.2