[C++ PATCH, RFC] PR c++/63959, continued
Ville Voutilainen
ville.voutilainen@gmail.com
Mon Jan 19 23:06:00 GMT 2015
On 19 January 2015 at 21:12, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> 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.
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.voutilainen@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.voutilainen@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.voutilainen@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.
-------------- next part --------------
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_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), "");
}
More information about the Libstdc++
mailing list