Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2021-05-07 Thread Antony Polukhin via Gcc-patches
Rebased the patch on current master. Please review.

Changelog stays the same:

New std::common_type assertions attempt to give a proper 'required from
here' hint for user code, do not bring many changes to the
implementation and check all the template parameters for completeness.
In some cases the type could be checked for completeness more than
once. This seems to be unsolvable due to the fact that
std::common_type could be specialized by the user, so we have to call
std::common_type recursively, potentially repeating the check for the
first type.

std::common_reference assertions make sure that we detect incomplete
types even if the user specialized the std::basic_common_reference.

2020-11-12  Antony Polukhin  
PR libstdc/71579
* include/std/type_traits (is_convertible, is_nothrow_convertible)
(common_type, common_reference): Add static_asserts
to make sure that the arguments of the type traits are not misused
with incomplete types.
* testsuite/20_util/common_reference/incomplete_basic_common_neg.cc:
New test.
* testsuite/20_util/common_reference/incomplete_neg.cc: New test.
* testsuite/20_util/common_type/incomplete_neg.cc: New test.
* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc: Remove
SFINAE tests on incomplete types.
* testsuite/20_util/is_convertible/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_convertible/incomplete_neg.cc: New test.

пт, 8 янв. 2021 г. в 20:28, Antony Polukhin :
>
>
> On Thu, Nov 12, 2020, 21:55 Antony Polukhin  wrote:
>>
>> Final bits for libstdc/71579
>
>
> Gentle reminder on last patch



-- 
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index eaf06fc..a95d327 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1406,12 +1406,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_convertible
 : public __is_convertible_helper<_From, _To>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_From>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_To>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
   // helper trait for unique_ptr, shared_ptr, and span
   template
 using __is_array_convertible
-  = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>;
+  = typename __is_convertible_helper<
+   _FromElementType(*)[], _ToElementType(*)[]>::type;
 
   template, is_function<_To>,
@@ -1454,7 +1460,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_nothrow_convertible
 : public __is_nt_convertible_helper<_From, _To>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_From>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_To>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
   /// is_nothrow_convertible_v
   template
@@ -2239,7 +2250,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct common_type<_Tp1, _Tp2>
 : public __common_type_impl<_Tp1, _Tp2>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp1>{}),
+   "each argument type must be a complete class or an unbounded array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp2>{}),
+   "each argument type must be a complete class or an unbounded array");
+};
 
   template
 struct __common_type_pack
@@ -2253,7 +2269,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct common_type<_Tp1, _Tp2, _Rp...>
 : public __common_type_fold,
__common_type_pack<_Rp...>>
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp1>{}),
+   "first argument type must be a complete class or an unbounded array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp2>{}),
+   "second argument type must be a complete class or an unbounded array");
+#ifdef __cpp_fold_expressions
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_Rp>{}) && ...),
+   "each argument type must be a complete class or an unbounded array");
+#endif
+};
 
   // Let C denote the same type, if any, as common_type_t.
   // If there is such a type C, type shall denote the same type, if any,
@@ -3352,9 +3378,10 @@ template 
 
   // If A and B are both rvalue reference types, ...
   template
-struct __common_ref_impl<_Xp&&, _Yp&&,
-  _Require>,
-  is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp
+struct __common_ref_impl<_Xp&&, _Yp&&, _Require<
+  typename __is_convertible_helper<_Xp&&, 

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2021-01-08 Thread Antony Polukhin via Gcc-patches
On Thu, Nov 12, 2020, 21:55 Antony Polukhin  wrote:

> Final bits for libstdc/71579
>

Gentle reminder on last patch

>


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-11-12 Thread Antony Polukhin via Gcc-patches
Final bits for libstdc/71579

std::common_type assertions attempt to give a proper 'required from
here' hint for user code, do not bring many changes to the
implementation and check all the template parameters for completeness.
In some cases the type could be checked for completeness more than
once. This seems to be unsolvable due to the fact that
std::common_type could be specialized by the user, so we have to call
std::common_type recursively, potentially repeating the check for the
first type.

std::common_reference assertions make sure that we detect incomplete
types even if the user specialized the std::basic_common_reference.

Changelog:

2020-11-12  Antony Polukhin  
PR libstdc/71579
* include/std/type_traits (is_convertible, is_nothrow_convertible)
(common_type, common_reference): Add static_asserts
to make sure that the arguments of the type traits are not misused
with incomplete types.
* testsuite/20_util/common_reference/incomplete_basic_common_neg.cc:
New test.
* testsuite/20_util/common_reference/incomplete_neg.cc: New test.
* testsuite/20_util/common_type/incomplete_neg.cc: New test.
* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc: Remove
SFINAE tests on incomplete types.
* testsuite/20_util/is_convertible/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_convertible/incomplete_neg.cc: New test.



--
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 34e068b..00fa7f5 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1406,12 +1406,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_convertible
 : public __is_convertible_helper<_From, _To>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_From>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_To>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
   // helper trait for unique_ptr, shared_ptr, and span
   template
 using __is_array_convertible
-  = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>;
+  = typename __is_convertible_helper<
+   _FromElementType(*)[], _ToElementType(*)[]>::type;
 
   template, is_function<_To>,
@@ -1454,7 +1460,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_nothrow_convertible
 : public __is_nt_convertible_helper<_From, _To>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_From>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_To>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
   /// is_nothrow_convertible_v
   template
@@ -2239,7 +2250,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct common_type<_Tp1, _Tp2>
 : public __common_type_impl<_Tp1, _Tp2>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp1>{}),
+   "each argument type must be a complete class or an unbounded array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp2>{}),
+   "each argument type must be a complete class or an unbounded array");
+};
 
   template
 struct __common_type_pack
@@ -2253,7 +2269,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct common_type<_Tp1, _Tp2, _Rp...>
 : public __common_type_fold,
__common_type_pack<_Rp...>>
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp1>{}),
+   "first argument type must be a complete class or an unbounded array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp2>{}),
+   "second argument type must be a complete class or an unbounded array");
+#ifdef __cpp_fold_expressions
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_Rp>{}) && ...),
+   "each argument type must be a complete class or an unbounded array");
+#endif
+};
 
   // Let C denote the same type, if any, as common_type_t.
   // If there is such a type C, type shall denote the same type, if any,
@@ -3315,9 +3341,10 @@ template 
 
   // If A and B are both rvalue reference types, ...
   template
-struct __common_ref_impl<_Xp&&, _Yp&&,
-  _Require>,
-  is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp
+struct __common_ref_impl<_Xp&&, _Yp&&, _Require<
+  typename __is_convertible_helper<_Xp&&, __common_ref_C<_Xp, _Yp>>::type,
+  typename __is_convertible_helper<_Yp&&, __common_ref_C<_Xp, _Yp>>::type
+>>
 { using type = __common_ref_C<_Xp, _Yp>; };
 
   // let D be COMMON-REF(const X&, Y&)
@@ -3326,8 

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-09-24 Thread Jonathan Wakely via Gcc-patches

On 20/08/20 18:31 +0300, Antony Polukhin via Libstdc++ wrote:

ср, 19 авг. 2020 г. в 14:29, Jonathan Wakely :
<...>

Do we also want to check
(std::__is_complete_or_unbounded(__type_identity<_ArgTypes>{}) && ...)
for invoke_result and the is_invocable traits?


Done.

Changelog:

2020-08-20  Antony Polukhin  

   PR libstdc/71579
   * include/std/type_traits (invoke_result, is_invocable, is_invocable_r)
   (is_nothrow_invocable, is_nothrow_invocable_r): Add static_asserts
   to make sure that the arguments of the type traits are not misused
   with incomplete types.`
   * testsuite/20_util/invoke_result/incomplete_args_neg.cc: New test.
   * testsuite/20_util/is_invocable/incomplete_args_neg.cc: New test.
   * testsuite/20_util/is_invocable/incomplete_neg.cc: New test.
   * testsuite/20_util/is_nothrow_invocable/incomplete_args_neg.cc: New test.
   * testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc: Check for
   error on incomplete response type usage in trait.


Committed with some tweaks to the static assert messages to say:

"each argument type must be a complete class or an unbounded array"

Thanks!




Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-09-24 Thread Jonathan Wakely via Gcc-patches

On 24/09/20 10:15 +0300, Antony Polukhin via Libstdc++ wrote:

Looks like the last patch was not applied. Do I have to change something in
it?


No, it just hasn't been reviewed yet.




Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-09-24 Thread Antony Polukhin via Gcc-patches
Looks like the last patch was not applied. Do I have to change something in
it?


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-08-20 Thread Antony Polukhin via Gcc-patches
ср, 19 авг. 2020 г. в 14:29, Jonathan Wakely :
<...>
> Do we also want to check
> (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>{}) && ...)
> for invoke_result and the is_invocable traits?

Done.

Changelog:

2020-08-20  Antony Polukhin  

PR libstdc/71579
* include/std/type_traits (invoke_result, is_invocable, is_invocable_r)
(is_nothrow_invocable, is_nothrow_invocable_r): Add static_asserts
to make sure that the arguments of the type traits are not misused
with incomplete types.`
* testsuite/20_util/invoke_result/incomplete_args_neg.cc: New test.
* testsuite/20_util/is_invocable/incomplete_args_neg.cc: New test.
* testsuite/20_util/is_invocable/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_invocable/incomplete_args_neg.cc: New test.
* testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc: Check for
error on incomplete response type usage in trait.


-- 
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 6ced781..bf2260a 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2965,6 +2965,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   
static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}),
"_Functor must be a complete class or an unbounded array");
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_ArgTypes>{}) && ...),
+   "Argument types must be a complete class or an unbounded array");
 };
 
   /// std::invoke_result_t
