diff mbox

[C++,RFC] PR c++/63959, continued

Message ID CAFk2RUZ3rAxTSwnO44JycT_+r_DSY8a1w5LSi8bE+JPcdFiX1A@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen Jan. 20, 2015, 2:27 p.m. UTC
On 20 January 2015 at 15:06, Jason Merrill <jason@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. :)

Comments

Jason Merrill Jan. 30, 2015, 5:46 p.m. UTC | #1
On 01/20/2015 09:27 AM, Ville Voutilainen wrote:
> +#define YES2(type) TRY(std::is_trivial<type>::value); \
> +  TRY(std::is_trivial<type[]>::value); \
>     TRY(std::is_trivial<const volatile type>::value)

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

Why would void *const volatile still be trivial?

Jason
Ville Voutilainen Jan. 30, 2015, 6:13 p.m. UTC | #2
On 30 January 2015 at 19:46, Jason Merrill <jason@redhat.com> wrote:
> On 01/20/2015 09:27 AM, Ville Voutilainen wrote:
>>
>> +#define YES2(type) TRY(std::is_trivial<type>::value); \
>> +  TRY(std::is_trivial<type[]>::value); \
>>     TRY(std::is_trivial<const volatile type>::value)
>
>
>> +YES2(void *);
>> +YES2(int A::*);
>
>
> Why would void *const volatile still be trivial?

Arrrrggggh. It isn't. YES and YES2 are macros, so YES2(void*) expands to
is_trivial<const volatile void*>::value, which is true, whereas
is_trivial<void* const volatile>::value is false.

I think it would be reasonable to convert these macros in that test into
function templates, no? :)
Jason Merrill Jan. 30, 2015, 6:25 p.m. UTC | #3
On 01/30/2015 01:13 PM, Ville Voutilainen wrote:
>> Why would void *const volatile still be trivial?
>
> Arrrrggggh. It isn't. YES and YES2 are macros, so YES2(void*) expands to
> is_trivial<const volatile void*>::value, which is true, whereas
> is_trivial<void* 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
diff mbox

Patch

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_trivial<type>::value); \
   TRY(std::is_trivial<type[]>::value); \
+  TRY(!std::is_trivial<const volatile type>::value)
+#define YES2(type) TRY(std::is_trivial<type>::value); \
+  TRY(std::is_trivial<type[]>::value); \
   TRY(std::is_trivial<const volatile type>::value)
 #define NO(type) TRY(!std::is_trivial<type>::value); \
   TRY(!std::is_trivial<type[]>::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.
-  static_assert(test_category<has_trivial_copy_constructor, int>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor, float>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		EnumType>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor, int*>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		int(*)(int)>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		int (ClassType::*)>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		int (ClassType::*) (int)>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor, int[2]>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		float[][3]>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		EnumType[2][3][4]>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor, int*[3]>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		int(*[][2])(int)>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		int (ClassType::*[2][3])>(true), "");
-  static_assert(test_category<has_trivial_copy_constructor,
-		int (ClassType::*[][2][3]) (int)>(true), "");
-
-  // Negative tests.  
-  static_assert(test_category<has_trivial_copy_constructor, void>(false), "");  
+  static_assert(has_trivial_copy_constructor<int>::value, "");
+  static_assert(has_trivial_copy_constructor<const int>::value, "");
+  static_assert(has_trivial_copy_constructor<float>::value, "");
+  static_assert(has_trivial_copy_constructor<const float>::value, "");
+  static_assert(has_trivial_copy_constructor<EnumType>::value, "");
+  static_assert(has_trivial_copy_constructor<int*>::value, "");
+  static_assert(has_trivial_copy_constructor<int(*)(int)>::value, "");
+  static_assert(has_trivial_copy_constructor<int (ClassType::*)>::value, "");
+  static_assert(has_trivial_copy_constructor<int (ClassType::*) (int)>
+		::value, "");
+  static_assert(has_trivial_copy_constructor<int[2]>::value, "");
+  static_assert(has_trivial_copy_constructor<float[][3]>::value, "");
+  static_assert(has_trivial_copy_constructor<EnumType[2][3][4]>::value, "");
+  static_assert(has_trivial_copy_constructor<int*[3]>::value, "");
+  static_assert(has_trivial_copy_constructor<int(*[][2])(int)>::value, "");
+  static_assert(has_trivial_copy_constructor<int (ClassType::*[2][3])>
+		::value, "");
+  static_assert(has_trivial_copy_constructor<
+		int (ClassType::*[][2][3]) (int)>::value, "");
+  static_assert(test_category<has_trivial_copy_constructor,
+		ClassType>(true), "");
+  // Negative tests.
+  static_assert(test_category<has_trivial_copy_constructor,
+		void>(false), "");  
+  static_assert(!has_trivial_copy_constructor<volatile int>::value, "");
+  static_assert(!has_trivial_copy_constructor<const volatile int>
+		::value, "");
 }
diff --git a/libstdc++-v3/testsuite/20_util/has_trivial_default_constructor/value.cc b/libstdc++-v3/testsuite/20_util/has_trivial_default_constructor/value.cc
index 7111274..766a792 100644
--- a/libstdc++-v3/testsuite/20_util/has_trivial_default_constructor/value.cc
+++ b/libstdc++-v3/testsuite/20_util/has_trivial_default_constructor/value.cc
@@ -31,36 +31,31 @@  void test01()
   using namespace __gnu_test;
 
   // Positive tests.
