aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/common.opt1
-rw-r--r--gcc/cp/class.cc28
-rw-r--r--gcc/testsuite/g++.dg/abi/no_unique_address8.C30
-rw-r--r--gcc/testsuite/g++.dg/abi/no_unique_address8a.C31
4 files changed, 88 insertions, 2 deletions
diff --git a/gcc/common.opt b/gcc/common.opt
index 3e19392..f137a1f 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1011,6 +1011,7 @@ Driver Undocumented
; Default in G++ 13.
;
; 19: Emits ABI tags if needed in structured binding mangled names.
+; Ignores cv-quals on [[no_unique_object]] members.
; Default in G++ 14.
;
; Additional positive integers will be assigned as new versions of
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 7787592..9139a00 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -4053,9 +4053,33 @@ check_subobject_offset (tree type, tree offset, splay_tree offsets)
if (!n)
return 0;
+ enum { ignore, fast, slow, warn }
+ cv_check = (abi_version_crosses (19) ? slow
+ : abi_version_at_least (19) ? fast
+ : ignore);
for (t = (tree) n->value; t; t = TREE_CHAIN (t))
- if (same_type_p (TREE_VALUE (t), type))
- return 1;
+ {
+ tree elt = TREE_VALUE (t);
+
+ if (same_type_p (elt, type))
+ return 1;
+
+ if (cv_check != ignore
+ && same_type_ignoring_top_level_qualifiers_p (elt, type))
+ {
+ if (cv_check == fast)
+ return 1;
+ cv_check = warn;
+ }
+ }
+
+ if (cv_check == warn)
+ {
+ warning (OPT_Wabi, "layout of %qs member of type %qT changes in %qs",
+ "[[no_unique_address]]", type, "-fabi-version=19");
+ if (abi_version_at_least (19))
+ return 1;
+ }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address8.C b/gcc/testsuite/g++.dg/abi/no_unique_address8.C
new file mode 100644
index 0000000..6aa2bba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address8.C
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=19 -Wabi=18" }
+
+#include <cstddef>
+
+#define NOUNIQUE [[no_unique_address]]
+
+struct Empty { };
+#define CHECK_DISTINCT(type, field1, field2) static_assert(offsetof(type, field1) != offsetof(type, field2))
+
+struct A1 {
+ NOUNIQUE Empty a;
+ Empty b;
+};
+CHECK_DISTINCT(A1, a, b);
+struct A2 {
+ NOUNIQUE const Empty a;
+ const Empty b;
+};
+CHECK_DISTINCT(A2, a, b);
+struct A3 { // { dg-warning "layout" }
+ NOUNIQUE const Empty a;
+ Empty b;
+};
+CHECK_DISTINCT(A3, a, b);
+struct A4 { // { dg-warning "layout" }
+ NOUNIQUE Empty a;
+ const Empty b;
+};
+CHECK_DISTINCT(A4, a, b);
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address8a.C b/gcc/testsuite/g++.dg/abi/no_unique_address8a.C
new file mode 100644
index 0000000..c5d4808
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address8a.C
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=18 -Wabi=19" }
+
+#include <cstddef>
+
+#define NOUNIQUE [[no_unique_address]]
+
+struct Empty { };
+#define CHECK_DISTINCT(type, field1, field2) static_assert(offsetof(type, field1) != offsetof(type, field2))
+#define CHECK_SAME(type, field1, field2) static_assert(offsetof(type, field1) == offsetof(type, field2))
+
+struct A1 {
+ NOUNIQUE Empty a;
+ Empty b;
+};
+CHECK_DISTINCT(A1, a, b);
+struct A2 {
+ NOUNIQUE const Empty a;
+ const Empty b;
+};
+CHECK_DISTINCT(A2, a, b);
+struct A3 { // { dg-warning "layout" }
+ NOUNIQUE const Empty a;
+ Empty b;
+};
+CHECK_SAME(A3, a, b);
+struct A4 { // { dg-warning "layout" }
+ NOUNIQUE Empty a;
+ const Empty b;
+};
+CHECK_SAME(A4, a, b);