diff options
-rw-r--r-- | gcc/common.opt | 1 | ||||
-rw-r--r-- | gcc/cp/class.cc | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/no_unique_address8.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/no_unique_address8a.C | 31 |
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); |