-  static_assert(test_category<has_trivial_default_constructor, int>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		float>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		EnumType>(true), "");
-  static_assert(test_category<has_trivial_default_constructor, int*>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int(*)(int)>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int (ClassType::*)>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int (ClassType::*) (int)>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int[2]>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		float[][3]>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		EnumType[2][3][4]>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int*[3]>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int(*[][2])(int)>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int (ClassType::*[2][3])>(true), "");
-  static_assert(test_category<has_trivial_default_constructor,
-		int (ClassType::*[][2][3]) (int)>(true), "");
+  static_assert(has_trivial_default_constructor<int>::value, "");
+  static_assert(has_trivial_default_constructor<const int>::value, "");
+  static_assert(has_trivial_default_constructor<float>::value, "");
+  static_assert(has_trivial_default_constructor<const float>::value, "");
+  static_assert(has_trivial_default_constructor<EnumType>::value, "");
+  static_assert(has_trivial_default_constructor<int*>::value, "");
+  static_assert(has_trivial_default_constructor<int(*)(int)>::value, "");
+  static_assert(has_trivial_default_constructor<int (ClassType::*)>::value, "");
+  static_assert(has_trivial_default_constructor<int (ClassType::*) (int)>
+		::value, "");
+  static_assert(has_trivial_default_constructor<int[2]>::value, "");
+  static_assert(has_trivial_default_constructor<float[][3]>::value, "");
+  static_assert(has_trivial_default_constructor<EnumType[2][3][4]>::value, "");
+  static_assert(has_trivial_default_constructor<int*[3]>::value, "");
+  static_assert(has_trivial_default_constructor<int(*[][2])(int)>::value, "");
+  static_assert(has_trivial_default_constructor<int (ClassType::*[2][3])>
+		::value, "");
+  static_assert(has_trivial_default_constructor<
+		int (ClassType::*[][2][3]) (int)>::value, "");
   static_assert(test_category<has_trivial_default_constructor,
 		ClassType>(true), "");
-
   // Negative tests.
   static_assert(test_category<has_trivial_default_constructor,
 		void>(false), "");  
+  static_assert(!has_trivial_default_constructor<volatile int>::value, "");
+  static_assert(!has_trivial_default_constructor<const volatile int>
+		::value, "");
 }
diff --git a/libstdc++-v3/testsuite/20_util/is_pod/value.cc b/libstdc++-v3/testsuite/20_util/is_pod/value.cc
index 8e0237e..5beba46 100644
--- a/libstdc++-v3/testsuite/20_util/is_pod/value.cc
+++ b/libstdc++-v3/testsuite/20_util/is_pod/value.cc
@@ -43,9 +43,14 @@  void test01()
   static_assert(test_category<is_pod, int (ClassType::*[2][3])>(true), "");
   static_assert(test_category<is_pod,
 		int (ClassType::*[][2][3]) (int)>(true), "");
-  static_assert(test_category<is_pod, ClassType>(true), "");
-  static_assert(test_category<is_pod, PODType>(true), "");
-
+  static_assert(is_pod<ClassType>::value, "");
+  static_assert(is_pod<const ClassType>::value, "");
+  static_assert(!is_pod<const volatile ClassType>::value, "");
+  static_assert(!is_pod<volatile ClassType>::value, "");
+  static_assert(is_pod<PODType>::value, "");
+  static_assert(is_pod<const PODType>::value, "");
+  static_assert(!is_pod<const volatile PODType>::value, "");
+  static_assert(!is_pod<volatile PODType>::value, "");
   static_assert(test_category<is_pod, void>(false), "");
   static_assert(test_category<is_pod, NType>(false), "");
   static_assert(test_category<is_pod, TType>(false), "");
diff --git a/libstdc++-v3/testsuite/20_util/is_trivial/value.cc b/libstdc++-v3/testsuite/20_util/is_trivial/value.cc
index ffc8acb..bb193bd 100644
--- a/libstdc++-v3/testsuite/20_util/is_trivial/value.cc
+++ b/libstdc++-v3/testsuite/20_util/is_trivial/value.cc
@@ -28,9 +28,14 @@  void test01()
   using std::is_trivial;
   using namespace __gnu_test;
 
-  static_assert(test_category<is_trivial, TType>(true), "");
-  static_assert(test_category<is_trivial, PODType>(true), "");
-
+  static_assert(is_trivial<TType>::value, "");
+  static_assert(is_trivial<const TType>::value, "");
+  static_assert(!is_trivial<volatile TType>::value, "");
+  static_assert(!is_trivial<const volatile TType>::value, "");
+  static_assert(is_trivial<PODType>::value, "");
+  static_assert(is_trivial<const PODType>::value, "");
+  static_assert(!is_trivial<volatile PODType>::value, "");
+  static_assert(!is_trivial<const volatile PODType>::value, "");
   static_assert(test_category<is_trivial, NType>(false), "");
   static_assert(test_category<is_trivial, SLType>(false), "");
 }