@@ -2978,6 +2981,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
"_Fn must be a complete class or an unbounded array");
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_ArgTypes>{}) && ...),
+   "Argument types must be a complete class or an unbounded array");
 };
 
   /// std::is_invocable_r
@@ -2987,6 +2993,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
"_Fn must be a complete class or an unbounded array");
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_ArgTypes>{}) && ...),
+   "Argument types must be a complete class or an unbounded array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}),
+   "_Ret must be a complete class or an unbounded array");
 };
 
   /// std::is_nothrow_invocable
@@ -2997,6 +3008,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
"_Fn must be a complete class or an unbounded array");
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_ArgTypes>{}) && ...),
+   "Argument types must be a complete class or an unbounded array");
 };
 
   template
@@ -3017,6 +3031,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
"_Fn must be a complete class or an unbounded array");
+  static_assert((std::__is_complete_or_unbounded(
+   __type_identity<_ArgTypes>{}) && ...),
+   "Argument types must be a complete class or an unbounded array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}),
+   "_Ret must be a complete class or an unbounded array");
 };
 
   /// std::is_invocable_v
diff --git 
a/libstdc++-v3/testsuite/20_util/invoke_result/incomplete_args_neg.cc 
b/libstdc++-v3/testsuite/20_util/invoke_result/incomplete_args_neg.cc
new file mode 100644
index 000..a35ff4c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/invoke_result/incomplete_args_neg.cc
@@ -0,0 +1,47 @@
+// { dg-do compile { target c++17 } }
+
+// Copyright (C) 2020 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
+// .
+
+// { dg-error "must be a complete class" "" { target *-*-* } 0 }
+
+#include 
+
+class X;
+
+void test01()
+{
+  std::invoke_result(); // { dg-error "required from 
here" }
+  std::invoke_result();   // { dg-error "required 
from here" }
+  std::invoke_result();   // { dg-error "required 
from here" 

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-08-19 Thread Antony Polukhin via Gcc-patches
ср, 19 авг. 2020 г. в 14:29, Jonathan Wakely :
<...>
> Do we also want to check
> (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>{}) && ...)
> for invoke_result and the is_invocable traits?
>
> We can use a fold expression there, because those traits are not
> defined before C++17.

Good idea. I'll try.

-- 
Best regards,
Antony Polukhin


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-08-19 Thread Jonathan Wakely via Gcc-patches

On 12/08/20 11:19 +0300, Antony Polukhin via Libstdc++ wrote:

Fixed patch for type traits hardening

Changelog

2020-08-12  Antony Polukhin  

   PR libstdc/71579
   * include/std/type_traits (invoke_result, is_nothrow_invocable_r)
   Add static_asserts to make sure that the argument of the type
   trait is not misused with incomplete types.
   (is_swappable_with, is_nothrow_swappable_with): Add static_asserts
   to make sure that the first and second arguments of the type trait
   are not misused with incomplete types.
   * testsuite/20_util/invoke_result/incomplete_neg.cc: New test.
   * testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc: New test.
   * testsuite/20_util/is_nothrow_swappable/incomplete_neg.cc: New test.
   * testsuite/20_util/is_nothrow_swappable_with/incomplete_neg.cc: New
   test.
   * testsuite/20_util/is_swappable_with/incomplete_neg.cc: New test.


Thanks, pushed to master.

Do we also want to check
(std::__is_complete_or_unbounded(__type_identity<_ArgTypes>{}) && ...)
for invoke_result and the is_invocable traits?

We can use a fold expression there, because those traits are not
defined before C++17.




Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2020-08-12 Thread Antony Polukhin via Gcc-patches
Fixed patch for type traits hardening

Changelog

2020-08-12  Antony Polukhin  

PR libstdc/71579
* include/std/type_traits (invoke_result, is_nothrow_invocable_r)
Add static_asserts to make sure that the argument of the type
trait is not misused with incomplete types.
(is_swappable_with, is_nothrow_swappable_with): Add static_asserts
to make sure that the first and second arguments of the type trait
are not misused with incomplete types.
* testsuite/20_util/invoke_result/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_swappable/incomplete_neg.cc: New test.
* testsuite/20_util/is_nothrow_swappable_with/incomplete_neg.cc: New
test.
* testsuite/20_util/is_swappable_with/incomplete_neg.cc: New test.


-- 
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 426febc..62f1190 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2811,13 +2811,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_swappable_with
 : public __is_swappable_with_impl<_Tp, _Up>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
   /// is_nothrow_swappable_with
   template
 struct is_nothrow_swappable_with
 : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
 #if __cplusplus >= 201402L
   /// is_swappable_with_v
@@ -2952,7 +2962,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct invoke_result
 : public __invoke_result<_Functor, _ArgTypes...>
