On 13 September 2018 at 13:41, Ville Voutilainen <ville.voutilai...@gmail.com> wrote: >> How does this work when: >> unsigned has_complex_copy_ctor : 1; > It doesn't. I need more bits. Luckily, we have some available.
Here. I suppose this could theoretically be done in some later stage of class completion, but that would presumably be an additional member function loop that looks at the constructors, weeds out copy constructors, and calculates the triviality bit (and it should probably then also look at fields and bases, again). So while I continue to have a minor distaste for this whole approach, and how it wastes two perfectly good bits for a dark corner case, I think I can learn to live with it. Tests pass on Linux-PPC64, although the suite is still running some library tests, so I think I'll do a paranoid re-run. OK for trunk? I'm not planning to backport this, it's not a regression. 2018-09-13 Ville Voutilainen <ville.voutilai...@gmail.com> gcc/cp PR c++/87051 * cp-tree.h (lang_type): Grow has_complex_copy_ctor and shrink dummy. * decl.c (grok_special_member_properties): Don't mark the class as having a non-trivial copy constructor if the copy constructor we're looking at is not a const-copy and a const-copy was already found, reset the copy constructor triviality if we found a trivial const-copy. testsuite/ PR c++/87051 * g++.dg/ext/is_trivially_constructible7.C: New.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6cd6e5f..fa39f6a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2046,7 +2046,7 @@ struct GTY(()) lang_type { unsigned lazy_copy_assign : 1; unsigned lazy_destructor : 1; unsigned has_const_copy_ctor : 1; - unsigned has_complex_copy_ctor : 1; + unsigned has_complex_copy_ctor : 2; unsigned has_complex_copy_assign : 1; unsigned non_aggregate : 1; @@ -2070,7 +2070,7 @@ struct GTY(()) lang_type { /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 4; + unsigned dummy : 3; tree primary_base; vec<tree_pair_s, va_gc> *vcall_indices; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 50b60e8..452e968 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13212,7 +13212,15 @@ grok_special_member_properties (tree decl) default arguments. */ TYPE_HAS_COPY_CTOR (class_type) = 1; if (user_provided_p (decl)) - TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 1; + { + if (ctor > 1) + TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 1; + else if (!TYPE_HAS_CONST_COPY_CTOR (class_type) + && TYPE_HAS_COMPLEX_COPY_CTOR (class_type) < 2) + TYPE_HAS_COMPLEX_COPY_CTOR (class_type) += 2; + } + else if (ctor > 1 && TYPE_HAS_COMPLEX_COPY_CTOR (class_type) == 2) + TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 0; if (ctor > 1) TYPE_HAS_CONST_COPY_CTOR (class_type) = 1; } diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C new file mode 100644 index 0000000..177eb2e --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible7.C @@ -0,0 +1,16 @@ +// { dg-do compile { target c++11 } } + +// PR c++/87051 + +struct M { + M(const M&) = default; + M(M&); +}; + +struct M2 { + M2(M2&); + M2(const M2&) = default; +}; + +static_assert( __is_trivially_constructible(M, M&&), ""); +static_assert( __is_trivially_constructible(M2, M2&&), "");