Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-03-09 Thread Jason Merrill

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



Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-03-06 Thread Ville Voutilainen
On 6 March 2015 at 23:58, Jason Merrill ja...@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?


Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-03-06 Thread Jason Merrill

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



Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Ville Voutilainen
On 30 January 2015 at 23:06, Ville Voutilainen
ville.voutilai...@gmail.com wrote:
 Let's drop libstdc++, this discussion is about a test that doesn't
 really concern them.

 On 30 January 2015 at 22:51, Jason Merrill ja...@redhat.com wrote:
 The patch changes all the static_assert strings to , which is not very
 useful; let's keep the macro.


 Ok. How about this one? It reuses the macro and keeps the YES/NO, but
 utilizes intermediate classes that perform the type transformations for
 the TRY macros in a non-surprising c++ manner.

Just a slight alternative, use TRY in YES/NO as well. It doesn't
change the diagnostics
when such a check fails, apparently, but it's a tad neater. :)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1273064..ca01e5a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3727,6 +3727,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/semantics.c b/gcc/cp/semantics.c
index 915048d..d376a09 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7477,7 +7477,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   type1 = strip_array_types (type1);
-  return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
+  return (scalarish_type_p (type1) || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index afb57a3..7f84f00 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);
 }
@@ -3228,7 +3229,7 @@ trivial_type_p (const_tree t)
 return (TYPE_HAS_TRIVIAL_DFLT (t)
 trivially_copyable_p (t));
   else
-return scalarish_type_p (t);
+return !CP_TYPE_VOLATILE_P (t)  scalarish_type_p (t);
 }
 
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C 
b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 3fed570..71019a6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -16,12 +16,23 @@
 #include type_traits
 
 #define TRY(expr) static_assert (expr, #expr)
-#define YES(type) TRY(std::is_trivialtype::value); \
-  TRY(std::is_trivialtype[]::value); \
-  TRY(std::is_trivialconst volatile type::value)
-#define NO(type) TRY(!std::is_trivialtype::value); \
-  TRY(!std::is_trivialtype[]::value); \
-  TRY(!std::is_trivialconst volatile type::value)
+
+template class T struct Yes
+{
+  TRY(std::is_trivialT::value);
+  TRY(std::is_trivialT[]::value);
+  TRY(!std::is_trivialconst volatile T::value);
+};
+
+template class T struct No
+{
+  TRY(!std::is_trivialT::value);
+  TRY(!std::is_trivialT[]::value);
+  TRY(!std::is_trivialconst volatile T::value);
+};
+
+#define YES(expr) TRY(sizeof(decltype(Yesexpr(
+#define NO(expr) TRY(sizeof(decltype(Noexpr(
 
 struct A;
 
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));
diff --git 
a/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc 
b/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
index ea58a22..ab88c3a 100644
--- a/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
+++ 

Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Ville Voutilainen
Let's drop libstdc++, this discussion is about a test that doesn't
really concern them.

On 30 January 2015 at 22:51, Jason Merrill ja...@redhat.com wrote:
 The patch changes all the static_assert strings to , which is not very
 useful; let's keep the macro.


Ok. How about this one? It reuses the macro and keeps the YES/NO, but
utilizes intermediate classes that perform the type transformations for
the TRY macros in a non-surprising c++ manner.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1273064..ca01e5a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3727,6 +3727,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/semantics.c b/gcc/cp/semantics.c
index 915048d..d376a09 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7477,7 +7477,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   type1 = strip_array_types (type1);
-  return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
+  return (scalarish_type_p (type1) || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index afb57a3..7f84f00 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);
 }
@@ -3228,7 +3229,7 @@ trivial_type_p (const_tree t)
 return (TYPE_HAS_TRIVIAL_DFLT (t)
 trivially_copyable_p (t));
   else
-return scalarish_type_p (t);
+return !CP_TYPE_VOLATILE_P (t)  scalarish_type_p (t);
 }
 
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C 
b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 3fed570..6df50d1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -16,12 +16,23 @@
 #include type_traits
 
 #define TRY(expr) static_assert (expr, #expr)