-{ };
+{
+  
static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}),
+   "_Functor must be a complete class or an unbounded array");
+};
 
   /// std::invoke_result_t
   template
@@ -3001,7 +3014,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_nothrow_invocable_r
 : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>,
  __call_is_nothrow_<_Fn, _ArgTypes...>>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
+   "_Fn must be a complete class or an unbounded array");
+};
 
   /// std::is_invocable_v
   template
diff --git a/libstdc++-v3/testsuite/20_util/invoke_result/incomplete_neg.cc 
b/libstdc++-v3/testsuite/20_util/invoke_result/incomplete_neg.cc
new file mode 100644
index 000..da58a8b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/invoke_result/incomplete_neg.cc
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++17 } }
+
+// Copyright (C) 2020 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
+// .
+
+// { dg-error "must be a complete class" "" { target *-*-* } 0 }
+
+#include 
+
+class X;
+
+void test01()
+{
+  std::invoke_result();// { dg-error "required from 
here" }
+  std::invoke_result(); // { dg-error "required from here" }
+}
diff --git 
a/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc 
b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc
new file mode 100644
index 000..ad16809
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/incomplete_neg.cc
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++17 } }
+
+// Copyright (C) 2020 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 

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-06-20 Thread Antony Polukhin
чт, 20 июн. 2019 г. в 20:57, Ville Voutilainen :
>
> On Thu, 20 Jun 2019 at 20:49, Antony Polukhin  wrote:
> >
> > чт, 6 июн. 2019 г. в 15:19, Jonathan Wakely :
> > > I'm removing some of these assertions again, because they are either
> > > reundant or wrong.
> >
> > Thanks for cleaning up!
> >
> >
> > In attachment there is an additional patch for type traits hardening.
> >
> > Things that still remain unasserted are type traits  with variadic
> > template arguments. I have to came up with a proper solution for
> > providing a useful and lightweight diagnostics.
>
> I see a
> public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
> in this patch, followed by a trait-body that static_asserts. In such
> cases, I think we want
> to
> a) be really careful about duplicating compiler diagnostics with library ones
> b) look at the compiler diagnostics, and if they are lacking, improve them.
>
> ...because that's what Jonathan's cleanup was really about.
> In the test modifications of __is_trivially_assignable, this looks bloody
> suspicious:
>
> +// { dg-prune-output "invalid use of incomplete type" }
> +// { dg-prune-output "must be a complete" }
>
> No. Don't merge. We are not replacing diagnostics A with diagnostics
> B, we are ignoring existing
> diagnostics and adding more. Which is exactly what Jonathan's cleanup avoided.

Thanks for the review and clarifications. I'll fix the patch.



-- 
Best regards,
Antony Polukhin


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-06-20 Thread Ville Voutilainen
On Thu, 20 Jun 2019 at 20:49, Antony Polukhin  wrote:
>
> чт, 6 июн. 2019 г. в 15:19, Jonathan Wakely :
> > I'm removing some of these assertions again, because they are either
> > reundant or wrong.
>
> Thanks for cleaning up!
>
>
> In attachment there is an additional patch for type traits hardening.
>
> Things that still remain unasserted are type traits  with variadic
> template arguments. I have to came up with a proper solution for
> providing a useful and lightweight diagnostics.

I see a
public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
in this patch, followed by a trait-body that static_asserts. In such
cases, I think we want
to
a) be really careful about duplicating compiler diagnostics with library ones
b) look at the compiler diagnostics, and if they are lacking, improve them.

...because that's what Jonathan's cleanup was really about.
In the test modifications of __is_trivially_assignable, this looks bloody
suspicious:

+// { dg-prune-output "invalid use of incomplete type" }
+// { dg-prune-output "must be a complete" }

No. Don't merge. We are not replacing diagnostics A with diagnostics
B, we are ignoring existing
diagnostics and adding more. Which is exactly what Jonathan's cleanup avoided.


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-06-20 Thread Antony Polukhin
чт, 6 июн. 2019 г. в 15:19, Jonathan Wakely :
> I'm removing some of these assertions again, because they are either
> reundant or wrong.

Thanks for cleaning up!


In attachment there is an additional patch for type traits hardening.

Things that still remain unasserted are type traits  with variadic
template arguments. I have to came up with a proper solution for
providing a useful and lightweight diagnostics.

