diff options
author | Antony Polukhin <antoshkka@gmail.com> | 2019-05-31 10:35:03 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2019-05-31 10:35:03 +0000 |
commit | 5db412c46d3c2da555246c664adeb8f9148c6ad9 (patch) | |
tree | de5f6c1cbbc45c5383532c6088dce9fa44f24b70 /libstdc++-v3/testsuite/20_util | |
parent | ee8d6756e5005314f180153297662009a1656974 (diff) |
PR libstdc++/71579 assert that type traits are not misused with incomplete types
This patch adds static asserts for type traits misuse with incomplete
classes and unions. This gives a nice readable error message instead
of an UB and odr-violations.
Some features of the patch:
* each type trait has it's own static_assert inside. This gives better
diagnostics than the approach with putting the assert into a helper
structure and using it in each trait.
* the result of completeness check is not memorized by the compiler.
This gives no false positive after the first failed check.
* some of the compiler builtins already implement the check. But not
all of them! So the asserts are in all the type_traits that may
benefit from the check. This also makes the behavior of libstdc++ more
consistent across different (non GCC) compilers.
* std::is_base_of does not have the assert as it works well in many
cases with incomplete types
2019-05-31 Antony Polukhin <antoshkka@gmail.com>
PR libstdc++/71579
* include/std/type_traits __type_identity, __is_complete_or_unbounded):
New helpers for checking preconditions in traits.
(is_trivial, is_trivially_copyable, is_standard_layout, is_pod)
(is_literal_type, is_empty, is_polymorphic, is_final, is_abstract)
(is_destructible, is_nothrow_destructible, is_constructible)
(is_default_constructible, is_copy_constructible)
(is_move_constructible, is_nothrow_default_constructible)
(is_nothrow_constructible, is_nothrow_copy_constructible)
(is_nothrow_move_constructible, is_copy_assignable, is_move_assignable)
(is_nothrow_assignable, is_nothrow_copy_assignable)
(is_nothrow_move_assignable, is_trivially_constructible)
(is_trivially_copy_constructible, is_trivially_move_constructible)
is_trivially_assignable, is_trivially_copy_assignable)
(is_trivially_move_assignable, is_trivially_destructible)
(alignment_of, is_swappable, is_nothrow_swappable, is_invocable)
(is_invocable_r, is_nothrow_invocable)
(has_unique_object_representations, is_aggregate): Add static_asserts
to make sure that type traits are not misused with incomplete types.
(__is_constructible_impl, __is_nothrow_default_constructible_impl)
(__is_nothrow_constructible_impl, __is_nothrow_assignable_impl): New
base characteristics without assertions that can be reused in other
traits.
* testsuite/20_util/is_complete_or_unbounded/memoization.cc: New test.
* testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc: New
test.
* testsuite/20_util/is_complete_or_unbounded/value.cc: New test.
* testsuite/20_util/is_abstract/incomplete_neg.cc: New test.
* testsuite/20_util/is_aggregate/incomplete_neg.cc: New test.
* testsuite/20_util/is_class/value.cc: Check incomplete type.
* testsuite/20_util/is_function/value.cc: Likewise.
* testsuite/20_util/is_move_constructible/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc: New
test.
* testsuite/20_util/is_polymorphic/incomplete_neg.cc: New test.
* testsuite/20_util/is_reference/value.cc: Check incomplete types.
* testsuite/20_util/is_unbounded_array/value.cc: Likewise.
* testsuite/20_util/is_union/value.cc: Likewise.
* testsuite/20_util/is_void/value.cc: Likewise.
* testsuite/util/testsuite_tr1.h: Add incomplete union type.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@271806 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/testsuite/20_util')
14 files changed, 316 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc new file mode 100644 index 00000000000..94f4ecd6000 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc @@ -0,0 +1,29 @@ +// { dg-do compile { target c++11 } } +// { dg-prune-output "invalid use of incomplete type" } +// { dg-prune-output "must be a complete" } +// +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + +class X; + +void test01() +{ + std::is_abstract<X>(); // { dg-error "required from here" } +} diff --git a/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc new file mode 100644 index 00000000000..8a3dd551cbb --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc @@ -0,0 +1,29 @@ +// { dg-do compile { target c++17 } } +// +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-error "must be a complete class" "" { target *-*-* } 0 } + +#include <type_traits> + +class X; + +void test01() +{ + std::is_aggregate<X>(); // { dg-error "required from here" } +} diff --git a/libstdc++-v3/testsuite/20_util/is_class/value.cc b/libstdc++-v3/testsuite/20_util/is_class/value.cc index 6391e286147..801dc679a21 100644 --- a/libstdc++-v3/testsuite/20_util/is_class/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_class/value.cc @@ -27,6 +27,7 @@ void test01() // Positive tests. static_assert(test_category<is_class, ClassType>(true), ""); + static_assert(test_category<is_class, IncompleteClass>(true), ""); static_assert(test_category<is_class, DerivedType>(true), ""); static_assert(test_category<is_class, ConvType>(true), ""); static_assert(test_category<is_class, AbstractClass>(true), ""); @@ -47,4 +48,5 @@ void test01() static_assert(test_category<is_class, int (ClassType::*) (int)>(false), ""); static_assert(test_category<is_class, int (int)>(false), ""); static_assert(test_category<is_class, EnumType>(false), ""); + static_assert(test_category<is_class, IncompleteUnion>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc new file mode 100644 index 00000000000..83afb40cd18 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc @@ -0,0 +1,29 @@ +// { dg-do compile { target c++11 } } + +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + +struct X; +static_assert( + !std::__is_complete_or_unbounded(std::__type_identity<X>{}), "error"); + +struct X{}; +static_assert( + std::__is_complete_or_unbounded(std::__type_identity<X>{}), + "Result memoized. This leads to worse diagnostics"); diff --git a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc new file mode 100644 index 00000000000..04b83a21c01 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc @@ -0,0 +1,27 @@ +// { dg-do compile { target c++11 } } +// { dg-prune-output "must be a complete" } + +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + +struct X; +constexpr bool res_incomplete = std::is_move_constructible<X>::value; // { dg-error "required from here" } + +struct X{}; +constexpr bool res_complete = std::is_default_constructible<X>::value; // { dg-bogus "required from here" } diff --git a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/value.cc b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/value.cc new file mode 100644 index 00000000000..5a03ad67a30 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/value.cc @@ -0,0 +1,100 @@ +// { dg-do compile { target c++11 } } + +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + + +struct incomplete_type; +class incomplete_type2; +union incomplete_union; +enum class incomplete_enum: int; +enum incomplete_enum2: int; +static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type>{}), ""); +static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type2>{}), ""); +static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_union>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum2>{}), ""); + +static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type[42]>{}), ""); +static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type2[42]>{}), ""); +static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_union[42]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum[42]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum2[42]>{}), ""); + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type2[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_union[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum2[]>{}), ""); + + +struct complete_type{ ~complete_type() = delete; }; +class complete_type2{ int i; }; +union complete_union{}; +enum class complete_enum: int {}; +enum complete_enum2: int {}; +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type2>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_union>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum2>{}), ""); + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type[42]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type2[42]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_union[42]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum[42]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum2[42]>{}), ""); + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type2[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_union[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum[]>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum2[]>{}), ""); + + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_type>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_type2>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_union>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_enum>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_enum2>{}), ""); + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const incomplete_type*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_type*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type&&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type&&>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<int complete_type::*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<int (complete_type::*)(int)>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<int incomplete_type::*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<int (incomplete_type::*)(int)>{}), ""); + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(*)() noexcept>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(...) noexcept>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(&)(int)>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(*)()>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(incomplete_type)>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(&)()>{}), ""); + +static_assert(std::__is_complete_or_unbounded(std::__type_identity<std::nullptr_t>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<void*>{}), ""); +static_assert(std::__is_complete_or_unbounded(std::__type_identity<const void* const>{}), ""); diff --git a/libstdc++-v3/testsuite/20_util/is_function/value.cc b/libstdc++-v3/testsuite/20_util/is_function/value.cc index cef2e3de2a1..7b94b58b6cb 100644 --- a/libstdc++-v3/testsuite/20_util/is_function/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_function/value.cc @@ -46,4 +46,6 @@ void test01() // Sanity check. static_assert(test_category<is_function, ClassType>(false), ""); + static_assert(test_category<is_function, IncompleteClass>(false), ""); + static_assert(test_category<is_function, IncompleteUnion>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_move_constructible/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_move_constructible/incomplete_neg.cc new file mode 100644 index 00000000000..d6a08d77639 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_move_constructible/incomplete_neg.cc @@ -0,0 +1,29 @@ +// { dg-do compile { target c++11 } } +// +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-error "must be a complete class" "" { target *-*-* } 0 } + +#include <type_traits> + +class X; + +void test01() +{ + std::is_move_constructible<X>(); // { dg-error "required from here" } +} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc new file mode 100644 index 00000000000..ebceec5474b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc @@ -0,0 +1,29 @@ +// { dg-do compile { target c++11 } } +// +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-error "must be a complete class" "" { target *-*-* } 0 } + +#include <type_traits> + +class X; + +void test01() +{ + std::is_nothrow_move_assignable<X>(); // { dg-error "required from here" } +} diff --git a/libstdc++-v3/testsuite/20_util/is_polymorphic/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_polymorphic/incomplete_neg.cc new file mode 100644 index 00000000000..8cd1b402a41 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_polymorphic/incomplete_neg.cc @@ -0,0 +1,29 @@ +// { dg-do compile { target c++11 } } +// { dg-prune-output "invalid use of incomplete type" } +// { dg-prune-output "must be a complete" } +// +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <type_traits> + +class X; + +void test01() +{ + std::is_polymorphic<X>(); // { dg-error "required from here" } +} diff --git a/libstdc++-v3/testsuite/20_util/is_reference/value.cc b/libstdc++-v3/testsuite/20_util/is_reference/value.cc index 79a99737eab..4676894a5e9 100644 --- a/libstdc++-v3/testsuite/20_util/is_reference/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_reference/value.cc @@ -33,8 +33,11 @@ void test01() static_assert(test_category<is_reference, int&&>(true), ""); static_assert(test_category<is_reference, ClassType&&>(true), ""); static_assert(test_category<is_reference, int(&&)(int)>(true), ""); + static_assert(test_category<is_reference, IncompleteClass&>(true), ""); + static_assert(test_category<is_reference, const IncompleteClass&>(true), ""); // Sanity check. static_assert(test_category<is_reference, ClassType>(false), ""); + static_assert(test_category<is_reference, IncompleteClass>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_unbounded_array/value.cc b/libstdc++-v3/testsuite/20_util/is_unbounded_array/value.cc index 19fb0524cd8..bca0e3cb82e 100644 --- a/libstdc++-v3/testsuite/20_util/is_unbounded_array/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_unbounded_array/value.cc @@ -44,6 +44,8 @@ void test01() static_assert(test_category<is_unbounded_array, ClassType[]>(true), ""); static_assert(test_category<is_unbounded_array, ClassType[2][3]>(false), ""); static_assert(test_category<is_unbounded_array, ClassType[][3]>(true), ""); + static_assert(test_category<is_unbounded_array, IncompleteClass[2][3]>(false), ""); + static_assert(test_category<is_unbounded_array, IncompleteClass[][3]>(true), ""); static_assert(test_category<is_unbounded_array, int(*)[2]>(false), ""); static_assert(test_category<is_unbounded_array, int(*)[]>(false), ""); static_assert(test_category<is_unbounded_array, int(&)[2]>(false), ""); @@ -51,6 +53,8 @@ void test01() // Sanity check. static_assert(test_category<is_unbounded_array, ClassType>(false), ""); + static_assert(test_category<is_unbounded_array, IncompleteClass>(false), ""); + static_assert(test_category<is_unbounded_array, IncompleteUnion>(false), ""); } template <class... T> void pos() diff --git a/libstdc++-v3/testsuite/20_util/is_union/value.cc b/libstdc++-v3/testsuite/20_util/is_union/value.cc index 7d0f2011fca..54df151e025 100644 --- a/libstdc++-v3/testsuite/20_util/is_union/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_union/value.cc @@ -27,6 +27,7 @@ void test01() // Positive tests. static_assert(test_category<is_union, UnionType>(true), ""); + static_assert(test_category<is_union, IncompleteUnion>(true), ""); // Negative tests. static_assert(test_category<is_union, ClassType>(false), ""); @@ -47,4 +48,5 @@ void test01() static_assert(test_category<is_union, int (ClassType::*) (int)>(false), ""); static_assert(test_category<is_union, int (int)>(false), ""); static_assert(test_category<is_union, EnumType>(false), ""); + static_assert(test_category<is_union, IncompleteClass>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_void/value.cc b/libstdc++-v3/testsuite/20_util/is_void/value.cc index f04cdd61ad7..dc116f7ad09 100644 --- a/libstdc++-v3/testsuite/20_util/is_void/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_void/value.cc @@ -47,4 +47,6 @@ void test01() // Sanity check. static_assert(test_category<is_void, ClassType>(false), ""); + static_assert(test_category<is_void, IncompleteClass>(false), ""); + static_assert(test_category<is_void, IncompleteUnion>(false), ""); } |