-#define YES(type) TRY(std::is_trivialtype::value); \
-  TRY(std::is_trivialtype[]::value); \
-  TRY(std::is_trivialconst volatile type::value)
-#define NO(type) TRY(!std::is_trivialtype::value); \
-  TRY(!std::is_trivialtype[]::value); \
-  TRY(!std::is_trivialconst volatile type::value)
+
+template class T struct Yes
+{
+  TRY(std::is_trivialT::value);
+  TRY(std::is_trivialT[]::value);
+  TRY(!std::is_trivialconst volatile T::value);
+};
+
+template class T struct No
+{
+  TRY(!std::is_trivialT::value);
+  TRY(!std::is_trivialT[]::value);
+  TRY(!std::is_trivialconst volatile T::value);
+};
+
+#define YES(expr) static_assert(sizeof(decltype(Yesexpr())), )
+#define NO(expr) static_assert(sizeof(decltype(Noexpr())), )
 
 struct A;
 
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));
diff --git 
a/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc 
b/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
index ea58a22..ab88c3a 100644
--- a/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
+++ b/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
@@ -31,30 +31,31 @@ void test01()
   using namespace __gnu_test;
 
   // Positive tests.
-  static_assert(test_categoryhas_trivial_copy_constructor, int(true), );
-  

Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Jason Merrill

On 01/30/2015 03:05 PM, Ville Voutilainen wrote:

-#define TRY(expr) static_assert (expr, #expr)


The patch changes all the static_assert strings to , which is not very 
useful; let's keep the macro.


Jason



Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Ville Voutilainen
On 30 January 2015 at 21:59, Ville Voutilainen
ville.voutilai...@gmail.com wrote:
 So, a new patch attached. The only change to the previous one is the change
 to the trivial1.C test.

Oops. The No-template was borken and there was remnants of the macros
in commented
code. Let's try that again, shall we? :) Attached.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1273064..ca01e5a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3727,6 +3727,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/semantics.c b/gcc/cp/semantics.c
index 915048d..d376a09 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7477,7 +7477,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   type1 = strip_array_types (type1);
-  return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
+  return (scalarish_type_p (type1) || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index afb57a3..7f84f00 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);
 }
@@ -3228,7 +3229,7 @@ trivial_type_p (const_tree t)
 return (TYPE_HAS_TRIVIAL_DFLT (t)
 trivially_copyable_p (t));
   else
-return scalarish_type_p (t);
+return !CP_TYPE_VOLATILE_P (t)  scalarish_type_p (t);
 }
 
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C 
b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 3fed570..49dc26b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -15,31 +15,38 @@
 
 #include type_traits
 
-#define TRY(expr) static_assert (expr, #expr)
-#define YES(type) TRY(std::is_trivialtype::value); \
-  TRY(std::is_trivialtype[]::value); \
-  TRY(std::is_trivialconst volatile type::value)
-#define NO(type) TRY(!std::is_trivialtype::value); \
-  TRY(!std::is_trivialtype[]::value); \
-  TRY(!std::is_trivialconst volatile type::value)
+
+template class T struct Yes
+{
+  static constexpr bool value = std::is_trivialT::value
+ std::is_trivialT[]::value
+ !std::is_trivialconst volatile T::value;
+};
+
+template class T struct No
+{
+  static constexpr bool value = !std::is_trivialT::value
+ !std::is_trivialT[]::value
+ !std::is_trivialconst volatile T::value;
+};
 
 struct A;
 
-YES(int);
-YES(__complex int);
-YES(void *);
-YES(int A::*);
+static_assert(Yesint::value, );
+static_assert(Yes__complex int::value, );
+static_assert(Yesvoid *::value, );
+static_assert(Yesint A::*::value, );
 typedef int (A::*pmf)();
-YES(pmf);
+static_assert(Yespmf::value, );
 
 struct A { ~A(); };
-NO(A);
+static_assert(NoA::value, );
 struct F: public A { int i; };
-NO(F);
+static_assert(NoF::value, );
 struct G: public A { A a; };
-NO(G);
+static_assert(NoG::value, );
 struct M { A a; };
-NO(M);
+static_assert(NoM::value, );
 
 class B
 {
@@ -50,15 +57,15 @@ class B
   int A::* pm;
   int (A::*pmf)();
 };
-YES(B);
+static_assert(YesB::value, );
 struct D: public B { };
-YES(D);
+static_assert(YesD::value, );
 struct E: public B { int q; };
-YES(E);
+static_assert(YesE::value, );
 struct D2: public B { };
-YES(D2);
+static_assert(YesD2::value, );
 struct I: public D, public D2 { };
-YES(I);
+static_assert(YesI::value, );
 
 struct C
 {
@@ -66,21 +73,21 @@ struct C
 private:
   int j;
 };
-YES(C);
+static_assert(YesC::value, );
 struct H: public C { };
-YES(H);
+static_assert(YesH::value, );
 struct N { C c; };
-YES(N);
+static_assert(YesN::value, );
 
 struct J { virtual void f(); };
 struct J2: J { };
-NO(J);
-NO(J2);
+static_assert(NoJ::value, );
+static_assert(NoJ2::value, );
 struct K { };
 struct L: virtual K {};
-YES(K);
-NO(L);
+static_assert(YesK::value, );
+static_assert(NoL::value, );
 
 // PR c++/41421
 struct O { O(int); };
-NO(O);
+static_assert(NoO::value, );
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C 

Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Ville Voutilainen
On 30 January 2015 at 19:46, Jason Merrill ja...@redhat.com wrote:
 On 01/20/2015 09:27 AM, Ville Voutilainen wrote:

 +#define YES2(type) TRY(std::is_trivialtype::value); \
 +  TRY(std::is_trivialtype[]::value); \
 TRY(std::is_trivialconst volatile type::value)


 +YES2(void *);
 +YES2(int A::*);


 Why would void *const volatile still be trivial?

Ah. It isn't. YES and YES2 are macros, so YES2(void*) expands to
is_trivialconst volatile void*::value, which is true, whereas
is_trivialvoid* const volatile::value is false.

I think it would be reasonable to convert these macros in that test into
function templates, no? :)


Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Jason Merrill

On 01/20/2015 09:27 AM, Ville Voutilainen wrote:

+#define YES2(type) TRY(std::is_trivialtype::value); \
+  TRY(std::is_trivialtype[]::value); \
TRY(std::is_trivialconst volatile type::value)



+YES2(void *);
+YES2(int A::*);


Why would void *const volatile still be trivial?

Jason



Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Ville Voutilainen
On 30 January 2015 at 20:25, Jason Merrill ja...@redhat.com wrote:
 On 01/30/2015 01:13 PM, Ville Voutilainen wrote:

 Why would void *const volatile still be trivial?


 Ah. It isn't. YES and YES2 are macros, so YES2(void*) expands to
 is_trivialconst volatile void*::value, which is true, whereas
 is_trivialvoid* const volatile::value is false.

 I think it would be reasonable to convert these macros in that test into
 function templates, no? :)


 Makes sense to me.  :)

 Jason


So, a new patch attached. The only change to the previous one is the change
to the trivial1.C test.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1273064..ca01e5a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3727,6 +3727,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/semantics.c b/gcc/cp/semantics.c
index 915048d..d376a09 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7477,7 +7477,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   type1 = strip_array_types (type1);
-  return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
+  return (scalarish_type_p (type1) || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index afb57a3..7f84f00 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);
 }
@@ -3228,7 +3229,7 @@ trivial_type_p (const_tree t)
 return (TYPE_HAS_TRIVIAL_DFLT (t)
 trivially_copyable_p (t));
   else
-return scalarish_type_p (t);
+return !CP_TYPE_VOLATILE_P (t)  scalarish_type_p (t);
 }
 
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C 
b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 3fed570..5e574da 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -15,31 +15,49 @@
 
 #include type_traits
 
-#define TRY(expr) static_assert (expr, #expr)
-#define YES(type) TRY(std::is_trivialtype::value); \
+
+template class T struct Yes
+{
+  static constexpr bool value = std::is_trivialT::value
+ std::is_trivialT[]::value
+ !std::is_trivialconst volatile T::value;
+};
+
+template class T struct No
+{
+  static constexpr bool value = !std::is_trivialT[]::value
+ !std::is_trivialconst volatile T::value;
+};
+
+/*
+#define Yes(type) TRY(std::is_trivialtype::value); \
+  TRY(std::is_trivialtype[]::value); \
+  TRY(!std::is_trivialconst volatile type::value)
+#define Yes2(type) TRY(std::is_trivialtype::value); \
   TRY(std::is_trivialtype[]::value); \
   TRY(std::is_trivialconst volatile type::value)
-#define NO(type) TRY(!std::is_trivialtype::value); \
+#define No(type) TRY(!std::is_trivialtype::value); \
   TRY(!std::is_trivialtype[]::value); \
   TRY(!std::is_trivialconst volatile type::value)
+*/
 
 struct A;
 
-YES(int);
-YES(__complex int);
-YES(void *);
-YES(int A::*);
+static_assert(Yesint::value, );
+static_assert(Yes__complex int::value, );
+static_assert(Yesvoid *::value, );
+static_assert(Yesint A::*::value, );
 typedef int (A::*pmf)();
-YES(pmf);
+static_assert(Yespmf::value, );
 
 struct A { ~A(); };
-NO(A);
+static_assert(NoA::value, );
 struct F: public A { int i; };
-NO(F);
+static_assert(NoF::value, );
 struct G: public A { A a; };
-NO(G);
+static_assert(NoG::value, );
 struct M { A a; };
-NO(M);
+static_assert(NoM::value, );
 
 class B
 {
@@ -50,15 +68,15 @@ class B
   int A::* pm;
   int (A::*pmf)();
 };
-YES(B);
+static_assert(YesB::value, );
 struct D: public B { };
-YES(D);
+static_assert(YesD::value, );
 struct E: public B { int q; };
-YES(E);
+static_assert(YesE::value, );
 struct D2: public B { };
-YES(D2);
+static_assert(YesD2::value, );
 struct I: public D, public D2 { };
-YES(I);
+static_assert(YesI::value, );
 
 struct C
 {
@@ -66,21 +84,21 @@ struct C
 private:
   int j;
 };
-YES(C);
+static_assert(YesC::value, );
 struct H: public C { };
-YES(H);

Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-30 Thread Jason Merrill

On 01/30/2015 01:13 PM, Ville Voutilainen wrote:

Why would void *const volatile still be trivial?


Ah. It isn't. YES and YES2 are macros, so YES2(void*) expands to
is_trivialconst volatile void*::value, which is true, whereas
is_trivialvoid* const volatile::value is false.

I think it would be reasonable to convert these macros in that test into
function templates, no? :)


Makes sense to me.  :)

Jason




Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-20 Thread Jason Merrill

On 01/19/2015 06:06 PM, Ville Voutilainen wrote:

+  return (trivial_type_p (type1)
+ || (scalarish_type_p (type1)  CP_TYPE_VOLATILE_P (type1))
+ || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));


I think we can drop the trivial_type_p check now, it's redundant.

Jason



Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-20 Thread Ville Voutilainen
On 20 January 2015 at 15:06, Jason Merrill ja...@redhat.com wrote:
 On 01/19/2015 06:06 PM, Ville Voutilainen wrote:

 +  return (trivial_type_p (type1)
 + || (scalarish_type_p (type1)  CP_TYPE_VOLATILE_P (type1))
 + || type_code1 == REFERENCE_TYPE
   || (CLASS_TYPE_P (type1)
TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));


 I think we can drop the trivial_type_p check now, it's redundant.


Well, we can do even better, just check for scalarish_type instead of
trivial || scalarish  volatile. ;) Patch attached, changelog as before.
I re-ran the tests that previously were failing in the first versions of the
patch, didn't run the full suite again, as I unfortunately need to run. :)
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/semantics.c b/gcc/cp/semantics.c
index 15b8d01..5856670 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7383,7 +7383,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   type1 = strip_array_types (type1);
-  return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
+  return (scalarish_type_p (type1) || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 80f2ce6..79be556 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);
 }
@@ -3228,7 +3229,7 @@ trivial_type_p (const_tree t)
 return (TYPE_HAS_TRIVIAL_DFLT (t)
 trivially_copyable_p (t));
   else
-return scalarish_type_p (t);
+return !CP_TYPE_VOLATILE_P (t)  scalarish_type_p (t);
 }
 
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C 
b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 3fed570..d0d7b46 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -18,6 +18,9 @@
 #define TRY(expr) static_assert (expr, #expr)
 #define YES(type) TRY(std::is_trivialtype::value); \
   TRY(std::is_trivialtype[]::value); \
