Message ID | 20240619135423.18890-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: implement DR1363 and DR1496 for __is_trivial [PR85723] | expand |
Ping. On Wed, Jun 19, 2024 at 09:54:23AM -0400, Marek Polacek wrote: > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > -- >8 -- > is_trivial was introduced in > <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2230.html> > which split POD into is_trivial and is_standard_layout. > > Later came CWG 1363. Since > > struct A { > A() = default; > A(int = 42) {} > }; > > cannot be default-initialized, it should not be trivial, so the definition > of what is a trivial class changed. > > Similarly, CWG 1496 concluded that > > struct B { > B() = delete; > }: > > should not be trivial either. > > P0848 adjusted the definition further to say "eligible". That means > that > > template<typename T> > struct C { > C() requires false = default; > }; > > should not be trivial, either, since C::C() is not eligible. > > Bug 85723 reports that we implement none of the CWGs. > > I chose to fix this by using type_has_non_deleted_trivial_default_ctor > which uses locate_ctor which uses build_new_method_call, which would > be used by default-initialization as well. With that, all __is_trivial > problems I could find in the Bugzilla are fixed, except for PR96288, > which may need changes to trivially-copyable, so I'm not messing with > that now. > > I hope this has no ABI implications. There's effort undergoing to > remove "trivial class" from the core language as it's not really > meaningful. So the impact of this change should be pretty low except > to fix a few libstdc++ problems. > > PR c++/108769 > PR c++/58074 > PR c++/115522 > PR c++/85723 > > gcc/cp/ChangeLog: > > * class.cc (type_has_non_deleted_trivial_default_ctor): Fix formatting. > * tree.cc (trivial_type_p): Instead of TYPE_HAS_TRIVIAL_DFLT, use > type_has_non_deleted_trivial_default_ctor. > > gcc/testsuite/ChangeLog: > > * g++.dg/warn/Wclass-memaccess.C: Add dg-warning. > * g++.dg/ext/is_trivial1.C: New test. > * g++.dg/ext/is_trivial2.C: New test. > * g++.dg/ext/is_trivial3.C: New test. > * g++.dg/ext/is_trivial4.C: New test. > * g++.dg/ext/is_trivial5.C: New test. > * g++.dg/ext/is_trivial6.C: New test. > --- > gcc/cp/class.cc | 3 +- > gcc/cp/tree.cc | 4 +- > gcc/testsuite/g++.dg/ext/is_trivial1.C | 14 ++++++ > gcc/testsuite/g++.dg/ext/is_trivial2.C | 17 +++++++ > gcc/testsuite/g++.dg/ext/is_trivial3.C | 15 ++++++ > gcc/testsuite/g++.dg/ext/is_trivial4.C | 10 ++++ > gcc/testsuite/g++.dg/ext/is_trivial5.C | 8 ++++ > gcc/testsuite/g++.dg/ext/is_trivial6.C | 49 ++++++++++++++++++++ > gcc/testsuite/g++.dg/warn/Wclass-memaccess.C | 2 + > 9 files changed, 120 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial1.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial2.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial3.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial4.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial5.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial6.C > > diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc > index 0ce361eb88e..718601756dd 100644 > --- a/gcc/cp/class.cc > +++ b/gcc/cp/class.cc > @@ -5918,7 +5918,8 @@ type_has_virtual_destructor (tree type) > /* True iff class TYPE has a non-deleted trivial default > constructor. */ > > -bool type_has_non_deleted_trivial_default_ctor (tree type) > +bool > +type_has_non_deleted_trivial_default_ctor (tree type) > { > return TYPE_HAS_TRIVIAL_DFLT (type) && locate_ctor (type); > } > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc > index 28648c14c6d..5b837f89e03 100644 > --- a/gcc/cp/tree.cc > +++ b/gcc/cp/tree.cc > @@ -4637,7 +4637,9 @@ trivial_type_p (const_tree t) > t = strip_array_types (CONST_CAST_TREE (t)); > > if (CLASS_TYPE_P (t)) > - return (TYPE_HAS_TRIVIAL_DFLT (t) > + /* A trivial class is a class that is trivially copyable and has one or > + more eligible default constructors, all of which are trivial. */ > + return (type_has_non_deleted_trivial_default_ctor (CONST_CAST_TREE (t)) > && trivially_copyable_p (t)); > else > return scalarish_type_p (t); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial1.C b/gcc/testsuite/g++.dg/ext/is_trivial1.C > new file mode 100644 > index 00000000000..60ce48edfe9 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial1.C > @@ -0,0 +1,14 @@ > +// PR c++/108769 > +// { dg-do compile { target c++20 } } > + > +template <class T> > +struct S { > + S() requires false = default; > +}; > +static_assert(!__is_trivial(S<int>)); > + > +template <class T> > +struct R { > + R() requires true = default; > +}; > +static_assert(__is_trivial(R<int>)); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial2.C b/gcc/testsuite/g++.dg/ext/is_trivial2.C > new file mode 100644 > index 00000000000..8a8e554580c > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial2.C > @@ -0,0 +1,17 @@ > +// PR c++/58074 > +// { dg-do compile { target c++11 } } > + > +struct Trivial > +{ > + Trivial() = delete; > +}; > + > +struct NonTrivial > +{ > + NonTrivial() = default; > + NonTrivial(NonTrivial&) = default; > + NonTrivial& operator=(NonTrivial&) = default; > +}; > + > +static_assert(!__is_trivial(Trivial), "Ouch"); > +static_assert(__is_trivial(NonTrivial), "Ouch"); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial3.C b/gcc/testsuite/g++.dg/ext/is_trivial3.C > new file mode 100644 > index 00000000000..9704a9468d5 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial3.C > @@ -0,0 +1,15 @@ > +// PR c++/115522 > +// { dg-do compile { target c++11 } } > + > +// Not default constructible. > +struct S { > + const int i; > +}; > + > +static_assert(!__is_trivial(S), ""); > + > +struct R { > + int &r; > +}; > + > +static_assert(!__is_trivial(R), ""); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial4.C b/gcc/testsuite/g++.dg/ext/is_trivial4.C > new file mode 100644 > index 00000000000..c26e784b76c > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial4.C > @@ -0,0 +1,10 @@ > +// CWG 1363 > +// PR c++/85723 > +// { dg-do compile { target c++11 } } > + > +struct A { > + A() = default; > + A(int i = 0) { } > +}; > + > +static_assert(!__is_trivial(A), ""); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial5.C b/gcc/testsuite/g++.dg/ext/is_trivial5.C > new file mode 100644 > index 00000000000..5c89e1da6e8 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial5.C > @@ -0,0 +1,8 @@ > +// CWG 1496 > +// PR c++/85723 > +// { dg-do compile { target c++11 } } > + > +struct NonTrivial { > + NonTrivial() = delete; > +}; > +static_assert(!__is_trivial (NonTrivial), "NonTrivial is trivial"); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial6.C b/gcc/testsuite/g++.dg/ext/is_trivial6.C > new file mode 100644 > index 00000000000..a3a688c5938 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial6.C > @@ -0,0 +1,49 @@ > +// PR c++/85723 > +// { dg-do compile { target c++20 } } > + > +template<typename T> > +struct A { > + A() = delete; > + A() requires(sizeof(T) == 1) = default; > + A() requires(sizeof(T) != 1) = delete; > +}; > +static_assert(!__is_trivial(A<int>)); > +static_assert(__is_trivial(A<char>)); > + > +template<typename T> > +struct B { > + B() = default; > + B() requires(sizeof(T) == 1) = default; > + B() requires(sizeof(T) != 1) = delete; > +}; > +static_assert(__is_trivial(B<int>)); > +static_assert(__is_trivial(B<char>)); > + > +template<typename T> > +struct C { > + C() = default; > + C() requires(sizeof(T) == 1) = delete; > + C() requires(sizeof(T) != 1) = default; > +}; > +static_assert(__is_trivial(C<int>)); > +static_assert(__is_trivial(C<char>)); > + > +template<typename T> > +struct D { > + D() = default; > + D(int = 42) {} > + D() requires(sizeof(T) == 1) = delete; > + D() requires(sizeof(T) != 1) = default; > +}; > +static_assert(!__is_trivial(D<int>)); > +static_assert(!__is_trivial(D<char>)); > + > + > +template<typename T> > +struct E { > + E() = delete; > + E() requires(sizeof(T) == 1) = default; > + E() requires(sizeof(T) != 1) = delete; > +}; > +static_assert(!__is_trivial(E<int>)); > +static_assert(__is_trivial(E<char>)); > diff --git a/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C > index 87aaa79ceca..636a6e6e1b8 100644 > --- a/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C > +++ b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C > @@ -1254,6 +1254,7 @@ void test (HasConstData *p, const HasConstData &x, > > // Reallocating is not diagnosed except in C++ 98 due to a bug. > T (q = realloc, (p, 1)); // { dg-warning "moving an object of non-trivially copyable type .struct HasConstData.; use .new. and .delete. instead" "c++98" { target { c++98_only } } } > +// { dg-warning "moving an object of non-trivial type" "" { target c++11 } .-1 } > T (q = realloc, (p, n)); // { dg-warning "realloc" "c++98" { target { c++98_only } } } > T (q = realloc, (p, sizeof *p)); // { dg-warning "realloc" "c++98" { target { c++98_only } } } > } > @@ -1333,6 +1334,7 @@ void test (HasReference *p, const HasReference &x, > // in C++ 98 because of a bug, but it seems like it should be > // diagnosed in all modes. > T (q = realloc, (p, 1)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } > +// { dg-warning "moving an object of non-trivial type" "" { target c++11 } .-1 } > T (q = realloc, (p, n)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } > T (q = realloc, (p, sizeof *p)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } > } > > base-commit: be18486825dd24533d320bf840bf95bd083487d1 > -- > 2.45.1 > Marek
On 6/19/24 9:54 AM, Marek Polacek wrote: > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > -- >8 -- > is_trivial was introduced in > <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2230.html> > which split POD into is_trivial and is_standard_layout. > > Later came CWG 1363. Since > > struct A { > A() = default; > A(int = 42) {} > }; > > cannot be default-initialized, it should not be trivial, so the definition > of what is a trivial class changed. > > Similarly, CWG 1496 concluded that > > struct B { > B() = delete; > }: > > should not be trivial either. > > P0848 adjusted the definition further to say "eligible". That means > that > > template<typename T> > struct C { > C() requires false = default; > }; > > should not be trivial, either, since C::C() is not eligible. > > Bug 85723 reports that we implement none of the CWGs. > > I chose to fix this by using type_has_non_deleted_trivial_default_ctor > which uses locate_ctor which uses build_new_method_call, which would > be used by default-initialization as well. With that, all __is_trivial > problems I could find in the Bugzilla are fixed, except for PR96288, > which may need changes to trivially-copyable, so I'm not messing with > that now. > > I hope this has no ABI implications. There's effort undergoing to > remove "trivial class" from the core language as it's not really > meaningful. So the impact of this change should be pretty low except > to fix a few libstdc++ problems. > > PR c++/108769 > PR c++/58074 > PR c++/115522 > PR c++/85723 > > gcc/cp/ChangeLog: > > * class.cc (type_has_non_deleted_trivial_default_ctor): Fix formatting. > * tree.cc (trivial_type_p): Instead of TYPE_HAS_TRIVIAL_DFLT, use > type_has_non_deleted_trivial_default_ctor. > > gcc/testsuite/ChangeLog: > > * g++.dg/warn/Wclass-memaccess.C: Add dg-warning. > * g++.dg/ext/is_trivial1.C: New test. > * g++.dg/ext/is_trivial2.C: New test. > * g++.dg/ext/is_trivial3.C: New test. > * g++.dg/ext/is_trivial4.C: New test. > * g++.dg/ext/is_trivial5.C: New test. > * g++.dg/ext/is_trivial6.C: New test. > --- > gcc/cp/class.cc | 3 +- > gcc/cp/tree.cc | 4 +- > gcc/testsuite/g++.dg/ext/is_trivial1.C | 14 ++++++ > gcc/testsuite/g++.dg/ext/is_trivial2.C | 17 +++++++ > gcc/testsuite/g++.dg/ext/is_trivial3.C | 15 ++++++ > gcc/testsuite/g++.dg/ext/is_trivial4.C | 10 ++++ > gcc/testsuite/g++.dg/ext/is_trivial5.C | 8 ++++ > gcc/testsuite/g++.dg/ext/is_trivial6.C | 49 ++++++++++++++++++++ > gcc/testsuite/g++.dg/warn/Wclass-memaccess.C | 2 + > 9 files changed, 120 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial1.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial2.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial3.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial4.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial5.C > create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial6.C > > diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc > index 0ce361eb88e..718601756dd 100644 > --- a/gcc/cp/class.cc > +++ b/gcc/cp/class.cc > @@ -5918,7 +5918,8 @@ type_has_virtual_destructor (tree type) > /* True iff class TYPE has a non-deleted trivial default > constructor. */ > > -bool type_has_non_deleted_trivial_default_ctor (tree type) > +bool > +type_has_non_deleted_trivial_default_ctor (tree type) > { > return TYPE_HAS_TRIVIAL_DFLT (type) && locate_ctor (type); > } > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc > index 28648c14c6d..5b837f89e03 100644 > --- a/gcc/cp/tree.cc > +++ b/gcc/cp/tree.cc > @@ -4637,7 +4637,9 @@ trivial_type_p (const_tree t) > t = strip_array_types (CONST_CAST_TREE (t)); > > if (CLASS_TYPE_P (t)) > - return (TYPE_HAS_TRIVIAL_DFLT (t) > + /* A trivial class is a class that is trivially copyable and has one or > + more eligible default constructors, all of which are trivial. */ > + return (type_has_non_deleted_trivial_default_ctor (CONST_CAST_TREE (t)) > && trivially_copyable_p (t)); > else > return scalarish_type_p (t); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial1.C b/gcc/testsuite/g++.dg/ext/is_trivial1.C > new file mode 100644 > index 00000000000..60ce48edfe9 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial1.C > @@ -0,0 +1,14 @@ > +// PR c++/108769 > +// { dg-do compile { target c++20 } } > + > +template <class T> > +struct S { > + S() requires false = default; > +}; > +static_assert(!__is_trivial(S<int>)); > + > +template <class T> > +struct R { > + R() requires true = default; > +}; > +static_assert(__is_trivial(R<int>)); > diff --git a/gcc/testsuite/g++.dg/ext/is_trivial2.C b/gcc/testsuite/g++.dg/ext/is_trivial2.C > new file mode 100644 > index 00000000000..8a8e554580c > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ext/is_trivial2.C > @@ -0,0 +1,17 @@ > +// PR c++/58074 > +// { dg-do compile { target c++11 } } > + > +struct Trivial > +{ > + Trivial() = delete; > +}; > + > +struct NonTrivial > +{ > + NonTrivial() = default; > + NonTrivial(NonTrivial&) = default; > + NonTrivial& operator=(NonTrivial&) = default; > +}; > + > +static_assert(!__is_trivial(Trivial), "Ouch"); > +static_assert(__is_trivial(NonTrivial), "Ouch"); Funny that these classes in this testcase are now named backwards, we've come full circle to the behavior that PR58074 was complaining about. Maybe add a comment to that effect? OK with that tweak. Jasnon
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index 0ce361eb88e..718601756dd 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -5918,7 +5918,8 @@ type_has_virtual_destructor (tree type) /* True iff class TYPE has a non-deleted trivial default constructor. */ -bool type_has_non_deleted_trivial_default_ctor (tree type) +bool +type_has_non_deleted_trivial_default_ctor (tree type) { return TYPE_HAS_TRIVIAL_DFLT (type) && locate_ctor (type); } diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 28648c14c6d..5b837f89e03 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -4637,7 +4637,9 @@ trivial_type_p (const_tree t) t = strip_array_types (CONST_CAST_TREE (t)); if (CLASS_TYPE_P (t)) - return (TYPE_HAS_TRIVIAL_DFLT (t) + /* A trivial class is a class that is trivially copyable and has one or + more eligible default constructors, all of which are trivial. */ + return (type_has_non_deleted_trivial_default_ctor (CONST_CAST_TREE (t)) && trivially_copyable_p (t)); else return scalarish_type_p (t); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial1.C b/gcc/testsuite/g++.dg/ext/is_trivial1.C new file mode 100644 index 00000000000..60ce48edfe9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial1.C @@ -0,0 +1,14 @@ +// PR c++/108769 +// { dg-do compile { target c++20 } } + +template <class T> +struct S { + S() requires false = default; +}; +static_assert(!__is_trivial(S<int>)); + +template <class T> +struct R { + R() requires true = default; +}; +static_assert(__is_trivial(R<int>)); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial2.C b/gcc/testsuite/g++.dg/ext/is_trivial2.C new file mode 100644 index 00000000000..8a8e554580c --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial2.C @@ -0,0 +1,17 @@ +// PR c++/58074 +// { dg-do compile { target c++11 } } + +struct Trivial +{ + Trivial() = delete; +}; + +struct NonTrivial +{ + NonTrivial() = default; + NonTrivial(NonTrivial&) = default; + NonTrivial& operator=(NonTrivial&) = default; +}; + +static_assert(!__is_trivial(Trivial), "Ouch"); +static_assert(__is_trivial(NonTrivial), "Ouch"); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial3.C b/gcc/testsuite/g++.dg/ext/is_trivial3.C new file mode 100644 index 00000000000..9704a9468d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial3.C @@ -0,0 +1,15 @@ +// PR c++/115522 +// { dg-do compile { target c++11 } } + +// Not default constructible. +struct S { + const int i; +}; + +static_assert(!__is_trivial(S), ""); + +struct R { + int &r; +}; + +static_assert(!__is_trivial(R), ""); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial4.C b/gcc/testsuite/g++.dg/ext/is_trivial4.C new file mode 100644 index 00000000000..c26e784b76c --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial4.C @@ -0,0 +1,10 @@ +// CWG 1363 +// PR c++/85723 +// { dg-do compile { target c++11 } } + +struct A { + A() = default; + A(int i = 0) { } +}; + +static_assert(!__is_trivial(A), ""); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial5.C b/gcc/testsuite/g++.dg/ext/is_trivial5.C new file mode 100644 index 00000000000..5c89e1da6e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial5.C @@ -0,0 +1,8 @@ +// CWG 1496 +// PR c++/85723 +// { dg-do compile { target c++11 } } + +struct NonTrivial { + NonTrivial() = delete; +}; +static_assert(!__is_trivial (NonTrivial), "NonTrivial is trivial"); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial6.C b/gcc/testsuite/g++.dg/ext/is_trivial6.C new file mode 100644 index 00000000000..a3a688c5938 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial6.C @@ -0,0 +1,49 @@ +// PR c++/85723 +// { dg-do compile { target c++20 } } + +template<typename T> +struct A { + A() = delete; + A() requires(sizeof(T) == 1) = default; + A() requires(sizeof(T) != 1) = delete; +}; +static_assert(!__is_trivial(A<int>)); +static_assert(__is_trivial(A<char>)); + +template<typename T> +struct B { + B() = default; + B() requires(sizeof(T) == 1) = default; + B() requires(sizeof(T) != 1) = delete; +}; +static_assert(__is_trivial(B<int>)); +static_assert(__is_trivial(B<char>)); + +template<typename T> +struct C { + C() = default; + C() requires(sizeof(T) == 1) = delete; + C() requires(sizeof(T) != 1) = default; +}; +static_assert(__is_trivial(C<int>)); +static_assert(__is_trivial(C<char>)); + +template<typename T> +struct D { + D() = default; + D(int = 42) {} + D() requires(sizeof(T) == 1) = delete; + D() requires(sizeof(T) != 1) = default; +}; +static_assert(!__is_trivial(D<int>)); +static_assert(!__is_trivial(D<char>)); + + +template<typename T> +struct E { + E() = delete; + E() requires(sizeof(T) == 1) = default; + E() requires(sizeof(T) != 1) = delete; +}; +static_assert(!__is_trivial(E<int>)); +static_assert(__is_trivial(E<char>)); diff --git a/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C index 87aaa79ceca..636a6e6e1b8 100644 --- a/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C +++ b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C @@ -1254,6 +1254,7 @@ void test (HasConstData *p, const HasConstData &x, // Reallocating is not diagnosed except in C++ 98 due to a bug. T (q = realloc, (p, 1)); // { dg-warning "moving an object of non-trivially copyable type .struct HasConstData.; use .new. and .delete. instead" "c++98" { target { c++98_only } } } +// { dg-warning "moving an object of non-trivial type" "" { target c++11 } .-1 } T (q = realloc, (p, n)); // { dg-warning "realloc" "c++98" { target { c++98_only } } } T (q = realloc, (p, sizeof *p)); // { dg-warning "realloc" "c++98" { target { c++98_only } } } } @@ -1333,6 +1334,7 @@ void test (HasReference *p, const HasReference &x, // in C++ 98 because of a bug, but it seems like it should be // diagnosed in all modes. T (q = realloc, (p, 1)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } +// { dg-warning "moving an object of non-trivial type" "" { target c++11 } .-1 } T (q = realloc, (p, n)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } T (q = realloc, (p, sizeof *p)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } }