diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2021-04-15 11:37:38 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2021-04-15 11:37:38 +0100 |
commit | a3317f7b3c02907a122f89879e5b6e90c386e64d (patch) | |
tree | ff690fd76bbd0d8470dc70e22180cb4bcef03ea4 /gcc/attribs.c | |
parent | b5f644a98b3f3543d3a8d2dfea7785c22879013f (diff) | |
download | gcc-a3317f7b3c02907a122f89879e5b6e90c386e64d.zip gcc-a3317f7b3c02907a122f89879e5b6e90c386e64d.tar.gz gcc-a3317f7b3c02907a122f89879e5b6e90c386e64d.tar.bz2 |
c: Don't drop vector attributes that affect type identity [PR98852]
<arm_neon.h> types are distinct from GNU vector types in at least
their mangling. However, there used to be nothing explicit in the
VECTOR_TYPE itself to indicate the difference: we simply treated them
as distinct TYPE_MAIN_VARIANTs. This caused problems like the ones
reported in PR95726.
The fix for that PR was to add type attributes to the <arm_neon.h>
types, in order to maintain the distinction between them and GNU
vectors. However, this in turn caused PR98852, where c_common_type
would unconditionally drop the attributes on the source types.
This meant that:
<arm_neon.h> vector + <arm_neon.h> vector
had a GNU vector type rather than an <arm_neon.h> vector type.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96377#c2 for
Jakub's analysis of the history of this c_common_type code.
TBH I'm not sure which case the build_type_attribute_variant
code is handling, but I think we should at least avoid dropping
attributes that affect type identity.
I've tried to audit the C and target-specific attributes to look
for other types that might be affected by this, but I couldn't
see any. We are only dealing with:
gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
|| code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
|| code1 == INTEGER_TYPE);
which excludes most affects_type_identity attributes. The closest
was s390_vector_bool, but the handler for that attribute changes
the type node and drops the attribute itself (*no_add_attrs = true).
I put the main list handling into a separate function
(remove_attributes_matching) because a later patch will need it
for something else.
gcc/
PR c/98852
* attribs.h (affects_type_identity_attributes): Declare.
* attribs.c (remove_attributes_matching): New function.
(affects_type_identity_attributes): Likewise.
gcc/c/
PR c/98852
* c-typeck.c (c_common_type): Do not drop attributes that
affect type identity.
gcc/testsuite/
PR c/98852
* gcc.target/aarch64/advsimd-intrinsics/pr98852.c: New test.
Diffstat (limited to 'gcc/attribs.c')
-rw-r--r-- | gcc/attribs.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/gcc/attribs.c b/gcc/attribs.c index 16c6b12..2fb2954 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -1366,6 +1366,60 @@ comp_type_attributes (const_tree type1, const_tree type2) return targetm.comp_type_attributes (type1, type2); } +/* PREDICATE acts as a function of type: + + (const_tree attr, const attribute_spec *as) -> bool + + where ATTR is an attribute and AS is its possibly-null specification. + Return a list of every attribute in attribute list ATTRS for which + PREDICATE is true. Return ATTRS itself if PREDICATE returns true + for every attribute. */ + +template<typename Predicate> +tree +remove_attributes_matching (tree attrs, Predicate predicate) +{ + tree new_attrs = NULL_TREE; + tree *ptr = &new_attrs; + const_tree start = attrs; + for (const_tree attr = attrs; attr; attr = TREE_CHAIN (attr)) + { + tree name = get_attribute_name (attr); + const attribute_spec *as = lookup_attribute_spec (name); + const_tree end; + if (!predicate (attr, as)) + end = attr; + else if (start == attrs) + continue; + else + end = TREE_CHAIN (attr); + + for (; start != end; start = TREE_CHAIN (start)) + { + *ptr = tree_cons (TREE_PURPOSE (start), + TREE_VALUE (start), NULL_TREE); + TREE_CHAIN (*ptr) = NULL_TREE; + ptr = &TREE_CHAIN (*ptr); + } + start = TREE_CHAIN (attr); + } + gcc_assert (!start || start == attrs); + return start ? attrs : new_attrs; +} + +/* If VALUE is true, return the subset of ATTRS that affect type identity, + otherwise return the subset of ATTRS that don't affect type identity. */ + +tree +affects_type_identity_attributes (tree attrs, bool value) +{ + auto predicate = [value](const_tree, const attribute_spec *as) -> bool + { + return bool (as && as->affects_type_identity) == value; + }; + return remove_attributes_matching (attrs, predicate); +} + /* Return a type like TTYPE except that its TYPE_ATTRIBUTE is ATTRIBUTE. |