+  TRY(!std::is_trivialconst volatile type::value)
+#define YES2(type) TRY(std::is_trivialtype::value); \
+  TRY(std::is_trivialtype[]::value); \
   TRY(std::is_trivialconst volatile type::value)
 #define NO(type) TRY(!std::is_trivialtype::value); \
   TRY(!std::is_trivialtype[]::value); \
@@ -27,8 +30,8 @@ struct A;
 
 YES(int);
 YES(__complex int);
-YES(void *);
-YES(int A::*);
+YES2(void *);
+YES2(int A::*);
 typedef int (A::*pmf)();
 YES(pmf);
 
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));
diff --git 
a/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc 
b/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
index ea58a22..9cfe672 100644
--- a/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
+++ b/libstdc++-v3/testsuite/20_util/has_trivial_copy_constructor/value.cc
@@ -31,30 +31,31 @@ void test01()
   using namespace __gnu_test;
 
   // Positive tests.
-  

Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-19 Thread Ville Voutilainen
On 19 January 2015 at 21:12, Ville Voutilainen
ville.voutilai...@gmail.com wrote:
 On 19 January 2015 at 18:28, Ville Voutilainen
 ville.voutilai...@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.

Ok, this ended up being a tad more involved than I hoped. Tested on Linux-x64.
I'm copying libstdc++ as well, since I'm mucking with the library tests as well
here. The changes in the library tests from using test_category to using the
traits directly isn't the prettiest thing I've ever done, but the issue is that
no volatile type is trivially_anything, except trivially_destructible,
so test_category
is unsuitable. Please double-check that I didn't miss any test failures, as
this got rather involved, as I said.

/cp
2015-01-20  Ville Voutilainen  ville.voutilai...@gmail.com

PR c++/63959
* class.c (check_field_decls): If any field is volatile, make
the class type have complex copy/move operations.
* semantics.c (trait_expr_value): For __has_trivial_destructor,
allow types that are not trivial, but are scalarish and volatile.
* tree.c (trivially_copyable_p): Check CP_TYPE_VOLATILE_P for
class types too.
* tree.c (trivial_type_p): Check CP_TYPE_VOLATILE_P.

/testsuite
2015-01-20  Ville Voutilainen  ville.voutilai...@gmail.com

PR c++/63959
* g++.dg/cpp0x/trivial1.C: Adjust.
* g++.dg/ext/is_trivially_constructible1.C: Adjust.

/testsuite
2015-01-20  Ville Voutilainen  ville.voutilai...@gmail.com

PR c++/63959
* 20_util/has_trivial_copy_constructor/value.cc: Adjust.
* 20_util/has_trivial_default_constructor/value.cc: Adjust.
* 20_util/is_pod/value.cc: Adjust.
* 20_util/is_trivial/value.cc: Adjust.
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/semantics.c b/gcc/cp/semantics.c
index 15b8d01..67152cd 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7383,7 +7383,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   type1 = strip_array_types (type1);
-  return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
+  return (trivial_type_p (type1)
+ || (scalarish_type_p (type1)  CP_TYPE_VOLATILE_P (type1))
+ || type_code1 == REFERENCE_TYPE
  || (CLASS_TYPE_P (type1)
   TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 80f2ce6..79be556 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);
 }
@@ -3228,7 +3229,7 @@ trivial_type_p (const_tree t)
 return (TYPE_HAS_TRIVIAL_DFLT (t)
 trivially_copyable_p (t));
   else
-return scalarish_type_p (t);
+return !CP_TYPE_VOLATILE_P (t)  scalarish_type_p (t);
 }
 
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C 
b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 3fed570..d0d7b46 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -18,6 +18,9 @@
 #define TRY(expr) static_assert (expr, #expr)
 #define YES(type) TRY(std::is_trivialtype::value); \
   TRY(std::is_trivialtype[]::value); \
+  TRY(!std::is_trivialconst volatile type::value)
+#define YES2(type) TRY(std::is_trivialtype::value); \
+  TRY(std::is_trivialtype[]::value); \
   TRY(std::is_trivialconst volatile type::value)
 #define NO(type) 

Re: [C++ PATCH, RFC] PR c++/63959, continued

2015-01-19 Thread Ville Voutilainen
On 19 January 2015 at 18:28, Ville Voutilainen
ville.voutilai...@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.