-- 
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index ac98c0d..9063fe5 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,28 @@
+2019-06-20  Antony Polukhin  
+
+   PR libstdc++/71579
+   * include/std/type_traits (is_assignable, is_nothrow_assignable)
+   (is_trivially_assignable, is_nothrow_invocable_r): Add static_asserts
+   to make sure that the second argument of the type trait is not misused
+   with incomplete types.
+   (is_convertible, is_nothrow_convertible, is_swappable_with)
+   (is_nothrow_swappable_with): Add static_asserts to make sure that the
+   first and second arguments of the type trait are not misused with
+   incomplete types.
+   invoke_result: Add static_asserts to make sure that the first argument
+   of the type trait is not misused with incomplete types.
+   * testsuite/20_util/invoke_result/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_assignable/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_convertible/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_nothrow_assignable/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_nothrow_convertible/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_nothrow_swappable/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_nothrow_swappable_with/incomplete_neg.cc: New
+   test.
+   * testsuite/20_util/is_swappable/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_swappable_with/incomplete_neg.cc: New test.
+   * testsuite/20_util/is_trivially_assignable/incomplete_neg.cc: New test.
+
 2019-06-20  Jonathan Wakely  
 
* acinclude.m4 (GLIBCXX_ENABLE_DEBUG): Only do debug build for final
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 7d4deb1..77fc94e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1106,7 +1106,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __bool_constant<__is_assignable(_Tp, _Up)>
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-   "template argument must be a complete class or an unbounded array");
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
+   "second template argument must be a complete class or an unbounded 
array");
 };
 
   template::value>
@@ -1168,7 +1170,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __is_nothrow_assignable_impl<_Tp, _Up>
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-   "template argument must be a complete class or an unbounded array");
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
+   "second template argument must be a complete class or an unbounded 
array");
 };
 
   template::value>
@@ -1313,7 +1317,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
 {
   static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-   "template argument must be a complete class or an unbounded array");
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
+   "second template argument must be a complete class or an unbounded 
array");
 };
 
   template::value>
@@ -1474,7 +1480,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_convertible
 : public __is_convertible_helper<_From, _To>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_From>{}),
+   "first template argument must be a complete class or an unbounded 
array");
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_To>{}),
+   "second template argument must be a complete class or an unbounded 
array");
+};
 
   template, is_function<_To>,
@@ -1516,7 +1527,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_nothrow_convertible
 : public __is_nt_convertible_helper<_From, _To>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_From>{}),
+   "_From must be a complete class or an unbounded array");
+  

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-06-06 Thread Jonathan Wakely

On 31/05/19 11:35 +0100, Jonathan Wakely wrote:

On 31/05/19 08:58 +0300, Antony Polukhin wrote:

On Thu, May 30, 2019, 19:38 Jonathan Wakely  wrote:
<...>


I've attached a relative diff, to be applied on top of yours, with my
suggested tweaks. Do you see any issues with it?

(If you're happy with those tweaks I can go ahead and apply this,
there's no need for an updated patch from you).



Looks good. Please apply!


Here's what I've tested and committed to trunk.

I decided to add a more detailed changelog too.


I'm removing some of these assertions again, because they are either
reundant or wrong.

Tested x86_64-linux, committed to trunk.


commit 6ffe4cf371688563be1680ffb75cc1160540cf2e
Author: redi 
Date:   Thu Jun 6 12:13:47 2019 +

Remove redundant static assertions in [meta.unary.prop] traits

The type property predicates that are implemented by a compiler builtin
already do the right checks in the compiler. The checks for complete
type or unbounded arrays were wrong for these types anyway.

* include/std/type_traits (is_empty, is_polymorphic, is_final)
(is_abstract, is_aggregate): Remove static_assert.
* testsuite/20_util/is_abstract/incomplete_neg.cc: Check for error
from builtin only.
* testsuite/20_util/is_aggregate/incomplete_neg.cc: Likewise. Add
missing -std=gnu++17 option.
* testsuite/20_util/is_empty/incomplete_neg.cc: New test.
* testsuite/20_util/is_final/incomplete_neg.cc: New test.
* testsuite/20_util/is_polymorphic/incomplete_neg.cc: Check for error
from builtin only.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@272000 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 78a113af415..e53d3c8d535 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -746,19 +746,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_empty
 : public integral_constant
-{
-  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-	"template argument must be a complete class or an unbounded array");
-};
+{ };
 
   /// is_polymorphic
   template
 struct is_polymorphic
 : public integral_constant
-{
-  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-	"template argument must be a complete class or an unbounded array");
-};
+{ };
 
 #if __cplusplus >= 201402L
 #define __cpp_lib_is_final 201402L
@@ -766,20 +760,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_final
 : public integral_constant
-{
-  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-	"template argument must be a complete class or an unbounded array");
-};
+{ };
 #endif
 
   /// is_abstract
   template
 struct is_abstract
 : public integral_constant
-{
-  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-	"template argument must be a complete class or an unbounded array");
-};
+{ };
 
   template::value>
@@ -3174,10 +3162,7 @@ template 
   template
 struct is_aggregate
 : bool_constant<__is_aggregate(remove_cv_t<_Tp>)>
-{
-  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
-	"template argument must be a complete class or an unbounded array");
-};
+{ };
 
   /// is_aggregate_v
   template
