aboutsummaryrefslogtreecommitdiff
path: root/gcc/attribs.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2021-04-15 11:37:38 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2021-04-15 11:37:38 +0100
commita3317f7b3c02907a122f89879e5b6e90c386e64d (patch)
treeff690fd76bbd0d8470dc70e22180cb4bcef03ea4 /gcc/attribs.c
parentb5f644a98b3f3543d3a8d2dfea7785c22879013f (diff)
downloadgcc-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.c54
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.