aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2020-05-14 12:20:32 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2020-05-14 12:20:32 +0100
commit2c814af65ef9f146519cba657890a4fd93c5be38 (patch)
tree310ef15bc44395d6c0d8b8e6bb473338ae6074b0
parent0d1ccfd0cc2e1add15929c43e6c7472336d33e65 (diff)
downloadgcc-2c814af65ef9f146519cba657890a4fd93c5be38.zip
gcc-2c814af65ef9f146519cba657890a4fd93c5be38.tar.gz
gcc-2c814af65ef9f146519cba657890a4fd93c5be38.tar.bz2
aarch64: Fix arm_sve_vector_bits on typedefs [PR95105]
Compiling this testcase with -march=armv8.2-a+sve -msve-vector-bits=512: ---------------------------------------------------------- typedef __SVFloat32_t foo; typedef foo bar __attribute__((arm_sve_vector_bits(512))); template<typename T> struct s { T x; }; extern s<bar> a; bar &b = a.x; ---------------------------------------------------------- gave the bogus error: cannot bind non-const lvalue reference of type ‘bar&’ to an rvalue of type ‘bar’ The testcase works if the attribute is applied directly to __SVFloat32_t instead of via foo. This shows a more general problem with the way that we were handling the arm_sve_vector_bits attribute: we started by building a distinct copy of the type to which the attribute was applied, instead of starting with its main variant. This new type then became its own main variant, meaning that the relationship between types that have the attribute could be different from the relationship between types that don't have the attribute. This patch instead copies the main variant of the original type and then reapplies all the differences. 2020-05-14 Richard Sandiford <richard.sandiford@arm.com> gcc/ PR target/95105 * config/aarch64/aarch64-sve-builtins.cc (handle_arm_sve_vector_bits_attribute): Create a copy of the original type's TYPE_MAIN_VARIANT, then reapply all the differences between the original type and its main variant. gcc/testsuite/ PR target/95105 * gcc.target/aarch64/sve/acle/general/attributes_8.c: New test. * g++.target/aarch64/sve/acle/general-c++/attributes_1.C: Likewise.
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc35
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/attributes_1.C122
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_8.c101
5 files changed, 262 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e0a50f1..125f7c7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2020-05-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/95105
+ * config/aarch64/aarch64-sve-builtins.cc
+ (handle_arm_sve_vector_bits_attribute): Create a copy of the
+ original type's TYPE_MAIN_VARIANT, then reapply all the differences
+ between the original type and its main variant.
+
2020-05-14 Richard Biener <rguenther@suse.de>
PR middle-end/95118
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 8511382..bdb04e8 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -3676,24 +3676,39 @@ handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int,
svbool_t and its fixed-length variants. Using a type variant
avoids that but means that we treat some ambiguous combinations
as valid. */
+ tree new_type;
+ tree base_type = TYPE_MAIN_VARIANT (type);
if (lang_GNU_C () && VECTOR_BOOLEAN_TYPE_P (type))
- type = build_variant_type_copy (type);
+ new_type = build_variant_type_copy (base_type);
else
- type = build_distinct_type_copy (type);
+ new_type = build_distinct_type_copy (base_type);
+
+ /* Allow the GNU vector extensions to be applied to vectors.
+ The extensions aren't yet defined for packed predicates,
+ so continue to treat them as abstract entities for now. */
+ if (!VECTOR_BOOLEAN_TYPE_P (new_type))
+ TYPE_INDIVISIBLE_P (new_type) = 0;
/* The new type is a normal sized type; it doesn't have the same
restrictions as sizeless types. */
- TYPE_ATTRIBUTES (type)
+ TYPE_ATTRIBUTES (new_type)
= remove_attribute ("SVE sizeless type",
- copy_list (TYPE_ATTRIBUTES (type)));
+ copy_list (TYPE_ATTRIBUTES (new_type)));
- /* Allow the GNU vector extensions to be applied to vectors.
- The extensions aren't yet defined for packed predicates,
- so continue to treat them as abstract entities for now. */
- if (!VECTOR_BOOLEAN_TYPE_P (type))
- TYPE_INDIVISIBLE_P (type) = 0;
+ /* Apply the relevant attributes, qualifiers and alignment of TYPE,
+ if they differ from the original (sizeless) BASE_TYPE. */
+ if (TYPE_ATTRIBUTES (base_type) != TYPE_ATTRIBUTES (type)
+ || TYPE_QUALS (base_type) != TYPE_QUALS (type))
+ {
+ tree attrs = remove_attribute ("SVE sizeless type",
+ copy_list (TYPE_ATTRIBUTES (type)));
+ new_type = build_type_attribute_qual_variant (new_type, attrs,
+ TYPE_QUALS (type));
+ }
+ if (TYPE_ALIGN (base_type) != TYPE_ALIGN (type))
+ new_type = build_aligned_type (new_type, TYPE_ALIGN (type));
- *node = type;
+ *node = new_type;
return NULL_TREE;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ce278ed..5163470 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/95105
+ * gcc.target/aarch64/sve/acle/general/attributes_8.c: New test.
+ * g++.target/aarch64/sve/acle/general-c++/attributes_1.C: Likewise.
+
2020-05-14 Richard Biener <rguenther@suse.de>
PR testsuite/94703
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/attributes_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/attributes_1.C
new file mode 100644
index 0000000..befd494
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/attributes_1.C
@@ -0,0 +1,122 @@
+/* { dg-options "-msve-vector-bits=256 -W -Wall" } */
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS
+#define FIXED_ATTR __attribute__ ((arm_sve_vector_bits (N)))
+
+template<typename T> struct foo { T var; };
+
+typedef svint8_t var1;
+typedef __SVInt8_t var2;
+
+typedef const var1 const_var1;
+typedef const var2 const_var2;
+
+typedef svint8_t fixed1 FIXED_ATTR;
+typedef svint8_t fixed1_alias FIXED_ATTR;
+typedef __SVInt8_t fixed2 FIXED_ATTR;
+
+typedef const_var1 const_fixed1 FIXED_ATTR;
+typedef const var1 const_fixed1_alias FIXED_ATTR;
+typedef const_var2 const_fixed2 FIXED_ATTR;
+
+extern fixed1 extern1;
+extern fixed1_alias extern1_alias;
+extern fixed2 extern2;
+
+extern foo<fixed1> extern1_foo;
+extern foo<fixed1_alias> extern1_alias_foo;
+extern foo<fixed2> extern2_foo;
+
+extern const_fixed1 const_extern1;
+extern const_fixed1_alias const_extern1_alias;
+extern const_fixed2 const_extern2;
+
+extern foo<const_fixed1> const_extern1_foo;
+extern foo<const_fixed1_alias> const_extern1_alias_foo;
+extern foo<const_fixed2> const_extern2_foo;
+
+fixed1 &ref1a = extern1;
+fixed1_alias &ref1b = extern1;
+fixed2 &ref1c = extern1;
+
+fixed1 &ref2a = extern1_alias;
+fixed1_alias &ref2b = extern1_alias;
+fixed2 &ref2c = extern1_alias;
+
+fixed1 &ref3a = extern2;
+fixed1_alias &ref3b = extern2;
+fixed2 &ref3c = extern2;
+
+fixed1 &ref1a_foo = extern1_foo.var;
+fixed1_alias &ref1b_foo = extern1_foo.var;
+fixed2 &ref1c_foo = extern1_foo.var;
+
+fixed1 &ref2a_foo = extern1_alias_foo.var;
+fixed1_alias &ref2b_foo = extern1_alias_foo.var;
+fixed2 &ref2c_foo = extern1_alias_foo.var;
+
+fixed1 &ref3a_foo = extern2_foo.var;
+fixed1_alias &ref3b_foo = extern2_foo.var;
+fixed2 &ref3c_foo = extern2_foo.var;
+
+fixed1 &ref4a = const_extern1; // { dg-error {discards qualifiers} }
+fixed1_alias &ref4b = const_extern1; // { dg-error {discards qualifiers} }
+fixed2 &ref4c = const_extern1; // { dg-error {discards qualifiers} }
+
+fixed1 &ref4a_foo = const_extern1_foo.var; // { dg-error {discards qualifiers} }
+fixed1_alias &ref4b_foo = const_extern1_foo.var; // { dg-error {discards qualifiers} }
+fixed2 &ref4c_foo = const_extern1_foo.var; // { dg-error {discards qualifiers} }
+
+const fixed1 &ref5a = const_extern2;
+const fixed1_alias &ref5b = const_extern2;
+const fixed2 &ref5c = const_extern2;
+
+const_fixed1 &const_ref1a = extern1;
+const_fixed1_alias &const_ref1b = extern1;
+const_fixed2 &const_ref1c = extern1;
+
+const_fixed1 &const_ref2a = extern1_alias;
+const_fixed1_alias &const_ref2b = extern1_alias;
+const_fixed2 &const_ref2c = extern1_alias;
+
+const_fixed1 &const_ref3a = extern2;
+const_fixed1_alias &const_ref3b = extern2;
+const_fixed2 &const_ref3c = extern2;
+
+const_fixed1 &const_ref1a_foo = extern1_foo.var;
+const_fixed1_alias &const_ref1b_foo = extern1_foo.var;
+const_fixed2 &const_ref1c_foo = extern1_foo.var;
+
+const_fixed1 &const_ref2a_foo = extern1_alias_foo.var;
+const_fixed1_alias &const_ref2b_foo = extern1_alias_foo.var;
+const_fixed2 &const_ref2c_foo = extern1_alias_foo.var;
+
+const_fixed1 &const_ref3a_foo = extern2_foo.var;
+const_fixed1_alias &const_ref3b_foo = extern2_foo.var;
+const_fixed2 &const_ref3c_foo = extern2_foo.var;
+
+const_fixed1 &const_ref4a = const_extern1;
+const_fixed1_alias &const_ref4b = const_extern1;
+const_fixed2 &const_ref4c = const_extern1;
+
+const_fixed1 &const_ref5a = const_extern1_alias;
+const_fixed1_alias &const_ref5b = const_extern1_alias;
+const_fixed2 &const_ref5c = const_extern1_alias;
+
+const_fixed1 &const_ref6a = const_extern2;
+const_fixed1_alias &const_ref6b = const_extern2;
+const_fixed2 &const_ref6c = const_extern2;
+
+const_fixed1 &const_ref4a_foo = const_extern1_foo.var;
+const_fixed1_alias &const_ref4b_foo = const_extern1_foo.var;
+const_fixed2 &const_ref4c_foo = const_extern1_foo.var;
+
+const_fixed1 &const_ref5a_foo = const_extern1_alias_foo.var;
+const_fixed1_alias &const_ref5b_foo = const_extern1_alias_foo.var;
+const_fixed2 &const_ref5c_foo = const_extern1_alias_foo.var;
+
+const_fixed1 &const_ref6a_foo = const_extern2_foo.var;
+const_fixed1_alias &const_ref6b_foo = const_extern2_foo.var;
+const_fixed2 &const_ref6c_foo = const_extern2_foo.var;
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_8.c
new file mode 100644
index 0000000..f302927
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/attributes_8.c
@@ -0,0 +1,101 @@
+/* { dg-options "-msve-vector-bits=256 -W -Wall" } */
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS
+#define FIXED_ATTR __attribute__ ((arm_sve_vector_bits (N)))
+#define ALIGNED_ATTR __attribute__((aligned(N / 8)))
+
+typedef svint8_t var1;
+typedef __SVInt8_t var2;
+
+typedef const var1 const_var1;
+typedef const var2 const_var2;
+
+typedef var1 aligned_var1 ALIGNED_ATTR;
+typedef var2 aligned_var2 ALIGNED_ATTR;
+
+typedef var1 fixed1 FIXED_ATTR;
+typedef var1 fixed1_alias FIXED_ATTR;
+typedef var2 fixed2 FIXED_ATTR;
+
+typedef const_var1 const_fixed1 FIXED_ATTR;
+typedef const var1 const_fixed1_alias FIXED_ATTR;
+typedef const_var2 const_fixed2 FIXED_ATTR;
+
+typedef aligned_var1 aligned_fixed1 FIXED_ATTR;
+typedef var1 aligned_fixed1_alias FIXED_ATTR ALIGNED_ATTR;
+typedef aligned_var2 aligned_fixed2 FIXED_ATTR;
+
+extern fixed1 extern1;
+extern fixed1_alias extern1_alias;
+extern fixed2 extern2;
+
+extern const_fixed1 const_extern1;
+extern const_fixed1_alias const_extern1_alias;
+extern const_fixed2 const_extern2;
+
+fixed1 *ptr1a = &extern1;
+fixed1_alias *ptr1b = &extern1;
+fixed2 *ptr1c = &extern1;
+
+fixed1 *ptr2a = &extern1_alias;
+fixed1_alias *ptr2b = &extern1_alias;
+fixed2 *ptr2c = &extern1_alias;
+
+fixed1 *ptr3a = &extern2;
+fixed1_alias *ptr3b = &extern2;
+fixed2 *ptr3c = &extern2;
+
+fixed1 *ptr4a = &const_extern1; // { dg-error {invalid conversion} "c++" { target c++ } }
+ // { dg-warning {discards 'const' qualifier} "c" { target c } .-1 }
+fixed1_alias *ptr4b = &const_extern1; // { dg-error {invalid conversion} "c++" { target c++ } }
+ // { dg-warning {discards 'const' qualifier} "c" { target c } .-1 }
+fixed2 *ptr4c = &const_extern1; // { dg-error {invalid conversion} "c++" { target c++ } }
+ // { dg-warning {discards 'const' qualifier} "c" { target c } .-1 }
+
+const fixed1 *ptr5a = &const_extern2;
+const fixed1_alias *ptr5b = &const_extern2;
+const fixed2 *ptr5c = &const_extern2;
+
+const_fixed1 *const_ptr1a = &extern1;
+const_fixed1_alias *const_ptr1b = &extern1;
+const_fixed2 *const_ptr1c = &extern1;
+
+const_fixed1 *const_ptr2a = &extern1_alias;
+const_fixed1_alias *const_ptr2b = &extern1_alias;
+const_fixed2 *const_ptr2c = &extern1_alias;
+
+const_fixed1 *const_ptr3a = &extern2;
+const_fixed1_alias *const_ptr3b = &extern2;
+const_fixed2 *const_ptr3c = &extern2;
+
+const_fixed1 *const_ptr4a = &const_extern1;
+const_fixed1_alias *const_ptr4b = &const_extern1;
+const_fixed2 *const_ptr4c = &const_extern1;
+
+const_fixed1 *const_ptr5a = &const_extern1_alias;
+const_fixed1_alias *const_ptr5b = &const_extern1_alias;
+const_fixed2 *const_ptr5c = &const_extern1_alias;
+
+const_fixed1 *const_ptr6a = &const_extern2;
+const_fixed1_alias *const_ptr6b = &const_extern2;
+const_fixed2 *const_ptr6c = &const_extern2;
+
+struct normal1 { int x; fixed1 y; };
+struct normal1_alias { int x; fixed1_alias y; };
+struct normal2 { int x; fixed2 y; };
+
+struct aligned1 { int x; aligned_fixed1 y; };
+struct aligned1_alias { int x; aligned_fixed1_alias y; };
+struct aligned2 { int x; aligned_fixed2 y; };
+
+#define ASSERT(NAME, TEST) typedef int NAME[(TEST) ? 1 : -1]
+
+ASSERT (check_normal1, sizeof (struct normal1) == N / 8 + 16);
+ASSERT (check_normal1_alias, sizeof (struct normal1_alias) == N / 8 + 16);
+ASSERT (check_normal2, sizeof (struct normal2) == N / 8 + 16);
+
+ASSERT (check_aligned1, sizeof (struct aligned1) == N / 4);
+ASSERT (check_aligned1_alias, sizeof (struct aligned1_alias) == N / 4);
+ASSERT (check_aligned2, sizeof (struct aligned2) == N / 4);