diff --git a/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc
index 94f4ecd6000..a2a73d01a06 100644
--- a/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/is_abstract/incomplete_neg.cc
@@ -1,7 +1,5 @@
 // { 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
@@ -19,6 +17,9 @@
 // with this library; see the file COPYING3.  If not see
 // .
 
+// Expect the compiler builtin to do the completeness check.
+// { dg-error "incomplete type" "" { target *-*-* } 0 }
+
 #include 
 
 class X;
diff --git a/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc
index 8a3dd551cbb..eff3f64c476 100644
--- a/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/is_aggregate/incomplete_neg.cc
@@ -1,5 +1,6 @@
+// { dg-options "-std=gnu++17" }
 // { 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
@@ -17,7 +18,8 @@
 // with this library; see the file COPYING3.  If 

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-05-31 Thread Jonathan Wakely

On 31/05/19 08:58 +0300, Antony Polukhin wrote:

On Thu, May 30, 2019, 19:38 Jonathan Wakely  wrote:
<...>


I've attached a relative diff, to be applied on top of yours, with my
suggested tweaks. Do you see any issues with it?

(If you're happy with those tweaks I can go ahead and apply this,
there's no need for an updated patch from you).



Looks good. Please apply!


Here's what I've tested and committed to trunk.

I decided to add a more detailed changelog too.



commit c877256d8a2b0f9383c1cd93c0b2907496c715db
Author: Jonathan Wakely 
Date:   Fri May 31 09:23:09 2019 +0100

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  

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.

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 3a622eb61e0..78a113af415 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -91,6 +91,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct conditional;
 
+  template 
+struct __type_identity {
+  using type = _Type;
+};
+
   template
 struct __or_;
 
@@ -177,6 +182,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #endif // C++17
 
+  // Forward declarations
+  template
+struct is_reference;
+  template
+struct is_function;
+  template
+struct 

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-05-30 Thread Antony Polukhin
On Thu, May 30, 2019, 19:38 Jonathan Wakely  wrote:
<...>

> I've attached a relative diff, to be applied on top of yours, with my
> suggested tweaks. Do you see any issues with it?
>
> (If you're happy with those tweaks I can go ahead and apply this,
> there's no need for an updated patch from you).
>

Looks good. Please apply!

>


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-05-30 Thread Jonathan Wakely

On 30/05/19 09:06 +0300, Antony Polukhin wrote:

чт, 9 мая 2019 г. в 00:10, Jonathan Wakely :


On 06/05/19 14:19 +0300, Antony Polukhin wrote:
>@@ -924,14 +984,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>   template
> struct is_default_constructible
> : public __is_default_constructible_safe<_Tp>::type
>-{ };
>+{
>+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
>+  "template argument must be a complete class or an unbounded array");
>+};
>
>   /// is_constructible

This "///" comment is for Doxygen, and should remain with the
is_constructible trait, not __is_constructible_impl.


Fixed that issue along with some other misplaced Doxygen comments.
Rebased the patch and removed some trailing white-spaces.


Thanks! Rebasing this was on my TODO list for today.


--
Best regards,
Antony Polukhin



diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b209460..c5f0672 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,27 @@
+2019-05-29  Antony Polukhin  
+
+   PR libstdc++/71579
+   * include/std/type_traits: Add static_asserts to make sure that
+   type traits are not misused with an incomplete type.


This changelog could be more explicit. It doesn't have to list every
changed trait, but maybe something like:

* include/std/type_traits: Add static_asserts to make sure that
type traits are not misused with an incomplete type. Create
   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:
+   Likewise.
+   * testsuite/20_util/__is_complete_or_unbounded/value.cc: Likewise.


I think I'd prefer not to have the double underscores in the directory
name here.


@@ -876,19 +935,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  template
struct is_nothrow_destructible
: public __is_nt_destructible_safe<_Tp>::type
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};
+
+template


N.B. This 'template' keyword should only be indented two spaces,
however ...


+struct __is_constructible_impl
+  : public __bool_constant<__is_constructible(_Tp, _Args...)>
{ };


I thought this could be an alias template instead of a class template:

 template
   using __is_constructible_impl
 = __bool_constant<__is_constructible(_Tp, _Args...)>;

But it causes failures in the 20_util/variable_templates_for_traits.cc
test. It looks like it instantiates some things too eagerly if it's an
alias template.


  /// is_constructible
  template
struct is_constructible
-  : public __bool_constant<__is_constructible(_Tp, _Args...)>
+  : public __is_constructible_impl<_Tp, _Args...>
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};
+
+  template
+struct __is_default_constructible_impl
+: public __is_constructible_impl<_Tp>::type
{ };


Do we need this new __is_default_constructible_impl type?
Could we just use __is_constructible_impl<_Tp> instead, to avoid an
extra step (and extra template instantiations)?


@@ -946,12 +1030,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __is_nt_default_constructible_atom<_Tp>
{ };

+template


Indentation again :-)


