Message ID | CAFk2RUYhAnLjFc8mcTfiheJAr4R6E1mdx32PTqZJ5EpPt8=4aQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
On 19 January 2015 at 18:28, Ville Voutilainen <ville.voutilainen@gmail.com> wrote: > When I patched the triviality test for volatile types, I missed two cases: > 1) volatile members in a class should make the class non-trivial. > 2) a volatile class type should itself be non-trivial. > (based on [basic.types]/9, [class]/6, [class.copy]/12 and [class.copy]/25) > > I haven't completed testing this yet, I still need to run the full testsuite > to make sure there are no regressions. I'm not sure whether this > can go into gcc5, since we're at stage 4. Not quite done yet, some tests need adjusting, I will fix them shortly.
On 01/19/2015 11:28 AM, Ville Voutilainen wrote: > * class.c (check_field_decls): If any field is volatile, make > the class type have complex copy/move operations. Discussion on the cxx-abi list points out that this breaks ABI compatibility between C and C++, and is therefore unacceptable. Jason
On 6 March 2015 at 23:58, Jason Merrill <jason@redhat.com> wrote: > On 01/19/2015 11:28 AM, Ville Voutilainen wrote: >> >> * class.c (check_field_decls): If any field is volatile, make >> the class type have complex copy/move operations. > > > Discussion on the cxx-abi list points out that this breaks ABI compatibility > between C and C++, and is therefore unacceptable. So.. just to clarify that we're on the same page.. making volatile-qualified types non-trivially copyable is ok, but making wrappers of volatile-qualified types non-trivially copyable is not ok? That's easily doable implementation-wise, but it makes me question the overall approach and its consistency. Is there a way to indicate that from the point of C++ a type is not trivially copyable without changing the "complexness" of a copy operation, ultimately without changing ABI?
On 03/06/2015 06:03 PM, Ville Voutilainen wrote: > So.. just to clarify that we're on the same page.. making volatile-qualified > types non-trivially copyable is ok, but making wrappers of volatile-qualified > types non-trivially copyable is not ok? That's easily doable implementation-wise, > but it makes me question the overall approach and its consistency. Indeed. This is a question for CWG; we may want to reconsider the first point as well. > Is there a way to indicate that from the point of C++ a type is not trivially > copyable without changing the "complexness" of a copy operation, > ultimately without changing ABI? There are various hacks I can imagine, but I think I'd prefer to resolve the standard issue before trying to implement it. Jason
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index edb87fe..529a2bf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3717,6 +3717,16 @@ check_field_decls (tree t, tree *access_decls, if (DECL_INITIAL (x) && cxx_dialect < cxx14) CLASSTYPE_NON_AGGREGATE (t) = true; + /* If any field is volatile, the structure type has complex copy + and move operations. */ + if (CP_TYPE_VOLATILE_P (type)) + { + TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1; + TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1; + TYPE_HAS_COMPLEX_COPY_CTOR (t) = 1; + TYPE_HAS_COMPLEX_MOVE_CTOR (t) = 1; + } + /* If any field is const, the structure type is pseudo-const. */ if (CP_TYPE_CONST_P (type)) { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 80f2ce6..169b796 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3211,7 +3211,8 @@ trivially_copyable_p (const_tree t) && (!TYPE_HAS_COPY_ASSIGN (t) || !TYPE_HAS_COMPLEX_COPY_ASSIGN (t)) && !TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) - && TYPE_HAS_TRIVIAL_DESTRUCTOR (t)); + && TYPE_HAS_TRIVIAL_DESTRUCTOR (t) + && !CP_TYPE_VOLATILE_P (t)); else return !CP_TYPE_VOLATILE_P (t) && scalarish_type_p (t); } diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C index a5bac7b..35ef1f1 100644 --- a/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C +++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C @@ -39,5 +39,16 @@ SA(!__is_trivially_copyable(volatile int)); struct E1 {const int val;}; SA(__is_trivially_copyable(E1)); +SA(!__is_trivially_copyable(volatile E1)); struct E2 {int& val;}; SA(__is_trivially_copyable(E2)); +struct E3 {volatile int val;}; +SA(!__is_trivially_copyable(E3)); +struct E4 {A a;}; +SA(!__is_trivially_copyable(volatile E4)); +struct E5 {volatile A a;}; +SA(!__is_trivially_copyable(E5)); +SA(!__is_trivially_copyable(volatile E5)); +struct E6 : A {}; +SA(__is_trivially_copyable(E6)); +SA(!__is_trivially_copyable(volatile E6));