+struct __is_nothrow_default_constructible_impl
+: public __and_<__is_default_constructible_impl<_Tp>,
+__is_nt_default_constructible_impl<_Tp>>
+{ };


This one can be an alias template:

 template
   using __is_nothrow_default_constructible_impl
 = typename __and_<__is_constructible_impl<_Tp>,
__is_nt_default_constructible_impl<_Tp>>::type;


+template
+struct __is_nothrow_assignable_impl
+: public __and_<__bool_constant<__is_assignable(_Tp, _Up)>,
+   __is_nt_assignable_impl<_Tp, _Up>>
+{ };


I wanted this one to be an alias template:

 template
   using __is_nothrow_assignable_impl
 = __and_<__bool_constant<__is_assignable(_Tp, _Up)>,
  __is_nt_assignable_impl<_Tp, _Up>>;

But that also causes the same test to fail. I think it would work if
we moved the __is_assignable intrinsic into a new __is_assignable_impl
class template, but then we'd be adding a new class template just to
get rid of another one. That doesn't seem sensible.

I've attached a relative diff, to be applied on top of yours, with my
suggested tweaks. Do you see any issues with it?

(If you're happy with those tweaks I can go ahead and apply this,
there's no need for an updated patch from you).

commit 732d9c1c9634900437f560538305a6ffde5d6e8d
Author: Jonathan Wakely 
Date:   Thu May 30 17:30:45 2019 +0100


Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-05-30 Thread Antony Polukhin
чт, 9 мая 2019 г. в 00:10, Jonathan Wakely :
>
> On 06/05/19 14:19 +0300, Antony Polukhin wrote:
> >@@ -924,14 +984,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >   template
> > struct is_default_constructible
> > : public __is_default_constructible_safe<_Tp>::type
> >-{ };
> >+{
> >+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
> >+  "template argument must be a complete class or an unbounded array");
> >+};
> >
> >   /// is_constructible
>
> This "///" comment is for Doxygen, and should remain with the
> is_constructible trait, not __is_constructible_impl.

Fixed that issue along with some other misplaced Doxygen comments.
Rebased the patch and removed some trailing white-spaces.

-- 
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b209460..c5f0672 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,27 @@
+2019-05-29  Antony Polukhin  
+
+   PR libstdc++/71579
+   * include/std/type_traits: Add static_asserts to make sure that
+   type traits are not misused with an incomplete type.
+   * testsuite/20_util/__is_complete_or_unbounded/memoization.cc:
+   New test.
+   * testsuite/20_util/__is_complete_or_unbounded/memoization_neg.cc:
+   Likewise.
+   * testsuite/20_util/__is_complete_or_unbounded/value.cc: Likewise.
+   * testsuite/20_util/is_abstract/incomplete_neg.cc: Likewise.
+   * testsuite/20_util/is_aggregate/incomplete_neg.cc: Likewise.
+   * testsuite/20_util/is_class/value.cc: Likewise.
+   * testsuite/20_util/is_function/value.cc: Likewise.
+   * testsuite/20_util/is_move_constructible/incomplete_neg.cc: Likewise.
+   * testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc:
+   Likewise.
+   * testsuite/20_util/is_polymorphic/incomplete_neg.cc: Likewise.
+   * testsuite/20_util/is_reference/value.cc: Likewise.
+   * 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.
+
 2019-05-29  Jonathan Wakely  
 
* testsuite/util/testsuite_api.h: Remove names of unused parameters.
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 3a622eb..b481106 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -91,6 +91,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct conditional;
 
+  template 
+struct __type_identity {
+  using type = _Type;
+};
+
   template
 struct __or_;
 
@@ -177,6 +182,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #endif // C++17
 
+  // Forward declarations
+  template
+struct is_reference;
+  template
+struct is_function;
+  template
+struct is_void;
+  template
+struct __is_array_unknown_bounds;
+
+  // Helper functions that return false_type for incomplete classes,
+  // incomplete unions and arrays of known bound from those.
+
+  template 
+constexpr true_type __is_complete_or_unbounded(__type_identity<_T>)
+{ return {}; }
+
+  template 
+constexpr typename __or_<
+  is_reference<_NestedType>,
+  is_function<_NestedType>,
+  is_void<_NestedType>,
+  __is_array_unknown_bounds<_NestedType>
+>::type __is_complete_or_unbounded(_TypeIdentity)
+{ return {}; }
+
   // For several sfinae-friendly trait implementations we transport both the
   // result information (as the member type) and the failure information (no
   // member type). This is very similar to std::enable_if, but we cannot use
@@ -399,9 +431,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public true_type { };
 
   template
-struct is_function;
-
-  template
 struct __is_member_object_pointer_helper
 : public false_type { };
 
@@ -671,44 +700,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_trivial
 : public integral_constant
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};
 
   // is_trivially_copyable
   template
 struct is_trivially_copyable
 : public integral_constant
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};
 
   /// is_standard_layout
   template
 struct is_standard_layout
 : public integral_constant
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};
 
   /// is_pod
   // Could use is_standard_layout && is_trivial instead of the builtin.
   template
 struct is_pod
 : public integral_constant
-{ };
+{
+  

Re: [PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-05-08 Thread Jonathan Wakely

On 06/05/19 14:19 +0300, Antony Polukhin wrote:

@@ -924,14 +984,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  template
struct is_default_constructible
: public __is_default_constructible_safe<_Tp>::type
-{ };
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};

  /// is_constructible


This "///" comment is for Doxygen, and should remain with the
is_constructible trait, not __is_constructible_impl.


-  template
-struct is_constructible
+template
+struct __is_constructible_impl
  : public __bool_constant<__is_constructible(_Tp, _Args...)>
{ };

+  template
+struct is_constructible
+  : public __is_constructible_impl<_Tp, _Args...>
+{
+  static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+   "template argument must be a complete class or an unbounded array");
+};
+
  template::value>
struct __is_copy_constructible_impl;



The rest looks reasonable, but I'll finish reviewing it ASAP, when I
have more time.



[PATCH] PR libstdc++/71579 assert that type traits are not misused with an incomplete type

2019-05-06 Thread Antony Polukhin
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

PR libstdc++/71579
* include/std/type_traits: Add static_asserts to make sure that
type traits are not misused with an incomplete type.
* testsuite/20_util/__is_complete_or_unbounded/memoization.cc:
New test.
* testsuite/20_util/__is_complete_or_unbounded/memoization_neg.cc:
Likewise.
* testsuite/20_util/__is_complete_or_unbounded/value.cc: Likewise.
* testsuite/20_util/is_abstract/incomplete_neg.cc: Likewise.
* testsuite/20_util/is_aggregate/incomplete_neg.cc: Likewise.
* testsuite/20_util/is_class/value.cc: Likewise.
* testsuite/20_util/is_function/value.cc: Likewise.
* testsuite/20_util/is_move_constructible/incomplete_neg.cc: Likewise.
* testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc:
Likewise.
* testsuite/20_util/is_polymorphic/incomplete_neg.cc: Likewise.
* testsuite/20_util/is_reference/value.cc: Likewise.
* 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.

-- 
Best regards,
Antony Polukhin
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 411eff1..3a0cf44 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,27 @@
+2019-05-06  Antony Polukhin  
+
+	PR libstdc++/71579
+	* include/std/type_traits: Add static_asserts to make sure that
+	type traits are not misused with an incomplete type.
+	* testsuite/20_util/__is_complete_or_unbounded/memoization.cc:
+	New test.
+	* testsuite/20_util/__is_complete_or_unbounded/memoization_neg.cc:
+	Likewise.
+	* testsuite/20_util/__is_complete_or_unbounded/value.cc: Likewise.
+	* testsuite/20_util/is_abstract/incomplete_neg.cc: Likewise.
+	* testsuite/20_util/is_aggregate/incomplete_neg.cc: Likewise.
+	* testsuite/20_util/is_class/value.cc: Likewise.
+	* testsuite/20_util/is_function/value.cc: Likewise.
+	* testsuite/20_util/is_move_constructible/incomplete_neg.cc: Likewise.
+	* testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc:
+	Likewise.
+	* testsuite/20_util/is_polymorphic/incomplete_neg.cc: Likewise.
+	* testsuite/20_util/is_reference/value.cc: Likewise.
+	* 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.
+
 2019-05-06  François Dumont  
 
 	* python/libstdcxx/v6/printers.py (add_one_template_type_printer):
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 1d14c75..6fdb534 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -91,6 +91,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct conditional;
 
+  template 
+struct __type_identity {
+  using type = _Type;
+};
+
   template
 struct __or_;
 
@@ -177,6 +182,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #endif // C++17
 
+  // Forward declarations
+  template
+struct is_reference;
+  template
+struct is_function;
+  template
+struct is_void;
+  template
+struct __is_array_unknown_bounds;
+
+  // Helper functions that return false_type for incomplete classes,
+  // incomplete unions and arrays of known bound from those.
+
+  template 
+constexpr true_type __is_complete_or_unbounded(__type_identity<_T>)
+{ return {}; }
+
+  template 
+constexpr typename __or_<
+  is_reference<_NestedType>,
+  is_function<_NestedType>,
+  is_void<_NestedType>,
+  __is_array_unknown_bounds<_NestedType>
+>::type __is_complete_or_unbounded(_TypeIdentity)
+{ return {}; }
+
   // For several sfinae-friendly trait implementations we transport both the
   // result information (as the member type) and the failure information (no
   // member type). This is very similar to std::enable_if, but we cannot use
@@ -399,9 +431,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public true_type { };
 
   template
-struct is_function;
-
-  template
 struct