public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits
@ 2023-03-26  4:30 Ken Matsui
  2023-03-26  4:30 ` [PATCH 01/10] c++: implement __is_reference built-in trait Ken Matsui
                   ` (11 more replies)
  0 siblings, 12 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Ken Matsui (10):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  libstdc++: use std::is_void instead of __is_void in helper_functions.h
  libstdc++: remove unused __is_void in cpp_type_traits.h
  c++: rename __is_void defined in pr46567.C to ____is_void
  c++: implement __is_void built-in trait
  libstdc++: use new built-in trait __is_void for std::is_void
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  2 +-
 libstdc++-v3/include/std/type_traits          | 30 ++++++++++
 11 files changed, 194 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 01/10] c++: implement __is_reference built-in trait
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 02/10] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 273d15ab097..23e5bc24dbb 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3701,6 +3701,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index bac593c0094..63a64152ce6 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 99a76e3ed65..b17fbf8005d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11996,6 +11996,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12201,6 +12204,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 02/10] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
  2023-03-26  4:30 ` [PATCH 01/10] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 03/10] c++: implement __is_function built-in trait Ken Matsui
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2bd607a8b8f..58a732735c8 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 03/10] c++: implement __is_function built-in trait
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
  2023-03-26  4:30 ` [PATCH 01/10] c++: implement __is_reference built-in trait Ken Matsui
  2023-03-26  4:30 ` [PATCH 02/10] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 04/10] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 23e5bc24dbb..500ac9177c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3750,6 +3750,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 63a64152ce6..99195201676 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b17fbf8005d..36fe370da2d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11993,6 +11993,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12205,6 +12208,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 04/10] libstdc++: use new built-in trait __is_function for std::is_function
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (2 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 03/10] c++: implement __is_function built-in trait Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 05/10] libstdc++: use std::is_void instead of __is_void in helper_functions.h Ken Matsui
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 58a732735c8..9eafd6b16f2 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 05/10] libstdc++: use std::is_void instead of __is_void in helper_functions.h
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (3 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 04/10] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 06/10] libstdc++: remove unused __is_void in cpp_type_traits.h Ken Matsui
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch uses std::is_void in helper_function.h instead of __is_void defined
in cpp_type_traits.h to avoid conflicts with the __is_void built-in trait to
be implemented.

libstdc++-v3/ChangeLog:

	* include/debug/helper_function.h (_DiffTraits): Use std::void
	instead of __is_void defined in cpp_type_traits.h

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/debug/helper_functions.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..e364a630d2c 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -67,7 +67,7 @@ namespace __gnu_debug
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
       template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+	       typename = typename std::is_void<_DiffType>::type>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 06/10] libstdc++: remove unused __is_void in cpp_type_traits.h
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (4 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 05/10] libstdc++: use std::is_void instead of __is_void in helper_functions.h Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 07/10] c++: rename __is_void defined in pr46567.C to ____is_void Ken Matsui
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch removes unused __is_void defined in cpp_type_traits.h

libstdc++-v3/ChangeLog:

	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/bits/cpp_type_traits.h | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 07/10] c++: rename __is_void defined in pr46567.C to ____is_void
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (5 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 06/10] libstdc++: remove unused __is_void in cpp_type_traits.h Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 08/10] c++: implement __is_void built-in trait Ken Matsui
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch renames __is_void defined in pr46567.C to ____is_void to
avoid conflicts with the __is_void built-in trait to be implemented.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/testsuite/g++.dg/tm/pr46567.C | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 08/10] c++: implement __is_void built-in trait
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (6 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 07/10] c++: rename __is_void defined in pr46567.C to ____is_void Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 09/10] libstdc++: use new built-in trait __is_void for std::is_void Ken Matsui
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C       | 35 ++++++++++++++++++++++++
 5 files changed, 46 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 500ac9177c7..e67c0ffeaac 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3753,6 +3753,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 99195201676..6284924630a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 36fe370da2d..a6598fedfbc 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11996,6 +11996,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12209,6 +12212,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 09/10] libstdc++: use new built-in trait __is_void for std::is_void
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (7 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 08/10] c++: implement __is_void built-in trait Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-26  4:30 ` [PATCH 10/10] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_void to dispatch to new built-in trait __is_void.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_void): Use __is_void built-in trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 9eafd6b16f2..98764685a39 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -294,6 +294,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Primary type categories.
 
   /// is_void
+#if __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_void
+    : public __bool_constant<__is_void(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_void
     : public false_type { };
@@ -313,6 +319,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
     struct is_void<const volatile void>
     : public true_type { };
+#endif
 
   /// @cond undocumented
   template<typename>
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 10/10] libstdc++: make std::is_object dispatch to new built-in traits
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (8 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 09/10] libstdc++: use new built-in trait __is_void for std::is_void Ken Matsui
@ 2023-03-26  4:30 ` Ken Matsui
  2023-03-30 18:32 ` [PATCH 0/7] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-26  4:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 98764685a39..5d50c55b70f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -689,11 +689,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                               __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH 0/7] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (9 preceding siblings ...)
  2023-03-26  4:30 ` [PATCH 10/10] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-03-30 18:32 ` Ken Matsui
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
  11 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:32 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Ken Matsui (7):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: use new built-in trait __is_void for std::is_void
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 30 ++++++++++
 11 files changed, 195 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 0/7] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
                   ` (10 preceding siblings ...)
  2023-03-30 18:32 ` [PATCH 0/7] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-03-30 18:39 ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 1/7] c++: implement __is_reference built-in trait Ken Matsui
                     ` (7 more replies)
  11 siblings, 8 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v2

	* Stopped using std::is_void in helper_functions.h
	* Squashed is_void-related commits into the commit of is_void implementation

Ken Matsui (7):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: use new built-in trait __is_void for std::is_void
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 30 ++++++++++
 11 files changed, 195 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 1/7] c++: implement __is_reference built-in trait
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 2/7] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 273d15ab097..23e5bc24dbb 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3701,6 +3701,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index bac593c0094..63a64152ce6 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 99a76e3ed65..b17fbf8005d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11996,6 +11996,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12201,6 +12204,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 2/7] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 1/7] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 3/7] c++: implement __is_function built-in trait Ken Matsui
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2bd607a8b8f..58a732735c8 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 3/7] c++: implement __is_function built-in trait
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 1/7] c++: implement __is_reference built-in trait Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 2/7] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 4/7] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 23e5bc24dbb..500ac9177c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3750,6 +3750,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 63a64152ce6..99195201676 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b17fbf8005d..36fe370da2d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11993,6 +11993,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12205,6 +12208,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 4/7] libstdc++: use new built-in trait __is_function for std::is_function
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
                     ` (2 preceding siblings ...)
  2023-03-30 18:39   ` [PATCH v2 3/7] c++: implement __is_function built-in trait Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 5/7] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 58a732735c8..9eafd6b16f2 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 5/7] c++, libstdc++: implement __is_void built-in trait
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
                     ` (3 preceding siblings ...)
  2023-03-30 18:39   ` [PATCH v2 4/7] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 6/7] libstdc++: use new built-in trait __is_void for std::is_void Ken Matsui
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 8 files changed, 51 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 500ac9177c7..e67c0ffeaac 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3753,6 +3753,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 99195201676..6284924630a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 36fe370da2d..a6598fedfbc 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11996,6 +11996,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12209,6 +12212,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 6/7] libstdc++: use new built-in trait __is_void for std::is_void
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
                     ` (4 preceding siblings ...)
  2023-03-30 18:39   ` [PATCH v2 5/7] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-03-30 18:39   ` [PATCH v2 7/7] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_void to dispatch to new built-in trait __is_void.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_void): Use __is_void built-in trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 9eafd6b16f2..98764685a39 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -294,6 +294,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Primary type categories.
 
   /// is_void
+#if __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_void
+    : public __bool_constant<__is_void(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_void
     : public false_type { };
@@ -313,6 +319,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
     struct is_void<const volatile void>
     : public true_type { };
+#endif
 
   /// @cond undocumented
   template<typename>
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v2 7/7] libstdc++: make std::is_object dispatch to new built-in traits
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
                     ` (5 preceding siblings ...)
  2023-03-30 18:39   ` [PATCH v2 6/7] libstdc++: use new built-in trait __is_void for std::is_void Ken Matsui
@ 2023-03-30 18:39   ` Ken Matsui
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  7 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-03-30 18:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 98764685a39..5d50c55b70f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -689,11 +689,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                               __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
                     ` (6 preceding siblings ...)
  2023-03-30 18:39   ` [PATCH v2 7/7] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-04-02  7:53   ` Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 1/6] c++: implement __is_reference built-in trait Ken Matsui
                       ` (6 more replies)
  7 siblings, 7 replies; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v3

	* Dropped the patch to use new built-in trait __is_void for std::is_void
	since we know that explicit specializations are faster than built-ins.

Ken Matsui (6):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 23 ++++++++
 11 files changed, 188 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 1/6] c++: implement __is_reference built-in trait
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-04-02  7:53     ` Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 273d15ab097..23e5bc24dbb 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3701,6 +3701,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index bac593c0094..63a64152ce6 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 99a76e3ed65..b17fbf8005d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11996,6 +11996,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12201,6 +12204,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-04-02  7:53     ` Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 3/6] c++: implement __is_function built-in trait Ken Matsui
                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2bd607a8b8f..58a732735c8 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 3/6] c++: implement __is_function built-in trait
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 1/6] c++: implement __is_reference built-in trait Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-04-02  7:53     ` Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 23e5bc24dbb..500ac9177c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3750,6 +3750,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 63a64152ce6..99195201676 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b17fbf8005d..36fe370da2d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11993,6 +11993,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12205,6 +12208,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                       ` (2 preceding siblings ...)
  2023-04-02  7:53     ` [PATCH v3 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-04-02  7:53     ` Ken Matsui
  2023-06-09 17:54       ` Patrick Palka
  2023-04-02  7:53     ` [PATCH v3 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                       ` (2 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 58a732735c8..9eafd6b16f2 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                       ` (3 preceding siblings ...)
  2023-04-02  7:53     ` [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-04-02  7:53     ` Ken Matsui
  2023-04-02  7:53     ` [PATCH v3 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 8 files changed, 51 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 500ac9177c7..e67c0ffeaac 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3753,6 +3753,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 99195201676..6284924630a 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 36fe370da2d..a6598fedfbc 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11996,6 +11996,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12209,6 +12212,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v3 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                       ` (4 preceding siblings ...)
  2023-04-02  7:53     ` [PATCH v3 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-04-02  7:53     ` Ken Matsui
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-04-02  7:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 9eafd6b16f2..c1691336e0f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                               __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
-- 
2.40.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-04-02  7:53     ` [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-06-09 17:54       ` Patrick Palka
  2023-06-09 23:53         ` Ken Matsui
  0 siblings, 1 reply; 92+ messages in thread
From: Patrick Palka @ 2023-06-09 17:54 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Sun, 2 Apr 2023, Ken Matsui via Gcc-patches wrote:

> This patch gets std::is_function to dispatch to new built-in trait
> __is_function.

For std::is_function and other predicate-like type traits, I think we also
want to make the corresponding variable template is_function_v directly
use the built-in too.

> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/std/type_traits (is_function): Use __is_function built-in
> 	trait.
> 
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>  libstdc++-v3/include/std/type_traits | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 58a732735c8..9eafd6b16f2 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      { };
>  
>    /// is_function
> +#if __has_builtin(__is_function)
> +  template<typename _Tp>
> +    struct is_function
> +    : public __bool_constant<__is_function(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_function
>      : public __bool_constant<!is_const<const _Tp>::value> { };
> @@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _Tp>
>      struct is_function<_Tp&&>
>      : public false_type { };
> +#endif
>  
>  #define __cpp_lib_is_null_pointer 201309L
>  
> -- 
> 2.40.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-06-09 17:54       ` Patrick Palka
@ 2023-06-09 23:53         ` Ken Matsui
  0 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-09 23:53 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On Fri, Jun 9, 2023 at 10:54 AM Patrick Palka <ppalka@redhat.com> wrote:
>
> On Sun, 2 Apr 2023, Ken Matsui via Gcc-patches wrote:
>
> > This patch gets std::is_function to dispatch to new built-in trait
> > __is_function.
>
> For std::is_function and other predicate-like type traits, I think we also
> want to make the corresponding variable template is_function_v directly
> use the built-in too.

Oh, thank you! Will implement it!

> >
> > libstdc++-v3/ChangeLog:
> >
> >       * include/std/type_traits (is_function): Use __is_function built-in
> >       trait.
> >
> > Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> > ---
> >  libstdc++-v3/include/std/type_traits | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> > index 58a732735c8..9eafd6b16f2 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >      { };
> >
> >    /// is_function
> > +#if __has_builtin(__is_function)
> > +  template<typename _Tp>
> > +    struct is_function
> > +    : public __bool_constant<__is_function(_Tp)>
> > +    { };
> > +#else
> >    template<typename _Tp>
> >      struct is_function
> >      : public __bool_constant<!is_const<const _Tp>::value> { };
> > @@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >    template<typename _Tp>
> >      struct is_function<_Tp&&>
> >      : public false_type { };
> > +#endif
> >
> >  #define __cpp_lib_is_null_pointer 201309L
> >
> > --
> > 2.40.0
> >
> >
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                       ` (5 preceding siblings ...)
  2023-04-02  7:53     ` [PATCH v3 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-06-11  2:43     ` Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 1/6] c++: implement __is_reference built-in trait Ken Matsui
                         ` (6 more replies)
  6 siblings, 7 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v4

	* Used built-in traits for the corresponding predicate-like type traits.

Ken Matsui (6):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 33 ++++++++---
 11 files changed, 191 insertions(+), 28 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 1/6] c++: implement __is_reference built-in trait
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-06-11  2:43       ` Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                         ` (5 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..f6951ee2670 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..1e3310cd682 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a2e74a5d2c7..2f37bc353a1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-06-11  2:43       ` Ken Matsui
  2023-06-12 18:09         ` François Dumont
  2023-06-11  2:43       ` [PATCH v4 3/6] c++: implement __is_function built-in trait Ken Matsui
                         ` (4 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.
	(is_reference_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..b2eb4bd3e7f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
@@ -3193,11 +3200,7 @@ template <typename _Tp>
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
 template <typename _Tp>
-  inline constexpr bool is_reference_v = false;
-template <typename _Tp>
-  inline constexpr bool is_reference_v<_Tp&> = true;
-template <typename _Tp>
-  inline constexpr bool is_reference_v<_Tp&&> = true;
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
 template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 3/6] c++: implement __is_function built-in trait
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 1/6] c++: implement __is_reference built-in trait Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-06-11  2:43       ` Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                         ` (3 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6951ee2670..927605c6cb7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 1e3310cd682..3cd3babc242 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 2f37bc353a1..b976633645a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                         ` (2 preceding siblings ...)
  2023-06-11  2:43       ` [PATCH v4 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-06-11  2:43       ` Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                         ` (2 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.
	(is_function_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index b2eb4bd3e7f..c0fa748da2e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3198,7 +3205,7 @@ template <typename _Tp>
 template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
 template <typename _Tp>
-  inline constexpr bool is_function_v = is_function<_Tp>::value;
+  inline constexpr bool is_function_v = __is_function(_Tp);
 template <typename _Tp>
   inline constexpr bool is_reference_v = __is_reference(_Tp);
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                         ` (3 preceding siblings ...)
  2023-06-11  2:43       ` [PATCH v4 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-06-11  2:43       ` Ken Matsui
  2023-06-11  2:43       ` [PATCH v4 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.
	* include/std/type_traits (is_void_v): Use __is_void built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 libstdc++-v3/include/std/type_traits          |  2 +-
 9 files changed, 52 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 927605c6cb7..e8cd98eb2c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3757,6 +3757,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 3cd3babc242..8e76668f6ed 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b976633645a..c4d44413dce 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12297,6 +12300,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index c0fa748da2e..412bfb35979 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3167,7 +3167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @ingroup variable_templates
    */
 template <typename _Tp>
-  inline constexpr bool is_void_v = is_void<_Tp>::value;
+  inline constexpr bool is_void_v = __is_void(_Tp);
 template <typename _Tp>
   inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v4 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                         ` (4 preceding siblings ...)
  2023-06-11  2:43       ` [PATCH v4 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-06-11  2:43       ` Ken Matsui
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-11  2:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 412bfb35979..26968e31261 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                               __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-11  2:43       ` [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-06-12 18:09         ` François Dumont
  2023-06-12 18:13           ` Ken Matsui
  0 siblings, 1 reply; 92+ messages in thread
From: François Dumont @ 2023-06-12 18:09 UTC (permalink / raw)
  To: Ken Matsui, gcc-patches; +Cc: libstdc++

Same remark for all your alike patches.

On 11/06/2023 04:43, Ken Matsui via Libstdc++ wrote:
> This patch gets std::is_reference to dispatch to new built-in trait
> __is_reference.
>
> libstdc++-v3/ChangeLog:
>
> 	* include/std/type_traits (is_reference): Use __is_reference built-in
> 	trait.
> 	(is_reference_v): Likewise.
>
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>   libstdc++-v3/include/std/type_traits | 13 ++++++++-----
>   1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 0e7a9c9c7f3..b2eb4bd3e7f 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>     // Composite type categories.
>   
>     /// is_reference
> +#if __has_builtin(__is_reference)
Here you are checking __has_builtin(__is_reference)...
> +  template<typename _Tp>
> +    struct is_reference
> +    : public __bool_constant<__is_reference(_Tp)>
> +    { };
> +#else
>     template<typename _Tp>
>       struct is_reference
>       : public false_type
> @@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       struct is_reference<_Tp&&>
>       : public true_type
>       { };
> +#endif
>   
>     /// is_arithmetic
>     template<typename _Tp>
> @@ -3193,11 +3200,7 @@ template <typename _Tp>
>   template <typename _Tp>
>     inline constexpr bool is_function_v = is_function<_Tp>::value;
>   template <typename _Tp>
> -  inline constexpr bool is_reference_v = false;
> -template <typename _Tp>
> -  inline constexpr bool is_reference_v<_Tp&> = true;
> -template <typename _Tp>
> -  inline constexpr bool is_reference_v<_Tp&&> = true;
> +  inline constexpr bool is_reference_v = __is_reference(_Tp);
...but not here, why ?


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-12 18:09         ` François Dumont
@ 2023-06-12 18:13           ` Ken Matsui
  0 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 18:13 UTC (permalink / raw)
  To: François Dumont; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 2208 bytes --]

Yes, I have fixed them on my side and am waiting for the test results!
Thank you!

On Mon, Jun 12, 2023 at 11:09 AM François Dumont <frs.dumont@gmail.com>
wrote:

> Same remark for all your alike patches.
>
> On 11/06/2023 04:43, Ken Matsui via Libstdc++ wrote:
> > This patch gets std::is_reference to dispatch to new built-in trait
> > __is_reference.
> >
> > libstdc++-v3/ChangeLog:
> >
> >       * include/std/type_traits (is_reference): Use __is_reference
> built-in
> >       trait.
> >       (is_reference_v): Likewise.
> >
> > Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> > ---
> >   libstdc++-v3/include/std/type_traits | 13 ++++++++-----
> >   1 file changed, 8 insertions(+), 5 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/std/type_traits
> b/libstdc++-v3/include/std/type_traits
> > index 0e7a9c9c7f3..b2eb4bd3e7f 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >     // Composite type categories.
> >
> >     /// is_reference
> > +#if __has_builtin(__is_reference)
> Here you are checking __has_builtin(__is_reference)...
> > +  template<typename _Tp>
> > +    struct is_reference
> > +    : public __bool_constant<__is_reference(_Tp)>
> > +    { };
> > +#else
> >     template<typename _Tp>
> >       struct is_reference
> >       : public false_type
> > @@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >       struct is_reference<_Tp&&>
> >       : public true_type
> >       { };
> > +#endif
> >
> >     /// is_arithmetic
> >     template<typename _Tp>
> > @@ -3193,11 +3200,7 @@ template <typename _Tp>
> >   template <typename _Tp>
> >     inline constexpr bool is_function_v = is_function<_Tp>::value;
> >   template <typename _Tp>
> > -  inline constexpr bool is_reference_v = false;
> > -template <typename _Tp>
> > -  inline constexpr bool is_reference_v<_Tp&> = true;
> > -template <typename _Tp>
> > -  inline constexpr bool is_reference_v<_Tp&&> = true;
> > +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> ...but not here, why ?
>
> --
Sincerely,
Ken Matsui

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                         ` (5 preceding siblings ...)
  2023-06-11  2:43       ` [PATCH v4 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-06-12 22:22       ` Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 1/6] c++: implement __is_reference built-in trait Ken Matsui
                           ` (6 more replies)
  6 siblings, 7 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v5

	* Wrap predicate-like type traits in #if.

Ken Matsui (6):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 52 +++++++++++++++++
 11 files changed, 217 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 1/6] c++: implement __is_reference built-in trait
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-06-12 22:22         ` Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                           ` (5 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..f6951ee2670 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..1e3310cd682 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a2e74a5d2c7..2f37bc353a1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-06-12 22:22         ` Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 3/6] c++: implement __is_function built-in trait Ken Matsui
                           ` (4 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.
	(is_reference_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..2a14df7e5f9 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
@@ -3192,12 +3199,19 @@ template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template <typename _Tp>
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_reference_v = false;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&> = true;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 3/6] c++: implement __is_function built-in trait
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 1/6] c++: implement __is_reference built-in trait Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-06-12 22:22         ` Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                           ` (3 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6951ee2670..927605c6cb7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 1e3310cd682..3cd3babc242 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 2f37bc353a1..b976633645a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                           ` (2 preceding siblings ...)
  2023-06-12 22:22         ` [PATCH v5 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-06-12 22:22         ` Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                           ` (2 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.
	(is_function_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2a14df7e5f9..954b57518de 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template <typename _Tp>
   inline constexpr bool is_union_v = __is_union(_Tp);
 template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template <typename _Tp>
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                           ` (3 preceding siblings ...)
  2023-06-12 22:22         ` [PATCH v5 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-06-12 22:22         ` Ken Matsui
  2023-06-12 22:22         ` [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.
	* include/std/type_traits (is_void_v): Use __is_void built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 libstdc++-v3/include/std/type_traits          |  6 ++++
 9 files changed, 57 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 927605c6cb7..e8cd98eb2c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3757,6 +3757,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 3cd3babc242..8e76668f6ed 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b976633645a..c4d44413dce 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12297,6 +12300,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 954b57518de..780fcc00135 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3166,8 +3166,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @{
    * @ingroup variable_templates
    */
+#if __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_void_v = __is_void(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_void_v = is_void<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                           ` (4 preceding siblings ...)
  2023-06-12 22:22         ` [PATCH v5 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-06-12 22:22         ` Ken Matsui
  2023-06-14  5:10           ` François Dumont
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.
	(__is_object): Define this built-in-like macro.
	(is_object_v): Use built-in traits through the build-in-like macro.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 780fcc00135..93335f94385 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+
+#define __is_object(_Tp) \
+  (!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp)))
+
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<__is_object(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
@@ -3235,8 +3247,15 @@ template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#ifdef __is_object
+template <typename _Tp>
+  inline constexpr bool is_object_v = __is_object(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                           ` (5 preceding siblings ...)
  2023-06-12 22:22         ` [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-06-12 22:39         ` Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 1/6] c++: implement __is_reference built-in trait Ken Matsui
                             ` (6 more replies)
  6 siblings, 7 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v6

	* Removed the built-in-like type trait for is_object.

Ken Matsui (6):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 52 +++++++++++++++++
 11 files changed, 217 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/6] c++: implement __is_reference built-in trait
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-06-12 22:39           ` Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                             ` (5 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..f6951ee2670 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..1e3310cd682 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a2e74a5d2c7..2f37bc353a1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-06-12 22:39           ` Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 3/6] c++: implement __is_function built-in trait Ken Matsui
                             ` (4 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.
	(is_reference_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..2a14df7e5f9 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
@@ -3192,12 +3199,19 @@ template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template <typename _Tp>
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_reference_v = false;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&> = true;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 3/6] c++: implement __is_function built-in trait
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 1/6] c++: implement __is_reference built-in trait Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-06-12 22:39           ` Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                             ` (3 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6951ee2670..927605c6cb7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 1e3310cd682..3cd3babc242 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 2f37bc353a1..b976633645a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                             ` (2 preceding siblings ...)
  2023-06-12 22:39           ` [PATCH v6 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-06-12 22:39           ` Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                             ` (2 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.
	(is_function_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2a14df7e5f9..954b57518de 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template <typename _Tp>
   inline constexpr bool is_union_v = __is_union(_Tp);
 template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template <typename _Tp>
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                             ` (3 preceding siblings ...)
  2023-06-12 22:39           ` [PATCH v6 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-06-12 22:39           ` Ken Matsui
  2023-06-12 22:39           ` [PATCH v6 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.
	* include/std/type_traits (is_void_v): Use __is_void built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 libstdc++-v3/include/std/type_traits          |  6 ++++
 9 files changed, 57 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 927605c6cb7..e8cd98eb2c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3757,6 +3757,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 3cd3babc242..8e76668f6ed 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b976633645a..c4d44413dce 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12297,6 +12300,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 954b57518de..780fcc00135 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3166,8 +3166,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @{
    * @ingroup variable_templates
    */
+#if __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_void_v = __is_void(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_void_v = is_void<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                             ` (4 preceding siblings ...)
  2023-06-12 22:39           ` [PATCH v6 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-06-12 22:39           ` Ken Matsui
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.
	(is_object_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 780fcc00135..a20565f75c0 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                             __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
@@ -3235,8 +3245,17 @@ template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_object_v
+    = !(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp));
+#else
 template <typename _Tp>
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                             ` (5 preceding siblings ...)
  2023-06-12 22:39           ` [PATCH v6 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-06-12 22:47           ` Ken Matsui
  2023-06-12 22:47             ` [PATCH v7 1/6] c++: implement __is_reference built-in trait Ken Matsui
                               ` (6 more replies)
  6 siblings, 7 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v7

	* Removed an unnecessary new line.

Ken Matsui (6):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 51 ++++++++++++++++
 11 files changed, 216 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 1/6] c++: implement __is_reference built-in trait
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-06-12 22:47             ` Ken Matsui
  2023-06-20 16:06               ` Patrick Palka
  2023-06-12 22:47             ` [PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                               ` (5 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..f6951ee2670 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..1e3310cd682 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a2e74a5d2c7..2f37bc353a1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-12 22:47             ` [PATCH v7 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-06-12 22:47             ` Ken Matsui
  2023-06-20 16:07               ` Patrick Palka
  2023-06-12 22:47             ` [PATCH v7 3/6] c++: implement __is_function built-in trait Ken Matsui
                               ` (4 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.
	(is_reference_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..2a14df7e5f9 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
@@ -3192,12 +3199,19 @@ template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template <typename _Tp>
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_reference_v = false;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&> = true;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 3/6] c++: implement __is_function built-in trait
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-12 22:47             ` [PATCH v7 1/6] c++: implement __is_reference built-in trait Ken Matsui
  2023-06-12 22:47             ` [PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-06-12 22:47             ` Ken Matsui
  2023-06-20 16:05               ` Patrick Palka
  2023-06-12 22:47             ` [PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                               ` (3 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6951ee2670..927605c6cb7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 1e3310cd682..3cd3babc242 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 2f37bc353a1..b976633645a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                               ` (2 preceding siblings ...)
  2023-06-12 22:47             ` [PATCH v7 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-06-12 22:47             ` Ken Matsui
  2023-06-20 16:05               ` Patrick Palka
  2023-06-12 22:47             ` [PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                               ` (2 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.
	(is_function_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2a14df7e5f9..954b57518de 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template <typename _Tp>
   inline constexpr bool is_union_v = __is_union(_Tp);
 template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template <typename _Tp>
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                               ` (3 preceding siblings ...)
  2023-06-12 22:47             ` [PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-06-12 22:47             ` Ken Matsui
  2023-06-20 16:00               ` Patrick Palka
  2023-06-12 22:47             ` [PATCH v7 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-06-15 10:49             ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.
	* include/std/type_traits (is_void_v): Use __is_void built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 libstdc++-v3/include/std/type_traits          |  6 ++++
 9 files changed, 57 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 927605c6cb7..e8cd98eb2c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3757,6 +3757,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 3cd3babc242..8e76668f6ed 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b976633645a..c4d44413dce 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12297,6 +12300,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 954b57518de..780fcc00135 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3166,8 +3166,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @{
    * @ingroup variable_templates
    */
+#if __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_void_v = __is_void(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_void_v = is_void<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v7 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                               ` (4 preceding siblings ...)
  2023-06-12 22:47             ` [PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-06-12 22:47             ` Ken Matsui
  2023-06-15 10:49             ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-12 22:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.
	(is_object_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
---
 libstdc++-v3/include/std/type_traits | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 780fcc00135..715310f10bf 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                             __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
@@ -3235,8 +3244,17 @@ template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_object_v
+    = !(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp));
+#else
 template <typename _Tp>
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-06-12 22:22         ` [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-06-14  5:10           ` François Dumont
  2023-06-14  5:25             ` Ken Matsui
  0 siblings, 1 reply; 92+ messages in thread
From: François Dumont @ 2023-06-14  5:10 UTC (permalink / raw)
  To: Ken Matsui, gcc-patches; +Cc: libstdc++


On 13/06/2023 00:22, Ken Matsui via Libstdc++ wrote:
> This patch gets std::is_object to dispatch to new built-in traits,
> __is_function, __is_reference, and __is_void.
>
> libstdc++-v3/ChangeLog:
> 	* include/std/type_traits (is_object): Use new built-in traits,
> 	__is_function, __is_reference, and __is_void.
> 	(__is_object): Define this built-in-like macro.
> 	(is_object_v): Use built-in traits through the build-in-like macro.
>
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>   libstdc++-v3/include/std/type_traits | 19 +++++++++++++++++++
>   1 file changed, 19 insertions(+)
>
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 780fcc00135..93335f94385 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -682,11 +682,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       { };
>   
>     /// is_object
> +#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
> +    && __has_builtin(__is_void)
> +
> +#define __is_object(_Tp) \
> +  (!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp)))

Is this evaluation order random ? Are all those builtin functions 
performances equivalent ?

I would have felt that __is_void is the simplest/fastest cause only for 
'void' so would have put it first.

> +
> +  template<typename _Tp>
> +    struct is_object
> +    : public __bool_constant<__is_object(_Tp)>
> +    { };
> +#else
>     template<typename _Tp>
>       struct is_object
>       : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
>                             is_void<_Tp>>>::type
>       { };
> +#endif
>   
>     template<typename>
>       struct is_member_pointer;
> @@ -3235,8 +3247,15 @@ template <typename _Tp>
>     inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
>   template <typename _Tp>
>     inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> +
> +#ifdef __is_object
> +template <typename _Tp>
> +  inline constexpr bool is_object_v = __is_object(_Tp);
> +#else
>   template <typename _Tp>
>     inline constexpr bool is_object_v = is_object<_Tp>::value;
> +#endif
> +
>   template <typename _Tp>
>     inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
>   template <typename _Tp>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-06-14  5:10           ` François Dumont
@ 2023-06-14  5:25             ` Ken Matsui
  0 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-14  5:25 UTC (permalink / raw)
  To: François Dumont; +Cc: gcc-patches, libstdc++

On Tue, Jun 13, 2023 at 10:10 PM François Dumont <frs.dumont@gmail.com> wrote:
>
>
> On 13/06/2023 00:22, Ken Matsui via Libstdc++ wrote:
> > This patch gets std::is_object to dispatch to new built-in traits,
> > __is_function, __is_reference, and __is_void.
> >
> > libstdc++-v3/ChangeLog:
> >       * include/std/type_traits (is_object): Use new built-in traits,
> >       __is_function, __is_reference, and __is_void.
> >       (__is_object): Define this built-in-like macro.
> >       (is_object_v): Use built-in traits through the build-in-like macro.
> >
> > Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> > ---
> >   libstdc++-v3/include/std/type_traits | 19 +++++++++++++++++++
> >   1 file changed, 19 insertions(+)
> >
> > diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> > index 780fcc00135..93335f94385 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -682,11 +682,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >       { };
> >
> >     /// is_object
> > +#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
> > +    && __has_builtin(__is_void)
> > +
> > +#define __is_object(_Tp) \
> > +  (!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp)))
>
> Is this evaluation order random ? Are all those builtin functions
> performances equivalent ?
>
> I would have felt that __is_void is the simplest/fastest cause only for
> 'void' so would have put it first.

This particular order is derived from the original implementation:

```
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
```

From what I can see, it appears there shouldn't be any disparities in
performance based on these implementations in /gcc/cp/semantics.cc:

```
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;

+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;

+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
```

VOID_TYPE_P: gcc/tree.h

```
/* Nonzero if this type is the (possibly qualified) void type.  */
#define VOID_TYPE_P(NODE) (TREE_CODE (NODE) == VOID_TYPE)
```

> > +
> > +  template<typename _Tp>
> > +    struct is_object
> > +    : public __bool_constant<__is_object(_Tp)>
> > +    { };
> > +#else
> >     template<typename _Tp>
> >       struct is_object
> >       : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
> >                             is_void<_Tp>>>::type
> >       { };
> > +#endif
> >
> >     template<typename>
> >       struct is_member_pointer;
> > @@ -3235,8 +3247,15 @@ template <typename _Tp>
> >     inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
> >   template <typename _Tp>
> >     inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> > +
> > +#ifdef __is_object
> > +template <typename _Tp>
> > +  inline constexpr bool is_object_v = __is_object(_Tp);
> > +#else
> >   template <typename _Tp>
> >     inline constexpr bool is_object_v = is_object<_Tp>::value;
> > +#endif
> > +
> >   template <typename _Tp>
> >     inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
> >   template <typename _Tp>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
                               ` (5 preceding siblings ...)
  2023-06-12 22:47             ` [PATCH v7 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-06-15 10:49             ` Ken Matsui
  2023-06-20 13:19               ` Ken Matsui
  2023-06-20 15:32               ` Patrick Palka
  6 siblings, 2 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-15 10:49 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++

Hi,

For those curious about the performance improvements of this patch, I
conducted a benchmark that instantiates 256k specializations of
is_object_v based on Patrick's code. You can find the benchmark code
at this link:

https://github.com/ken-matsui/gcc-benches/blob/main/is_object_benchmark.cc

On my computer, using the gcc HEAD of this patch for a release build,
the patch with -DUSE_BUILTIN took 64% less time and used 44-47% less
memory compared to not using it.

Sincerely,
Ken Matsui

On Mon, Jun 12, 2023 at 3:49 PM Ken Matsui <kmatsui@cs.washington.edu> wrote:
>
> Hi,
>
> This patch series gets std::is_object to dispatch to built-in traits and
> implements the following built-in traits, on which std::object depends.
>
>         * __is_reference
>         * __is_function
>         * __is_void
>
> std::is_object was depending on them with disjunction and negation.
>
> __not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type
>
> Therefore, this patch uses them directly instead of implementing an additional
> built-in trait __is_object, which makes the compiler slightly bigger and
> slower.
>
> __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>
>
> This would instantiate only __bool_constant<true> and __bool_constant<false>,
> which can be mostly shared. That is, the purpose of built-in traits is
> considered as achieved.
>
> Changes in v7
>
>         * Removed an unnecessary new line.
>
> Ken Matsui (6):
>   c++: implement __is_reference built-in trait
>   libstdc++: use new built-in trait __is_reference for std::is_reference
>   c++: implement __is_function built-in trait
>   libstdc++: use new built-in trait __is_function for std::is_function
>   c++, libstdc++: implement __is_void built-in trait
>   libstdc++: make std::is_object dispatch to new built-in traits
>
>  gcc/cp/constraint.cc                          |  9 +++
>  gcc/cp/cp-trait.def                           |  3 +
>  gcc/cp/semantics.cc                           | 12 ++++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
>  gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
>  gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
>  gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
>  gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
>  libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
>  libstdc++-v3/include/debug/helper_functions.h |  5 +-
>  libstdc++-v3/include/std/type_traits          | 51 ++++++++++++++++
>  11 files changed, 216 insertions(+), 21 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C
>
> --
> 2.41.0
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-15 10:49             ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
@ 2023-06-20 13:19               ` Ken Matsui
  2023-06-20 15:32               ` Patrick Palka
  1 sibling, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-06-20 13:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++

Just a quick update, the benchmark code link has been updated and can
now be accessed at
https://github.com/ken-matsui/gcc-benches/blob/main/is_object.cc. I
have also created a report file which can be found at
https://github.com/ken-matsui/gcc-benches/blob/main/is_object.md.

On Thu, Jun 15, 2023 at 3:49 AM Ken Matsui <kmatsui@cs.washington.edu> wrote:
>
> Hi,
>
> For those curious about the performance improvements of this patch, I
> conducted a benchmark that instantiates 256k specializations of
> is_object_v based on Patrick's code. You can find the benchmark code
> at this link:
>
> https://github.com/ken-matsui/gcc-benches/blob/main/is_object_benchmark.cc
>
> On my computer, using the gcc HEAD of this patch for a release build,
> the patch with -DUSE_BUILTIN took 64% less time and used 44-47% less
> memory compared to not using it.
>
> Sincerely,
> Ken Matsui
>
> On Mon, Jun 12, 2023 at 3:49 PM Ken Matsui <kmatsui@cs.washington.edu> wrote:
> >
> > Hi,
> >
> > This patch series gets std::is_object to dispatch to built-in traits and
> > implements the following built-in traits, on which std::object depends.
> >
> >         * __is_reference
> >         * __is_function
> >         * __is_void
> >
> > std::is_object was depending on them with disjunction and negation.
> >
> > __not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type
> >
> > Therefore, this patch uses them directly instead of implementing an additional
> > built-in trait __is_object, which makes the compiler slightly bigger and
> > slower.
> >
> > __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>
> >
> > This would instantiate only __bool_constant<true> and __bool_constant<false>,
> > which can be mostly shared. That is, the purpose of built-in traits is
> > considered as achieved.
> >
> > Changes in v7
> >
> >         * Removed an unnecessary new line.
> >
> > Ken Matsui (6):
> >   c++: implement __is_reference built-in trait
> >   libstdc++: use new built-in trait __is_reference for std::is_reference
> >   c++: implement __is_function built-in trait
> >   libstdc++: use new built-in trait __is_function for std::is_function
> >   c++, libstdc++: implement __is_void built-in trait
> >   libstdc++: make std::is_object dispatch to new built-in traits
> >
> >  gcc/cp/constraint.cc                          |  9 +++
> >  gcc/cp/cp-trait.def                           |  3 +
> >  gcc/cp/semantics.cc                           | 12 ++++
> >  gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
> >  gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
> >  gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
> >  gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
> >  gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
> >  libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
> >  libstdc++-v3/include/debug/helper_functions.h |  5 +-
> >  libstdc++-v3/include/std/type_traits          | 51 ++++++++++++++++
> >  11 files changed, 216 insertions(+), 21 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C
> >
> > --
> > 2.41.0
> >

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-15 10:49             ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
  2023-06-20 13:19               ` Ken Matsui
@ 2023-06-20 15:32               ` Patrick Palka
  2023-06-24 15:12                 ` Ken Matsui
  1 sibling, 1 reply; 92+ messages in thread
From: Patrick Palka @ 2023-06-20 15:32 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 3126 bytes --]

On Thu, 15 Jun 2023, Ken Matsui via Libstdc++ wrote:

> Hi,
> 
> For those curious about the performance improvements of this patch, I
> conducted a benchmark that instantiates 256k specializations of
> is_object_v based on Patrick's code. You can find the benchmark code
> at this link:
> 
> https://github.com/ken-matsui/gcc-benches/blob/main/is_object_benchmark.cc
> 
> On my computer, using the gcc HEAD of this patch for a release build,
> the patch with -DUSE_BUILTIN took 64% less time and used 44-47% less
> memory compared to not using it.

That's more like it :D  Though the benchmark should also invoke the
trait on non-object types too, e.g. Instantiator& or Instantiator(int).

> 
> Sincerely,
> Ken Matsui
> 
> On Mon, Jun 12, 2023 at 3:49 PM Ken Matsui <kmatsui@cs.washington.edu> wrote:
> >
> > Hi,
> >
> > This patch series gets std::is_object to dispatch to built-in traits and
> > implements the following built-in traits, on which std::object depends.
> >
> >         * __is_reference
> >         * __is_function
> >         * __is_void
> >
> > std::is_object was depending on them with disjunction and negation.
> >
> > __not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type
> >
> > Therefore, this patch uses them directly instead of implementing an additional
> > built-in trait __is_object, which makes the compiler slightly bigger and
> > slower.
> >
> > __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>
> >
> > This would instantiate only __bool_constant<true> and __bool_constant<false>,
> > which can be mostly shared. That is, the purpose of built-in traits is
> > considered as achieved.
> >
> > Changes in v7
> >
> >         * Removed an unnecessary new line.
> >
> > Ken Matsui (6):
> >   c++: implement __is_reference built-in trait
> >   libstdc++: use new built-in trait __is_reference for std::is_reference
> >   c++: implement __is_function built-in trait
> >   libstdc++: use new built-in trait __is_function for std::is_function
> >   c++, libstdc++: implement __is_void built-in trait
> >   libstdc++: make std::is_object dispatch to new built-in traits
> >
> >  gcc/cp/constraint.cc                          |  9 +++
> >  gcc/cp/cp-trait.def                           |  3 +
> >  gcc/cp/semantics.cc                           | 12 ++++
> >  gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
> >  gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
> >  gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
> >  gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
> >  gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
> >  libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
> >  libstdc++-v3/include/debug/helper_functions.h |  5 +-
> >  libstdc++-v3/include/std/type_traits          | 51 ++++++++++++++++
> >  11 files changed, 216 insertions(+), 21 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C
> >
> > --
> > 2.41.0
> >
> 
> 

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-06-12 22:47             ` [PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-06-20 16:00               ` Patrick Palka
  0 siblings, 0 replies; 92+ messages in thread
From: Patrick Palka @ 2023-06-20 16:00 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Mon, 12 Jun 2023, Ken Matsui via Libstdc++ wrote:

> This patch implements built-in trait for std::is_void. Since the new built-in
> name is __is_void, to avoid unintentional macro replacement, this patch also
> involves the removal of the existing __is_void in helper_functions.h and
> cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
> pr46567.C.

Hmm, I suspect an __is_void built-in won't show an improvement over
the current is_void implementation in terms of four explicit specializations.
And given the __is_void name conflict in cpp_type_traits.h (which means
GCC trunk will reject older libstdc++ headers at least until we get
smarter about how we recognize built-ins), I'm leaning towards not
implementing an __is_void built-in for now.

In that case we should probably define a built-in for is_object since
we can no longer implement it solely in terms of other built-ins, and
fortunately the name __is_object seems to never have been used in
libstdc++ so we won't have to deal with any name conflicts unlike with
__is_void.

Jonathan, what do you think?

> 
> gcc/cp/ChangeLog:
> 
> 	* cp-trait.def: Define __is_void.
> 	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
> 	* semantics.cc (trait_expr_value): Likewise.
> 	(finish_trait_expr): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
> 	(____is_void): ... this.
> 	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
> 	* g++.dg/ext/is_void.C: New test.
> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/debug/helper_functions.h (_DiffTraits): Stop using
> 	__is_void.
> 	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.
> 	* include/std/type_traits (is_void_v): Use __is_void built-in
> 	trait.
> 
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>  gcc/cp/constraint.cc                          |  3 ++
>  gcc/cp/cp-trait.def                           |  1 +
>  gcc/cp/semantics.cc                           |  4 +++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
>  gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
>  gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
>  libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
>  libstdc++-v3/include/debug/helper_functions.h |  5 ++-
>  libstdc++-v3/include/std/type_traits          |  6 ++++
>  9 files changed, 57 insertions(+), 21 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C
> 
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 927605c6cb7..e8cd98eb2c7 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3757,6 +3757,9 @@ diagnose_trait_expr (tree expr, tree args)
>      case CPTK_IS_FUNCTION:
>        inform (loc, "  %qT is not a function", t1);
>        break;
> +    case CPTK_IS_VOID:
> +      inform (loc, "  %qT is not a void type", t1);
> +      break;
>      case CPTK_IS_AGGREGATE:
>        inform (loc, "  %qT is not an aggregate", t1);
>        break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 3cd3babc242..8e76668f6ed 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
>  DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
> +DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index b976633645a..c4d44413dce 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_FUNCTION:
>        return type_code1 == FUNCTION_TYPE;
>  
> +    case CPTK_IS_VOID:
> +      return VOID_TYPE_P (type1);
> +
>      case CPTK_IS_FINAL:
>        return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
>  
> @@ -12297,6 +12300,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_SAME:
>      case CPTK_IS_REFERENCE:
>      case CPTK_IS_FUNCTION:
> +    case CPTK_IS_VOID:
>        break;
>  
>      case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index 90eb00ebf2d..b96cc9e6f50 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -152,3 +152,6 @@
>  #if !__has_builtin (__is_function)
>  # error "__has_builtin (__is_function) failed"
>  #endif
> +#if !__has_builtin (__is_void)
> +# error "__has_builtin (__is_void) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
> new file mode 100644
> index 00000000000..707f0d6875b
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_void.C
> @@ -0,0 +1,35 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <testsuite_tr1.h>
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
> +  SA(TRAIT(TYPE) == EXPECT);					\
> +  SA(TRAIT(const TYPE) == EXPECT);				\
> +  SA(TRAIT(volatile TYPE) == EXPECT);			\
> +  SA(TRAIT(const volatile TYPE) == EXPECT)
> +
> +SA_TEST_CATEGORY(__is_void, void, true);
> +
> +SA_TEST_CATEGORY(__is_void, char, false);
> +SA_TEST_CATEGORY(__is_void, signed char, false);
> +SA_TEST_CATEGORY(__is_void, unsigned char, false);
> +SA_TEST_CATEGORY(__is_void, wchar_t, false);
> +SA_TEST_CATEGORY(__is_void, short, false);
> +SA_TEST_CATEGORY(__is_void, unsigned short, false);
> +SA_TEST_CATEGORY(__is_void, int, false);
> +SA_TEST_CATEGORY(__is_void, unsigned int, false);
> +SA_TEST_CATEGORY(__is_void, long, false);
> +SA_TEST_CATEGORY(__is_void, unsigned long, false);
> +SA_TEST_CATEGORY(__is_void, long long, false);
> +SA_TEST_CATEGORY(__is_void, unsigned long long, false);
> +SA_TEST_CATEGORY(__is_void, float, false);
> +SA_TEST_CATEGORY(__is_void, double, false);
> +SA_TEST_CATEGORY(__is_void, long double, false);
> +
> +// Sanity check.
> +SA_TEST_CATEGORY(__is_void, ClassType, false);
> +SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
> +SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
> diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
> index 6d791484448..e689e293bd4 100644
> --- a/gcc/testsuite/g++.dg/tm/pr46567.C
> +++ b/gcc/testsuite/g++.dg/tm/pr46567.C
> @@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
>        typedef __true_type __type;
>      };
>    template<typename _Tp>
> -    struct __is_void
> +    struct ____is_void
>      {
>        enum { __value = 0 };
>        typedef __false_type __type;
>      };
>    template<>
> -    struct __is_void<void>
> +    struct ____is_void<void>
>      {
>        enum { __value = 1 };
>        typedef __true_type __type;
> @@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
>      { };
>    template<typename _Tp>
>      struct __is_fundamental
> -    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
> +    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
>      { };
>    template<typename _Tp>
>      struct __is_scalar
> diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
> index 4312f32a4e0..d329bc5b208 100644
> --- a/libstdc++-v3/include/bits/cpp_type_traits.h
> +++ b/libstdc++-v3/include/bits/cpp_type_traits.h
> @@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        typedef __true_type __type;
>      };
>  
> -  // Holds if the template-argument is a void type.
> -  template<typename _Tp>
> -    struct __is_void
> -    {
> -      enum { __value = 0 };
> -      typedef __false_type __type;
> -    };
> -
> -  template<>
> -    struct __is_void<void>
> -    {
> -      enum { __value = 1 };
> -      typedef __true_type __type;
> -    };
> -
>    //
>    // Integer types
>    //
> diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
> index dccf8e9e5e6..66b4e9e1ecf 100644
> --- a/libstdc++-v3/include/debug/helper_functions.h
> +++ b/libstdc++-v3/include/debug/helper_functions.h
> @@ -66,13 +66,12 @@ namespace __gnu_debug
>        typedef
>  	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
>  
> -      template<typename _DiffType,
> -	       typename = typename std::__is_void<_DiffType>::__type>
> +      template<typename _DiffType, typename = _DiffType>
>  	struct _DiffTraits
>  	{ typedef _DiffType __type; };
>  
>        template<typename _DiffType>
> -	struct _DiffTraits<_DiffType, std::__true_type>
> +	struct _DiffTraits<_DiffType, void>
>  	{ typedef std::ptrdiff_t __type; };
>  
>        typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 954b57518de..780fcc00135 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -3166,8 +3166,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>     * @{
>     * @ingroup variable_templates
>     */
> +#if __has_builtin(__is_void)
> +template <typename _Tp>
> +  inline constexpr bool is_void_v = __is_void(_Tp);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_void_v = is_void<_Tp>::value;
> +#endif

We should instead optimize this the way we do for the class template, by
defining 4 explicit specializations of is_void_v.

> +
>  template <typename _Tp>
>    inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
>  template <typename _Tp>
> -- 
> 2.41.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-06-12 22:47             ` [PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-06-20 16:05               ` Patrick Palka
  0 siblings, 0 replies; 92+ messages in thread
From: Patrick Palka @ 2023-06-20 16:05 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Mon, 12 Jun 2023, Ken Matsui via Libstdc++ wrote:

> This patch gets std::is_function to dispatch to new built-in trait
> __is_function.
> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/std/type_traits (is_function): Use __is_function built-in
> 	trait.
> 	(is_function_v): Likewise.

LGTM

> 
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>  libstdc++-v3/include/std/type_traits | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 2a14df7e5f9..954b57518de 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      { };
>  
>    /// is_function
> +#if __has_builtin(__is_function)
> +  template<typename _Tp>
> +    struct is_function
> +    : public __bool_constant<__is_function(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_function
>      : public __bool_constant<!is_const<const _Tp>::value> { };
> @@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _Tp>
>      struct is_function<_Tp&&>
>      : public false_type { };
> +#endif
>  
>  #define __cpp_lib_is_null_pointer 201309L
>  
> @@ -3197,8 +3204,14 @@ template <typename _Tp>
>    inline constexpr bool is_union_v = __is_union(_Tp);
>  template <typename _Tp>
>    inline constexpr bool is_class_v = __is_class(_Tp);
> +
> +#if __has_builtin(__is_function)
> +template <typename _Tp>
> +  inline constexpr bool is_function_v = __is_function(_Tp);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_function_v = is_function<_Tp>::value;
> +#endif
>  
>  #if __has_builtin(__is_reference)
>  template <typename _Tp>
> -- 
> 2.41.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 3/6] c++: implement __is_function built-in trait
  2023-06-12 22:47             ` [PATCH v7 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-06-20 16:05               ` Patrick Palka
  0 siblings, 0 replies; 92+ messages in thread
From: Patrick Palka @ 2023-06-20 16:05 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Mon, 12 Jun 2023, Ken Matsui via Gcc-patches wrote:

> This patch implements built-in trait for std::is_function.
> 
> gcc/cp/ChangeLog:
> 
> 	* cp-trait.def: Define __is_function.
> 	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
> 	* semantics.cc (trait_expr_value): Likewise.
> 	(finish_trait_expr): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
> 	* g++.dg/ext/is_function.C: New test.

LGTM

> 
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>  gcc/cp/constraint.cc                     |  3 ++
>  gcc/cp/cp-trait.def                      |  1 +
>  gcc/cp/semantics.cc                      |  4 ++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
>  gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
>  5 files changed, 69 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
> 
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index f6951ee2670..927605c6cb7 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
>      case CPTK_IS_UNION:
>        inform (loc, "  %qT is not a union", t1);
>        break;
> +    case CPTK_IS_FUNCTION:
> +      inform (loc, "  %qT is not a function", t1);
> +      break;
>      case CPTK_IS_AGGREGATE:
>        inform (loc, "  %qT is not an aggregate", t1);
>        break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 1e3310cd682..3cd3babc242 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> +DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 2f37bc353a1..b976633645a 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_ENUM:
>        return type_code1 == ENUMERAL_TYPE;
>  
> +    case CPTK_IS_FUNCTION:
> +      return type_code1 == FUNCTION_TYPE;
> +
>      case CPTK_IS_FINAL:
>        return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
>  
> @@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_UNION:
>      case CPTK_IS_SAME:
>      case CPTK_IS_REFERENCE:
> +    case CPTK_IS_FUNCTION:
>        break;
>  
>      case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index b697673790c..90eb00ebf2d 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -149,3 +149,6 @@
>  #if !__has_builtin (__is_reference)
>  # error "__has_builtin (__is_reference) failed"
>  #endif
> +#if !__has_builtin (__is_function)
> +# error "__has_builtin (__is_function) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
> new file mode 100644
> index 00000000000..2e1594b12ad
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_function.C
> @@ -0,0 +1,58 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <testsuite_tr1.h>
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
> +  SA(TRAIT(TYPE) == EXPECT);					\
> +  SA(TRAIT(const TYPE) == EXPECT);				\
> +  SA(TRAIT(volatile TYPE) == EXPECT);			\
> +  SA(TRAIT(const volatile TYPE) == EXPECT)
> +
> +struct A
> +{ void fn(); };
> +
> +template<typename>
> +struct AHolder { };
> +
> +template<class T, class U>
> +struct AHolder<U T::*>
> +{ using type = U; };
> +
> +// Positive tests.
> +SA(__is_function(int (int)));
> +SA(__is_function(ClassType (ClassType)));
> +SA(__is_function(float (int, float, int[], int&)));
> +SA(__is_function(int (int, ...)));
> +SA(__is_function(bool (ClassType) const));
> +SA(__is_function(AHolder<decltype(&A::fn)>::type));
> +
> +void fn();
> +SA(__is_function(decltype(fn)));
> +
> +// Negative tests.
> +SA_TEST_CATEGORY(__is_function, int, false);
> +SA_TEST_CATEGORY(__is_function, int*, false);
> +SA_TEST_CATEGORY(__is_function, int&, false);
> +SA_TEST_CATEGORY(__is_function, void, false);
> +SA_TEST_CATEGORY(__is_function, void*, false);
> +SA_TEST_CATEGORY(__is_function, void**, false);
> +SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
> +
> +SA_TEST_CATEGORY(__is_function, AbstractClass, false);
> +SA(!__is_function(int(&)(int)));
> +SA(!__is_function(int(*)(int)));
> +
> +SA_TEST_CATEGORY(__is_function, A, false);
> +SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
> +
> +struct FnCallOverload
> +{ void operator()(); };
> +SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
> +
> +// Sanity check.
> +SA_TEST_CATEGORY(__is_function, ClassType, false);
> +SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
> +SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
> -- 
> 2.41.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 1/6] c++: implement __is_reference built-in trait
  2023-06-12 22:47             ` [PATCH v7 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-06-20 16:06               ` Patrick Palka
  0 siblings, 0 replies; 92+ messages in thread
From: Patrick Palka @ 2023-06-20 16:06 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Mon, 12 Jun 2023, Ken Matsui via Libstdc++ wrote:

> This patch implements built-in trait for std::is_reference.
> 
> gcc/cp/ChangeLog:
> 
> 	* cp-trait.def: Define __is_reference.
> 	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
> 	* semantics.cc (trait_expr_value): Likewise.
> 	(finish_trait_expr): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
> 	* g++.dg/ext/is_reference.C: New test.

LGTM

> 
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>  gcc/cp/constraint.cc                     |  3 +++
>  gcc/cp/cp-trait.def                      |  1 +
>  gcc/cp/semantics.cc                      |  4 +++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
>  gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
>  5 files changed, 45 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
> 
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 8cf0f2d0974..f6951ee2670 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
>      case CPTK_HAS_VIRTUAL_DESTRUCTOR:
>        inform (loc, "  %qT does not have a virtual destructor", t1);
>        break;
> +    case CPTK_IS_REFERENCE:
> +      inform (loc, "  %qT is not a reference", t1);
> +      break;
>      case CPTK_IS_ABSTRACT:
>        inform (loc, "  %qT is not an abstract class", t1);
>        break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 8b7fece0cc8..1e3310cd682 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
>  DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
>  DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
>  DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
> +DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
>  DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
>  DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
>  DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index a2e74a5d2c7..2f37bc353a1 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_FINAL:
>        return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
>  
> +    case CPTK_IS_REFERENCE:
> +      return type_code1 == REFERENCE_TYPE;
> +
>      case CPTK_IS_LAYOUT_COMPATIBLE:
>        return layout_compatible_type_p (type1, type2);
>  
> @@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_ENUM:
>      case CPTK_IS_UNION:
>      case CPTK_IS_SAME:
> +    case CPTK_IS_REFERENCE:
>        break;
>  
>      case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index f343e153e56..b697673790c 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -146,3 +146,6 @@
>  #if !__has_builtin (__remove_cvref)
>  # error "__has_builtin (__remove_cvref) failed"
>  #endif
> +#if !__has_builtin (__is_reference)
> +# error "__has_builtin (__is_reference) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
> new file mode 100644
> index 00000000000..b5ce4db7afd
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_reference.C
> @@ -0,0 +1,34 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <testsuite_tr1.h>
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
> +  SA(TRAIT(TYPE) == EXPECT);					\
> +  SA(TRAIT(const TYPE) == EXPECT);				\
> +  SA(TRAIT(volatile TYPE) == EXPECT);			\
> +  SA(TRAIT(const volatile TYPE) == EXPECT)
> +
> +// Positive tests.
> +SA_TEST_CATEGORY(__is_reference, int&, true);
> +SA_TEST_CATEGORY(__is_reference, ClassType&, true);
> +SA(__is_reference(int(&)(int)));
> +SA_TEST_CATEGORY(__is_reference, int&&, true);
> +SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
> +SA(__is_reference(int(&&)(int)));
> +SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
> +
> +// Negative tests
> +SA_TEST_CATEGORY(__is_reference, void, false);
> +SA_TEST_CATEGORY(__is_reference, int*, false);
> +SA_TEST_CATEGORY(__is_reference, int[3], false);
> +SA(!__is_reference(int(int)));
> +SA(!__is_reference(int(*const)(int)));
> +SA(!__is_reference(int(*volatile)(int)));
> +SA(!__is_reference(int(*const volatile)(int)));
> +
> +// Sanity check.
> +SA_TEST_CATEGORY(__is_reference, ClassType, false);
> +SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
> -- 
> 2.41.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-06-12 22:47             ` [PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-06-20 16:07               ` Patrick Palka
  0 siblings, 0 replies; 92+ messages in thread
From: Patrick Palka @ 2023-06-20 16:07 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Mon, 12 Jun 2023, Ken Matsui via Libstdc++ wrote:

> This patch gets std::is_reference to dispatch to new built-in trait
> __is_reference.
> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/std/type_traits (is_reference): Use __is_reference built-in
> 	trait.
> 	(is_reference_v): Likewise.

LGTM

> 
> Signed-off-by: Ken Matsui <kmatsui@cs.washington.edu>
> ---
>  libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 0e7a9c9c7f3..2a14df7e5f9 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // Composite type categories.
>  
>    /// is_reference
> +#if __has_builtin(__is_reference)
> +  template<typename _Tp>
> +    struct is_reference
> +    : public __bool_constant<__is_reference(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_reference
>      : public false_type
> @@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      struct is_reference<_Tp&&>
>      : public true_type
>      { };
> +#endif
>  
>    /// is_arithmetic
>    template<typename _Tp>
> @@ -3192,12 +3199,19 @@ template <typename _Tp>
>    inline constexpr bool is_class_v = __is_class(_Tp);
>  template <typename _Tp>
>    inline constexpr bool is_function_v = is_function<_Tp>::value;
> +
> +#if __has_builtin(__is_reference)
> +template <typename _Tp>
> +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_reference_v = false;
>  template <typename _Tp>
>    inline constexpr bool is_reference_v<_Tp&> = true;
>  template <typename _Tp>
>    inline constexpr bool is_reference_v<_Tp&&> = true;
> +#endif
> +
>  template <typename _Tp>
>    inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
>  template <typename _Tp>
> -- 
> 2.41.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-20 15:32               ` Patrick Palka
@ 2023-06-24 15:12                 ` Ken Matsui
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
  0 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-06-24 15:12 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On Tue, Jun 20, 2023 at 8:32 AM Patrick Palka <ppalka@redhat.com> wrote:
>
> On Thu, 15 Jun 2023, Ken Matsui via Libstdc++ wrote:
>
> > Hi,
> >
> > For those curious about the performance improvements of this patch, I
> > conducted a benchmark that instantiates 256k specializations of
> > is_object_v based on Patrick's code. You can find the benchmark code
> > at this link:
> >
> > https://github.com/ken-matsui/gcc-benches/blob/main/is_object_benchmark.cc
> >
> > On my computer, using the gcc HEAD of this patch for a release build,
> > the patch with -DUSE_BUILTIN took 64% less time and used 44-47% less
> > memory compared to not using it.
>
> That's more like it :D  Though the benchmark should also invoke the
> trait on non-object types too, e.g. Instantiator& or Instantiator(int).

Here is the updated benchmark:

https://github.com/ken-matsui/gcc-benches/blob/main/is_object.md#sat-jun-24-080110-am-pdt-2023

Time: -74.7544%
Peak Memory Usage: -62.5913%
Total Memory Usage: -64.2708%

> >
> > Sincerely,
> > Ken Matsui
> >
> > On Mon, Jun 12, 2023 at 3:49 PM Ken Matsui <kmatsui@cs.washington.edu> wrote:
> > >
> > > Hi,
> > >
> > > This patch series gets std::is_object to dispatch to built-in traits and
> > > implements the following built-in traits, on which std::object depends.
> > >
> > >         * __is_reference
> > >         * __is_function
> > >         * __is_void
> > >
> > > std::is_object was depending on them with disjunction and negation.
> > >
> > > __not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type
> > >
> > > Therefore, this patch uses them directly instead of implementing an additional
> > > built-in trait __is_object, which makes the compiler slightly bigger and
> > > slower.
> > >
> > > __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>
> > >
> > > This would instantiate only __bool_constant<true> and __bool_constant<false>,
> > > which can be mostly shared. That is, the purpose of built-in traits is
> > > considered as achieved.
> > >
> > > Changes in v7
> > >
> > >         * Removed an unnecessary new line.
> > >
> > > Ken Matsui (6):
> > >   c++: implement __is_reference built-in trait
> > >   libstdc++: use new built-in trait __is_reference for std::is_reference
> > >   c++: implement __is_function built-in trait
> > >   libstdc++: use new built-in trait __is_function for std::is_function
> > >   c++, libstdc++: implement __is_void built-in trait
> > >   libstdc++: make std::is_object dispatch to new built-in traits
> > >
> > >  gcc/cp/constraint.cc                          |  9 +++
> > >  gcc/cp/cp-trait.def                           |  3 +
> > >  gcc/cp/semantics.cc                           | 12 ++++
> > >  gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
> > >  gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
> > >  gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
> > >  gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
> > >  gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
> > >  libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
> > >  libstdc++-v3/include/debug/helper_functions.h |  5 +-
> > >  libstdc++-v3/include/std/type_traits          | 51 ++++++++++++++++
> > >  11 files changed, 216 insertions(+), 21 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
> > >  create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
> > >  create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C
> > >
> > > --
> > > 2.41.0
> > >
> >
> >

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits
  2023-06-24 15:12                 ` Ken Matsui
@ 2023-07-08  5:08                   ` Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 1/6] c++: implement __is_reference built-in trait Ken Matsui
                                       ` (6 more replies)
  0 siblings, 7 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function
	* __is_void

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp))>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v8

	* Updated the commit author to kmatsui@gcc.gnu.org considering the
	expiration of my university's email address.

Ken Matsui (6):
  c++: implement __is_reference built-in trait
  libstdc++: use new built-in trait __is_reference for std::is_reference
  c++: implement __is_function built-in trait
  libstdc++: use new built-in trait __is_function for std::is_function
  c++, libstdc++: implement __is_void built-in trait
  libstdc++: make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                          |  9 +++
 gcc/cp/cp-trait.def                           |  3 +
 gcc/cp/semantics.cc                           | 12 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  9 +++
 gcc/testsuite/g++.dg/ext/is_function.C        | 58 +++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C       | 34 +++++++++++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 -----
 libstdc++-v3/include/debug/helper_functions.h |  5 +-
 libstdc++-v3/include/std/type_traits          | 51 ++++++++++++++++
 11 files changed, 216 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 1/6] c++: implement __is_reference built-in trait
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
@ 2023-07-08  5:08                     ` Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
                                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..f6951ee2670 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..1e3310cd682 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a2e74a5d2c7..2f37bc353a1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 1/6] c++: implement __is_reference built-in trait Ken Matsui
@ 2023-07-08  5:08                     ` Ken Matsui
  2023-07-12 10:08                       ` Jonathan Wakely
  2023-07-08  5:08                     ` [PATCH v8 3/6] c++: implement __is_function built-in trait Ken Matsui
                                       ` (4 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.
	(is_reference_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..2a14df7e5f9 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
@@ -3192,12 +3199,19 @@ template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template <typename _Tp>
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_reference_v = false;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&> = true;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 3/6] c++: implement __is_function built-in trait
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 1/6] c++: implement __is_reference built-in trait Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-07-08  5:08                     ` Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
                                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6951ee2670..927605c6cb7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 1e3310cd682..3cd3babc242 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 2f37bc353a1..b976633645a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
                                       ` (2 preceding siblings ...)
  2023-07-08  5:08                     ` [PATCH v8 3/6] c++: implement __is_function built-in trait Ken Matsui
@ 2023-07-08  5:08                     ` Ken Matsui
  2023-07-12 10:10                       ` Jonathan Wakely
  2023-07-08  5:08                     ` [PATCH v8 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
                                       ` (2 subsequent siblings)
  6 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.
	(is_function_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 libstdc++-v3/include/std/type_traits | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2a14df7e5f9..954b57518de 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template <typename _Tp>
   inline constexpr bool is_union_v = __is_union(_Tp);
 template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template <typename _Tp>
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 5/6] c++, libstdc++: implement __is_void built-in trait
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
                                       ` (3 preceding siblings ...)
  2023-07-08  5:08                     ` [PATCH v8 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-07-08  5:08                     ` Ken Matsui
  2023-07-08  5:08                     ` [PATCH v8 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_void. Since the new built-in
name is __is_void, to avoid unintentional macro replacement, this patch also
involves the removal of the existing __is_void in helper_functions.h and
cpp_type_traits.h and renaming __is_void to ____is_void in the test file,
pr46567.C.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_void.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOID.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/tm/pr46567.C (__is_void): Rename to ...
	(____is_void): ... this.
	* g++.dg/ext/has-builtin-1.C: Test existence of __is_void.
	* g++.dg/ext/is_void.C: New test.

libstdc++-v3/ChangeLog:

	* include/debug/helper_functions.h (_DiffTraits): Stop using
	__is_void.
	* include/bits/cpp_type_traits.h (__is_void): Remove unused __is_void.
	* include/std/type_traits (is_void_v): Use __is_void built-in
	trait.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 gcc/cp/constraint.cc                          |  3 ++
 gcc/cp/cp-trait.def                           |  1 +
 gcc/cp/semantics.cc                           |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C      |  3 ++
 gcc/testsuite/g++.dg/ext/is_void.C            | 35 +++++++++++++++++++
 gcc/testsuite/g++.dg/tm/pr46567.C             |  6 ++--
 libstdc++-v3/include/bits/cpp_type_traits.h   | 15 --------
 libstdc++-v3/include/debug/helper_functions.h |  5 ++-
 libstdc++-v3/include/std/type_traits          |  6 ++++
 9 files changed, 57 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_void.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 927605c6cb7..e8cd98eb2c7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3757,6 +3757,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_FUNCTION:
       inform (loc, "  %qT is not a function", t1);
       break;
+    case CPTK_IS_VOID:
+      inform (loc, "  %qT is not a void type", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 3cd3babc242..8e76668f6ed 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_VOID, "__is_void", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b976633645a..c4d44413dce 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FUNCTION:
       return type_code1 == FUNCTION_TYPE;
 
+    case CPTK_IS_VOID:
+      return VOID_TYPE_P (type1);
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12297,6 +12300,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
     case CPTK_IS_FUNCTION:
+    case CPTK_IS_VOID:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90eb00ebf2d..b96cc9e6f50 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -152,3 +152,6 @@
 #if !__has_builtin (__is_function)
 # error "__has_builtin (__is_function) failed"
 #endif
+#if !__has_builtin (__is_void)
+# error "__has_builtin (__is_void) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_void.C b/gcc/testsuite/g++.dg/ext/is_void.C
new file mode 100644
index 00000000000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_void, void, true);
+
+SA_TEST_CATEGORY(__is_void, char, false);
+SA_TEST_CATEGORY(__is_void, signed char, false);
+SA_TEST_CATEGORY(__is_void, unsigned char, false);
+SA_TEST_CATEGORY(__is_void, wchar_t, false);
+SA_TEST_CATEGORY(__is_void, short, false);
+SA_TEST_CATEGORY(__is_void, unsigned short, false);
+SA_TEST_CATEGORY(__is_void, int, false);
+SA_TEST_CATEGORY(__is_void, unsigned int, false);
+SA_TEST_CATEGORY(__is_void, long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long, false);
+SA_TEST_CATEGORY(__is_void, long long, false);
+SA_TEST_CATEGORY(__is_void, unsigned long long, false);
+SA_TEST_CATEGORY(__is_void, float, false);
+SA_TEST_CATEGORY(__is_void, double, false);
+SA_TEST_CATEGORY(__is_void, long double, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_void, ClassType, false);
+SA_TEST_CATEGORY(__is_void, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_void, IncompleteUnion, false);
diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C
index 6d791484448..e689e293bd4 100644
--- a/gcc/testsuite/g++.dg/tm/pr46567.C
+++ b/gcc/testsuite/g++.dg/tm/pr46567.C
@@ -72,13 +72,13 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
       typedef __true_type __type;
     };
   template<typename _Tp>
-    struct __is_void
+    struct ____is_void
     {
       enum { __value = 0 };
       typedef __false_type __type;
     };
   template<>
-    struct __is_void<void>
+    struct ____is_void<void>
     {
       enum { __value = 1 };
       typedef __true_type __type;
@@ -222,7 +222,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) {
     { };
   template<typename _Tp>
     struct __is_fundamental
-    : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> >
+    : public __traitor<____is_void<_Tp>, __is_arithmetic<_Tp> >
     { };
   template<typename _Tp>
     struct __is_scalar
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 4312f32a4e0..d329bc5b208 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -105,21 +105,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __true_type __type;
     };
 
-  // Holds if the template-argument is a void type.
-  template<typename _Tp>
-    struct __is_void
-    {
-      enum { __value = 0 };
-      typedef __false_type __type;
-    };
-
-  template<>
-    struct __is_void<void>
-    {
-      enum { __value = 1 };
-      typedef __true_type __type;
-    };
-
   //
   // Integer types
   //
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index dccf8e9e5e6..66b4e9e1ecf 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -66,13 +66,12 @@ namespace __gnu_debug
       typedef
 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
 
-      template<typename _DiffType,
-	       typename = typename std::__is_void<_DiffType>::__type>
+      template<typename _DiffType, typename = _DiffType>
 	struct _DiffTraits
 	{ typedef _DiffType __type; };
 
       template<typename _DiffType>
-	struct _DiffTraits<_DiffType, std::__true_type>
+	struct _DiffTraits<_DiffType, void>
 	{ typedef std::ptrdiff_t __type; };
 
       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 954b57518de..780fcc00135 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3166,8 +3166,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @{
    * @ingroup variable_templates
    */
+#if __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_void_v = __is_void(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_void_v = is_void<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v8 6/6] libstdc++: make std::is_object dispatch to new built-in traits
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
                                       ` (4 preceding siblings ...)
  2023-07-08  5:08                     ` [PATCH v8 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
@ 2023-07-08  5:08                     ` Ken Matsui
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
  6 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-08  5:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function, __is_reference, and __is_void.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function, __is_reference, and __is_void.
	(is_object_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 libstdc++-v3/include/std/type_traits | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 780fcc00135..715310f10bf 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                             __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
@@ -3235,8 +3244,17 @@ template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+template <typename _Tp>
+  inline constexpr bool is_object_v
+    = !(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp));
+#else
 template <typename _Tp>
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v8 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference
  2023-07-08  5:08                     ` [PATCH v8 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-07-12 10:08                       ` Jonathan Wakely
  0 siblings, 0 replies; 92+ messages in thread
From: Jonathan Wakely @ 2023-07-12 10:08 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Sat, 8 Jul 2023 at 06:13, Ken Matsui via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> This patch gets std::is_reference to dispatch to new built-in trait
> __is_reference.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/type_traits (is_reference): Use __is_reference built-in
>         trait.
>         (is_reference_v): Likewise.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>

OK for trunk after the front-end __is_reference is committed.


> ---
>  libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
>
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 0e7a9c9c7f3..2a14df7e5f9 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // Composite type categories.
>
>    /// is_reference
> +#if __has_builtin(__is_reference)
> +  template<typename _Tp>
> +    struct is_reference
> +    : public __bool_constant<__is_reference(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_reference
>      : public false_type
> @@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      struct is_reference<_Tp&&>
>      : public true_type
>      { };
> +#endif
>
>    /// is_arithmetic
>    template<typename _Tp>
> @@ -3192,12 +3199,19 @@ template <typename _Tp>
>    inline constexpr bool is_class_v = __is_class(_Tp);
>  template <typename _Tp>
>    inline constexpr bool is_function_v = is_function<_Tp>::value;
> +
> +#if __has_builtin(__is_reference)
> +template <typename _Tp>
> +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_reference_v = false;
>  template <typename _Tp>
>    inline constexpr bool is_reference_v<_Tp&> = true;
>  template <typename _Tp>
>    inline constexpr bool is_reference_v<_Tp&&> = true;
> +#endif
> +
>  template <typename _Tp>
>    inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
>  template <typename _Tp>
> --
> 2.41.0
>


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v8 4/6] libstdc++: use new built-in trait __is_function for std::is_function
  2023-07-08  5:08                     ` [PATCH v8 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-07-12 10:10                       ` Jonathan Wakely
  0 siblings, 0 replies; 92+ messages in thread
From: Jonathan Wakely @ 2023-07-12 10:10 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

On Sat, 8 Jul 2023 at 06:15, Ken Matsui via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> This patch gets std::is_function to dispatch to new built-in trait
> __is_function.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/type_traits (is_function): Use __is_function built-in
>         trait.
>         (is_function_v): Likewise.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> ---
>  libstdc++-v3/include/std/type_traits | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 2a14df7e5f9..954b57518de 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      { };
>
>    /// is_function
> +#if __has_builtin(__is_function)
> +  template<typename _Tp>
> +    struct is_function
> +    : public __bool_constant<__is_function(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_function
>      : public __bool_constant<!is_const<const _Tp>::value> { };
> @@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _Tp>
>      struct is_function<_Tp&&>
>      : public false_type { };
> +#endif
>
>  #define __cpp_lib_is_null_pointer 201309L
>
> @@ -3197,8 +3204,14 @@ template <typename _Tp>
>    inline constexpr bool is_union_v = __is_union(_Tp);
>  template <typename _Tp>
>    inline constexpr bool is_class_v = __is_class(_Tp);
> +
> +#if __has_builtin(__is_function)
> +template <typename _Tp>
> +  inline constexpr bool is_function_v = __is_function(_Tp);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_function_v = is_function<_Tp>::value;

This fallback could be:

template <typename _Tp>
   inline constexpr bool is_function_v = !is_const_v<const _Tp>;

That would avoid instantiating std::is_function and std::is_const and
std::integral_constant, which should be significant.


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v10 0/5] c++, libstdc++: Make std::is_object dispatch to new built-in traits
  2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
                                       ` (5 preceding siblings ...)
  2023-07-08  5:08                     ` [PATCH v8 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-07-13  2:33                     ` Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 1/5] c++: Implement __is_reference built-in trait Ken Matsui
                                         ` (4 more replies)
  6 siblings, 5 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

Hi,

This patch series gets std::is_object to dispatch to built-in traits and
implements the following built-in traits, on which std::object depends.

	* __is_reference
	* __is_function

std::is_object was depending on them with disjunction and negation.

__not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type

Therefore, this patch uses them directly instead of implementing an additional
built-in trait __is_object, which makes the compiler slightly bigger and
slower.

__bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) || is_void<_Tp>::value)>

This would instantiate only __bool_constant<true> and __bool_constant<false>,
which can be mostly shared. That is, the purpose of built-in traits is
considered as achieved.

Changes in v8

	* Dropped __is_void built-in implementation since it is optimal.
	* Optimized is_function_v

Ken Matsui (5):
  c++: Implement __is_reference built-in trait
  libstdc++: Use new built-in trait __is_reference for std::is_reference
  c++: Implement __is_function built-in trait
  libstdc++: Use new built-in trait __is_function for std::is_function
  libstdc++: Make std::is_object dispatch to new built-in traits

 gcc/cp/constraint.cc                     |  6 +++
 gcc/cp/cp-trait.def                      |  2 +
 gcc/cp/semantics.cc                      |  8 ++++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  6 +++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++
 libstdc++-v3/include/std/type_traits     | 50 +++++++++++++++++++-
 7 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v10 1/5] c++: Implement __is_reference built-in trait
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
@ 2023-07-13  2:33                       ` Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference Ken Matsui
                                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_reference.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_reference.
	* g++.dg/ext/is_reference.C: New test.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 gcc/cp/constraint.cc                     |  3 +++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/is_reference.C  | 34 ++++++++++++++++++++++++
 5 files changed, 45 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..f6951ee2670 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3705,6 +3705,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_HAS_VIRTUAL_DESTRUCTOR:
       inform (loc, "  %qT does not have a virtual destructor", t1);
       break;
+    case CPTK_IS_REFERENCE:
+      inform (loc, "  %qT is not a reference", t1);
+      break;
     case CPTK_IS_ABSTRACT:
       inform (loc, "  %qT is not an abstract class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..1e3310cd682 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -67,6 +67,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a2e74a5d2c7..2f37bc353a1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12075,6 +12075,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
+    case CPTK_IS_REFERENCE:
+      return type_code1 == REFERENCE_TYPE;
+
     case CPTK_IS_LAYOUT_COMPATIBLE:
       return layout_compatible_type_p (type1, type2);
 
@@ -12289,6 +12292,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
+    case CPTK_IS_REFERENCE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..b697673790c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_reference)
+# error "__has_builtin (__is_reference) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_reference.C b/gcc/testsuite/g++.dg/ext/is_reference.C
new file mode 100644
index 00000000000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+// Positive tests.
+SA_TEST_CATEGORY(__is_reference, int&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&, true);
+SA(__is_reference(int(&)(int)));
+SA_TEST_CATEGORY(__is_reference, int&&, true);
+SA_TEST_CATEGORY(__is_reference, ClassType&&, true);
+SA(__is_reference(int(&&)(int)));
+SA_TEST_CATEGORY(__is_reference, IncompleteClass&, true);
+
+// Negative tests
+SA_TEST_CATEGORY(__is_reference, void, false);
+SA_TEST_CATEGORY(__is_reference, int*, false);
+SA_TEST_CATEGORY(__is_reference, int[3], false);
+SA(!__is_reference(int(int)));
+SA(!__is_reference(int(*const)(int)));
+SA(!__is_reference(int(*volatile)(int)));
+SA(!__is_reference(int(*const volatile)(int)));
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_reference, ClassType, false);
+SA_TEST_CATEGORY(__is_reference, IncompleteClass, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 1/5] c++: Implement __is_reference built-in trait Ken Matsui
@ 2023-07-13  2:33                       ` Ken Matsui
  2023-07-13  2:56                         ` Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 3/5] c++: Implement __is_function built-in trait Ken Matsui
                                         ` (2 subsequent siblings)
  4 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_reference to dispatch to new built-in trait
__is_reference.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_reference): Use __is_reference built-in
	trait.
	(is_reference_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..2a14df7e5f9 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if __has_builtin(__is_reference)
+  template<typename _Tp>
+    struct is_reference
+    : public __bool_constant<__is_reference(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_reference
     : public false_type
@@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_reference<_Tp&&>
     : public true_type
     { };
+#endif
 
   /// is_arithmetic
   template<typename _Tp>
@@ -3192,12 +3199,19 @@ template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
 template <typename _Tp>
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template <typename _Tp>
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template <typename _Tp>
   inline constexpr bool is_reference_v = false;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&> = true;
 template <typename _Tp>
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v10 3/5] c++: Implement __is_function built-in trait
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 1/5] c++: Implement __is_reference built-in trait Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-07-13  2:33                       ` Ken Matsui
  2023-07-13  2:41                         ` Ken Matsui
  2023-08-22 19:52                         ` Patrick Palka
  2023-07-13  2:33                       ` [PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function Ken Matsui
  2023-07-13  2:33                       ` [PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits Ken Matsui
  4 siblings, 2 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_function.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
	* g++.dg/ext/is_function.C: New test.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 gcc/cp/constraint.cc                     |  3 ++
 gcc/cp/cp-trait.def                      |  1 +
 gcc/cp/semantics.cc                      |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6951ee2670..927605c6cb7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_FUNCTION:
+      inform (loc, "  %qT is not a function", t1);
+      break;
     case CPTK_IS_AGGREGATE:
       inform (loc, "  %qT is not an aggregate", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 1e3310cd682..3cd3babc242 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 2f37bc353a1..b976633645a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
       return type_code1 == ENUMERAL_TYPE;
 
+    case CPTK_IS_FUNCTION:
+      return type_code1 == FUNCTION_TYPE;
+
     case CPTK_IS_FINAL:
       return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
     case CPTK_IS_SAME:
     case CPTK_IS_REFERENCE:
+    case CPTK_IS_FUNCTION:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index b697673790c..90eb00ebf2d 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -149,3 +149,6 @@
 #if !__has_builtin (__is_reference)
 # error "__has_builtin (__is_reference) failed"
 #endif
+#if !__has_builtin (__is_function)
+# error "__has_builtin (__is_function) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
new file mode 100644
index 00000000000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);					\
+  SA(TRAIT(const TYPE) == EXPECT);				\
+  SA(TRAIT(volatile TYPE) == EXPECT);			\
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+struct A
+{ void fn(); };
+
+template<typename>
+struct AHolder { };
+
+template<class T, class U>
+struct AHolder<U T::*>
+{ using type = U; };
+
+// Positive tests.
+SA(__is_function(int (int)));
+SA(__is_function(ClassType (ClassType)));
+SA(__is_function(float (int, float, int[], int&)));
+SA(__is_function(int (int, ...)));
+SA(__is_function(bool (ClassType) const));
+SA(__is_function(AHolder<decltype(&A::fn)>::type));
+
+void fn();
+SA(__is_function(decltype(fn)));
+
+// Negative tests.
+SA_TEST_CATEGORY(__is_function, int, false);
+SA_TEST_CATEGORY(__is_function, int*, false);
+SA_TEST_CATEGORY(__is_function, int&, false);
+SA_TEST_CATEGORY(__is_function, void, false);
+SA_TEST_CATEGORY(__is_function, void*, false);
+SA_TEST_CATEGORY(__is_function, void**, false);
+SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
+
+SA_TEST_CATEGORY(__is_function, AbstractClass, false);
+SA(!__is_function(int(&)(int)));
+SA(!__is_function(int(*)(int)));
+
+SA_TEST_CATEGORY(__is_function, A, false);
+SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
+
+struct FnCallOverload
+{ void operator()(); };
+SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_function, ClassType, false);
+SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
+SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
                                         ` (2 preceding siblings ...)
  2023-07-13  2:33                       ` [PATCH v10 3/5] c++: Implement __is_function built-in trait Ken Matsui
@ 2023-07-13  2:33                       ` Ken Matsui
  2023-08-08 20:35                         ` Jonathan Wakely
  2023-07-13  2:33                       ` [PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits Ken Matsui
  4 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_function to dispatch to new built-in trait
__is_function.

libstdc++-v3/ChangeLog:

	* include/std/type_traits (is_function): Use __is_function built-in
	trait.
	(is_function_v): Likewise. Optimize its implementation.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 libstdc++-v3/include/std/type_traits | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 2a14df7e5f9..7ef50a2e64f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_function
+#if __has_builtin(__is_function)
+  template<typename _Tp>
+    struct is_function
+    : public __bool_constant<__is_function(_Tp)>
+    { };
+#else
   template<typename _Tp>
     struct is_function
     : public __bool_constant<!is_const<const _Tp>::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_function<_Tp&&>
     : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,18 @@ template <typename _Tp>
   inline constexpr bool is_union_v = __is_union(_Tp);
 template <typename _Tp>
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
 template <typename _Tp>
-  inline constexpr bool is_function_v = is_function<_Tp>::value;
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
+template <typename _Tp>
+  inline constexpr bool is_function_v = !is_const_v<const _Tp>;
+template <typename _Tp>
+  inline constexpr bool is_function_v<_Tp&> = false;
+template <typename _Tp>
+  inline constexpr bool is_function_v<_Tp&&> = false;
+#endif
 
 #if __has_builtin(__is_reference)
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits
  2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
                                         ` (3 preceding siblings ...)
  2023-07-13  2:33                       ` [PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-07-13  2:33                       ` Ken Matsui
  2023-09-01 13:00                         ` [PING][PATCH " Ken Matsui
  4 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Ken Matsui

This patch gets std::is_object to dispatch to new built-in traits,
__is_function and __is_reference.

libstdc++-v3/ChangeLog:
	* include/std/type_traits (is_object): Use new built-in traits,
	__is_function and __is_reference.
	(is_object_v): Likewise.

Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
 libstdc++-v3/include/std/type_traits | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 7ef50a2e64f..4ff025b09fa 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,11 +682,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
 
   /// is_object
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+    && __has_builtin(__is_void)
+  template<typename _Tp>
+    struct is_object
+    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
+                             __is_void(_Tp))>
+    { };
+#else
   template<typename _Tp>
     struct is_object
     : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                           is_void<_Tp>>>::type
     { };
+#endif
 
   template<typename>
     struct is_member_pointer;
@@ -3233,8 +3242,16 @@ template <typename _Tp>
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template <typename _Tp>
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference)
+template <typename _Tp>
+  inline constexpr bool is_object_v
+    = !(__is_function(_Tp) || __is_reference(_Tp) || is_void<_Tp>::value);
+#else
 template <typename _Tp>
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template <typename _Tp>
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template <typename _Tp>
-- 
2.41.0


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v10 3/5] c++: Implement __is_function built-in trait
  2023-07-13  2:33                       ` [PATCH v10 3/5] c++: Implement __is_function built-in trait Ken Matsui
@ 2023-07-13  2:41                         ` Ken Matsui
  2023-08-22 19:52                         ` Patrick Palka
  1 sibling, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:41 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

Hi,

Here is the benchmark result for is_function:

https://github.com/ken-matsui/gcc-benches/blob/main/is_function.md#wed-jul-12-072510-pm-pdt-2023

Time: -21.3748%
Peak Memory Usage: -10.962%
Total Memory Usage: -12.8384%

Sincerely,
Ken Matsui

On Wed, Jul 12, 2023 at 7:40 PM Ken Matsui <kmatsui@gcc.gnu.org> wrote:
>
> This patch implements built-in trait for std::is_function.
>
> gcc/cp/ChangeLog:
>
>         * cp-trait.def: Define __is_function.
>         * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
>         * semantics.cc (trait_expr_value): Likewise.
>         (finish_trait_expr): Likewise.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
>         * g++.dg/ext/is_function.C: New test.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> ---
>  gcc/cp/constraint.cc                     |  3 ++
>  gcc/cp/cp-trait.def                      |  1 +
>  gcc/cp/semantics.cc                      |  4 ++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
>  gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
>  5 files changed, 69 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index f6951ee2670..927605c6cb7 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
>      case CPTK_IS_UNION:
>        inform (loc, "  %qT is not a union", t1);
>        break;
> +    case CPTK_IS_FUNCTION:
> +      inform (loc, "  %qT is not a function", t1);
> +      break;
>      case CPTK_IS_AGGREGATE:
>        inform (loc, "  %qT is not an aggregate", t1);
>        break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 1e3310cd682..3cd3babc242 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> +DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 2f37bc353a1..b976633645a 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_ENUM:
>        return type_code1 == ENUMERAL_TYPE;
>
> +    case CPTK_IS_FUNCTION:
> +      return type_code1 == FUNCTION_TYPE;
> +
>      case CPTK_IS_FINAL:
>        return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
>
> @@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_UNION:
>      case CPTK_IS_SAME:
>      case CPTK_IS_REFERENCE:
> +    case CPTK_IS_FUNCTION:
>        break;
>
>      case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index b697673790c..90eb00ebf2d 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -149,3 +149,6 @@
>  #if !__has_builtin (__is_reference)
>  # error "__has_builtin (__is_reference) failed"
>  #endif
> +#if !__has_builtin (__is_function)
> +# error "__has_builtin (__is_function) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
> new file mode 100644
> index 00000000000..2e1594b12ad
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_function.C
> @@ -0,0 +1,58 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <testsuite_tr1.h>
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)  \
> +  SA(TRAIT(TYPE) == EXPECT);                                   \
> +  SA(TRAIT(const TYPE) == EXPECT);                             \
> +  SA(TRAIT(volatile TYPE) == EXPECT);                  \
> +  SA(TRAIT(const volatile TYPE) == EXPECT)
> +
> +struct A
> +{ void fn(); };
> +
> +template<typename>
> +struct AHolder { };
> +
> +template<class T, class U>
> +struct AHolder<U T::*>
> +{ using type = U; };
> +
> +// Positive tests.
> +SA(__is_function(int (int)));
> +SA(__is_function(ClassType (ClassType)));
> +SA(__is_function(float (int, float, int[], int&)));
> +SA(__is_function(int (int, ...)));
> +SA(__is_function(bool (ClassType) const));
> +SA(__is_function(AHolder<decltype(&A::fn)>::type));
> +
> +void fn();
> +SA(__is_function(decltype(fn)));
> +
> +// Negative tests.
> +SA_TEST_CATEGORY(__is_function, int, false);
> +SA_TEST_CATEGORY(__is_function, int*, false);
> +SA_TEST_CATEGORY(__is_function, int&, false);
> +SA_TEST_CATEGORY(__is_function, void, false);
> +SA_TEST_CATEGORY(__is_function, void*, false);
> +SA_TEST_CATEGORY(__is_function, void**, false);
> +SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
> +
> +SA_TEST_CATEGORY(__is_function, AbstractClass, false);
> +SA(!__is_function(int(&)(int)));
> +SA(!__is_function(int(*)(int)));
> +
> +SA_TEST_CATEGORY(__is_function, A, false);
> +SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
> +
> +struct FnCallOverload
> +{ void operator()(); };
> +SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
> +
> +// Sanity check.
> +SA_TEST_CATEGORY(__is_function, ClassType, false);
> +SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
> +SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
> --
> 2.41.0
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference
  2023-07-13  2:33                       ` [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference Ken Matsui
@ 2023-07-13  2:56                         ` Ken Matsui
  2023-09-04 15:00                           ` [PING][PATCH " Ken Matsui
  0 siblings, 1 reply; 92+ messages in thread
From: Ken Matsui @ 2023-07-13  2:56 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

Hi,

Here is the benchmark result for is_reference:

https://github.com/ken-matsui/gcc-benches/blob/main/is_reference.md#wed-jul-12-074702-pm-pdt-2023

Time: -8.15593%
Peak Memory Usage: -4.48408%
Total Memory Usage: -8.03783%

Sincerely,
Ken Matsui

On Wed, Jul 12, 2023 at 7:39 PM Ken Matsui <kmatsui@gcc.gnu.org> wrote:
>
> This patch gets std::is_reference to dispatch to new built-in trait
> __is_reference.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/type_traits (is_reference): Use __is_reference built-in
>         trait.
>         (is_reference_v): Likewise.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> ---
>  libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
>
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 0e7a9c9c7f3..2a14df7e5f9 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // Composite type categories.
>
>    /// is_reference
> +#if __has_builtin(__is_reference)
> +  template<typename _Tp>
> +    struct is_reference
> +    : public __bool_constant<__is_reference(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_reference
>      : public false_type
> @@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      struct is_reference<_Tp&&>
>      : public true_type
>      { };
> +#endif
>
>    /// is_arithmetic
>    template<typename _Tp>
> @@ -3192,12 +3199,19 @@ template <typename _Tp>
>    inline constexpr bool is_class_v = __is_class(_Tp);
>  template <typename _Tp>
>    inline constexpr bool is_function_v = is_function<_Tp>::value;
> +
> +#if __has_builtin(__is_reference)
> +template <typename _Tp>
> +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_reference_v = false;
>  template <typename _Tp>
>    inline constexpr bool is_reference_v<_Tp&> = true;
>  template <typename _Tp>
>    inline constexpr bool is_reference_v<_Tp&&> = true;
> +#endif
> +
>  template <typename _Tp>
>    inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
>  template <typename _Tp>
> --
> 2.41.0
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function
  2023-07-13  2:33                       ` [PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function Ken Matsui
@ 2023-08-08 20:35                         ` Jonathan Wakely
  0 siblings, 0 replies; 92+ messages in thread
From: Jonathan Wakely @ 2023-08-08 20:35 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 2158 bytes --]

On Thu, 13 Jul 2023 at 03:41, Ken Matsui via Libstdc++ <
libstdc++@gcc.gnu.org> wrote:

> This patch gets std::is_function to dispatch to new built-in trait
> __is_function.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/type_traits (is_function): Use __is_function built-in
>         trait.
>         (is_function_v): Likewise. Optimize its implementation.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
>

OK for trunk (after the compiler change is approved).




> ---
>  libstdc++-v3/include/std/type_traits | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/libstdc++-v3/include/std/type_traits
> b/libstdc++-v3/include/std/type_traits
> index 2a14df7e5f9..7ef50a2e64f 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -594,6 +594,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      { };
>
>    /// is_function
> +#if __has_builtin(__is_function)
> +  template<typename _Tp>
> +    struct is_function
> +    : public __bool_constant<__is_function(_Tp)>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_function
>      : public __bool_constant<!is_const<const _Tp>::value> { };
> @@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _Tp>
>      struct is_function<_Tp&&>
>      : public false_type { };
> +#endif
>
>  #define __cpp_lib_is_null_pointer 201309L
>
> @@ -3197,8 +3204,18 @@ template <typename _Tp>
>    inline constexpr bool is_union_v = __is_union(_Tp);
>  template <typename _Tp>
>    inline constexpr bool is_class_v = __is_class(_Tp);
> +
> +#if __has_builtin(__is_function)
>  template <typename _Tp>
> -  inline constexpr bool is_function_v = is_function<_Tp>::value;
> +  inline constexpr bool is_function_v = __is_function(_Tp);
> +#else
> +template <typename _Tp>
> +  inline constexpr bool is_function_v = !is_const_v<const _Tp>;
> +template <typename _Tp>
> +  inline constexpr bool is_function_v<_Tp&> = false;
> +template <typename _Tp>
> +  inline constexpr bool is_function_v<_Tp&&> = false;
> +#endif
>
>  #if __has_builtin(__is_reference)
>  template <typename _Tp>
> --
> 2.41.0
>
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v10 3/5] c++: Implement __is_function built-in trait
  2023-07-13  2:33                       ` [PATCH v10 3/5] c++: Implement __is_function built-in trait Ken Matsui
  2023-07-13  2:41                         ` Ken Matsui
@ 2023-08-22 19:52                         ` Patrick Palka
  2023-09-04 15:00                           ` [PING][PATCH " Ken Matsui
  1 sibling, 1 reply; 92+ messages in thread
From: Patrick Palka @ 2023-08-22 19:52 UTC (permalink / raw)
  To: Ken Matsui; +Cc: gcc-patches, libstdc++, jason

On Wed, 12 Jul 2023, Ken Matsui via Libstdc++ wrote:

> This patch implements built-in trait for std::is_function.
> 
> gcc/cp/ChangeLog:
> 
> 	* cp-trait.def: Define __is_function.
> 	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
> 	* semantics.cc (trait_expr_value): Likewise.
> 	(finish_trait_expr): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
> 	* g++.dg/ext/is_function.C: New test.

LGTM!

> 
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> ---
>  gcc/cp/constraint.cc                     |  3 ++
>  gcc/cp/cp-trait.def                      |  1 +
>  gcc/cp/semantics.cc                      |  4 ++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
>  gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
>  5 files changed, 69 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
> 
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index f6951ee2670..927605c6cb7 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
>      case CPTK_IS_UNION:
>        inform (loc, "  %qT is not a union", t1);
>        break;
> +    case CPTK_IS_FUNCTION:
> +      inform (loc, "  %qT is not a function", t1);
> +      break;
>      case CPTK_IS_AGGREGATE:
>        inform (loc, "  %qT is not an aggregate", t1);
>        break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 1e3310cd682..3cd3babc242 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> +DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 2f37bc353a1..b976633645a 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_ENUM:
>        return type_code1 == ENUMERAL_TYPE;
>  
> +    case CPTK_IS_FUNCTION:
> +      return type_code1 == FUNCTION_TYPE;
> +
>      case CPTK_IS_FINAL:
>        return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
>  
> @@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
>      case CPTK_IS_UNION:
>      case CPTK_IS_SAME:
>      case CPTK_IS_REFERENCE:
> +    case CPTK_IS_FUNCTION:
>        break;
>  
>      case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index b697673790c..90eb00ebf2d 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -149,3 +149,6 @@
>  #if !__has_builtin (__is_reference)
>  # error "__has_builtin (__is_reference) failed"
>  #endif
> +#if !__has_builtin (__is_function)
> +# error "__has_builtin (__is_function) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
> new file mode 100644
> index 00000000000..2e1594b12ad
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_function.C
> @@ -0,0 +1,58 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <testsuite_tr1.h>
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)	\
> +  SA(TRAIT(TYPE) == EXPECT);					\
> +  SA(TRAIT(const TYPE) == EXPECT);				\
> +  SA(TRAIT(volatile TYPE) == EXPECT);			\
> +  SA(TRAIT(const volatile TYPE) == EXPECT)
> +
> +struct A
> +{ void fn(); };
> +
> +template<typename>
> +struct AHolder { };
> +
> +template<class T, class U>
> +struct AHolder<U T::*>
> +{ using type = U; };
> +
> +// Positive tests.
> +SA(__is_function(int (int)));
> +SA(__is_function(ClassType (ClassType)));
> +SA(__is_function(float (int, float, int[], int&)));
> +SA(__is_function(int (int, ...)));
> +SA(__is_function(bool (ClassType) const));
> +SA(__is_function(AHolder<decltype(&A::fn)>::type));
> +
> +void fn();
> +SA(__is_function(decltype(fn)));
> +
> +// Negative tests.
> +SA_TEST_CATEGORY(__is_function, int, false);
> +SA_TEST_CATEGORY(__is_function, int*, false);
> +SA_TEST_CATEGORY(__is_function, int&, false);
> +SA_TEST_CATEGORY(__is_function, void, false);
> +SA_TEST_CATEGORY(__is_function, void*, false);
> +SA_TEST_CATEGORY(__is_function, void**, false);
> +SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
> +
> +SA_TEST_CATEGORY(__is_function, AbstractClass, false);
> +SA(!__is_function(int(&)(int)));
> +SA(!__is_function(int(*)(int)));
> +
> +SA_TEST_CATEGORY(__is_function, A, false);
> +SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
> +
> +struct FnCallOverload
> +{ void operator()(); };
> +SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
> +
> +// Sanity check.
> +SA_TEST_CATEGORY(__is_function, ClassType, false);
> +SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
> +SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
> -- 
> 2.41.0
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PING][PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits
  2023-07-13  2:33                       ` [PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits Ken Matsui
@ 2023-09-01 13:00                         ` Ken Matsui
  0 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-09-01 13:00 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches, libstdc++, Ken Matsui

Ping for std::is_object.

Sincerely,
Ken Matsui

On Wed, Jul 12, 2023 at 7:42 PM Ken Matsui <kmatsui@gcc.gnu.org> wrote:
>
> This patch gets std::is_object to dispatch to new built-in traits,
> __is_function and __is_reference.
>
> libstdc++-v3/ChangeLog:
>         * include/std/type_traits (is_object): Use new built-in traits,
>         __is_function and __is_reference.
>         (is_object_v): Likewise.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> ---
>  libstdc++-v3/include/std/type_traits | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> index 7ef50a2e64f..4ff025b09fa 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -682,11 +682,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      { };
>
>    /// is_object
> +#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
> +    && __has_builtin(__is_void)
> +  template<typename _Tp>
> +    struct is_object
> +    : public __bool_constant<!(__is_function(_Tp) || __is_reference(_Tp) ||
> +                             __is_void(_Tp))>
> +    { };
> +#else
>    template<typename _Tp>
>      struct is_object
>      : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
>                            is_void<_Tp>>>::type
>      { };
> +#endif
>
>    template<typename>
>      struct is_member_pointer;
> @@ -3233,8 +3242,16 @@ template <typename _Tp>
>    inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
>  template <typename _Tp>
>    inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> +
> +#if __has_builtin(__is_function) && __has_builtin(__is_reference)
> +template <typename _Tp>
> +  inline constexpr bool is_object_v
> +    = !(__is_function(_Tp) || __is_reference(_Tp) || is_void<_Tp>::value);
> +#else
>  template <typename _Tp>
>    inline constexpr bool is_object_v = is_object<_Tp>::value;
> +#endif
> +
>  template <typename _Tp>
>    inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
>  template <typename _Tp>
> --
> 2.41.0
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PING][PATCH v10 3/5] c++: Implement __is_function built-in trait
  2023-08-22 19:52                         ` Patrick Palka
@ 2023-09-04 15:00                           ` Ken Matsui
  0 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-09-04 15:00 UTC (permalink / raw)
  To: jason; +Cc: Ken Matsui, gcc-patches, libstdc++

Ping for __is_function built-in.

Sincerely,
Ken Matsui


On Tue, Aug 22, 2023 at 12:53 PM Patrick Palka <ppalka@redhat.com> wrote:
>
> On Wed, 12 Jul 2023, Ken Matsui via Libstdc++ wrote:
>
> > This patch implements built-in trait for std::is_function.
> >
> > gcc/cp/ChangeLog:
> >
> >       * cp-trait.def: Define __is_function.
> >       * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
> >       * semantics.cc (trait_expr_value): Likewise.
> >       (finish_trait_expr): Likewise.
> >
> > gcc/testsuite/ChangeLog:
> >
> >       * g++.dg/ext/has-builtin-1.C: Test existence of __is_function.
> >       * g++.dg/ext/is_function.C: New test.
>
> LGTM!
>
> >
> > Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> > ---
> >  gcc/cp/constraint.cc                     |  3 ++
> >  gcc/cp/cp-trait.def                      |  1 +
> >  gcc/cp/semantics.cc                      |  4 ++
> >  gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
> >  gcc/testsuite/g++.dg/ext/is_function.C   | 58 ++++++++++++++++++++++++
> >  5 files changed, 69 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C
> >
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index f6951ee2670..927605c6cb7 100644
> > --- a/gcc/cp/constraint.cc
> > +++ b/gcc/cp/constraint.cc
> > @@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
> >      case CPTK_IS_UNION:
> >        inform (loc, "  %qT is not a union", t1);
> >        break;
> > +    case CPTK_IS_FUNCTION:
> > +      inform (loc, "  %qT is not a function", t1);
> > +      break;
> >      case CPTK_IS_AGGREGATE:
> >        inform (loc, "  %qT is not an aggregate", t1);
> >        break;
> > diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> > index 1e3310cd682..3cd3babc242 100644
> > --- a/gcc/cp/cp-trait.def
> > +++ b/gcc/cp/cp-trait.def
> > @@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
> >  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
> >  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
> >  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> > +DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
> >  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
> >  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
> >  /* FIXME Added space to avoid direct usage in GCC 13.  */
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 2f37bc353a1..b976633645a 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -12072,6 +12072,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
> >      case CPTK_IS_ENUM:
> >        return type_code1 == ENUMERAL_TYPE;
> >
> > +    case CPTK_IS_FUNCTION:
> > +      return type_code1 == FUNCTION_TYPE;
> > +
> >      case CPTK_IS_FINAL:
> >        return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
> >
> > @@ -12293,6 +12296,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
> >      case CPTK_IS_UNION:
> >      case CPTK_IS_SAME:
> >      case CPTK_IS_REFERENCE:
> > +    case CPTK_IS_FUNCTION:
> >        break;
> >
> >      case CPTK_IS_LAYOUT_COMPATIBLE:
> > diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> > index b697673790c..90eb00ebf2d 100644
> > --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> > +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> > @@ -149,3 +149,6 @@
> >  #if !__has_builtin (__is_reference)
> >  # error "__has_builtin (__is_reference) failed"
> >  #endif
> > +#if !__has_builtin (__is_function)
> > +# error "__has_builtin (__is_function) failed"
> > +#endif
> > diff --git a/gcc/testsuite/g++.dg/ext/is_function.C b/gcc/testsuite/g++.dg/ext/is_function.C
> > new file mode 100644
> > index 00000000000..2e1594b12ad
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/ext/is_function.C
> > @@ -0,0 +1,58 @@
> > +// { dg-do compile { target c++11 } }
> > +
> > +#include <testsuite_tr1.h>
> > +
> > +using namespace __gnu_test;
> > +
> > +#define SA(X) static_assert((X),#X)
> > +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)        \
> > +  SA(TRAIT(TYPE) == EXPECT);                                 \
> > +  SA(TRAIT(const TYPE) == EXPECT);                           \
> > +  SA(TRAIT(volatile TYPE) == EXPECT);                        \
> > +  SA(TRAIT(const volatile TYPE) == EXPECT)
> > +
> > +struct A
> > +{ void fn(); };
> > +
> > +template<typename>
> > +struct AHolder { };
> > +
> > +template<class T, class U>
> > +struct AHolder<U T::*>
> > +{ using type = U; };
> > +
> > +// Positive tests.
> > +SA(__is_function(int (int)));
> > +SA(__is_function(ClassType (ClassType)));
> > +SA(__is_function(float (int, float, int[], int&)));
> > +SA(__is_function(int (int, ...)));
> > +SA(__is_function(bool (ClassType) const));
> > +SA(__is_function(AHolder<decltype(&A::fn)>::type));
> > +
> > +void fn();
> > +SA(__is_function(decltype(fn)));
> > +
> > +// Negative tests.
> > +SA_TEST_CATEGORY(__is_function, int, false);
> > +SA_TEST_CATEGORY(__is_function, int*, false);
> > +SA_TEST_CATEGORY(__is_function, int&, false);
> > +SA_TEST_CATEGORY(__is_function, void, false);
> > +SA_TEST_CATEGORY(__is_function, void*, false);
> > +SA_TEST_CATEGORY(__is_function, void**, false);
> > +SA_TEST_CATEGORY(__is_function, std::nullptr_t, false);
> > +
> > +SA_TEST_CATEGORY(__is_function, AbstractClass, false);
> > +SA(!__is_function(int(&)(int)));
> > +SA(!__is_function(int(*)(int)));
> > +
> > +SA_TEST_CATEGORY(__is_function, A, false);
> > +SA_TEST_CATEGORY(__is_function, decltype(&A::fn), false);
> > +
> > +struct FnCallOverload
> > +{ void operator()(); };
> > +SA_TEST_CATEGORY(__is_function, FnCallOverload, false);
> > +
> > +// Sanity check.
> > +SA_TEST_CATEGORY(__is_function, ClassType, false);
> > +SA_TEST_CATEGORY(__is_function, IncompleteClass, false);
> > +SA_TEST_CATEGORY(__is_function, IncompleteUnion, false);
> > --
> > 2.41.0
> >
> >
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PING][PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference
  2023-07-13  2:56                         ` Ken Matsui
@ 2023-09-04 15:00                           ` Ken Matsui
  0 siblings, 0 replies; 92+ messages in thread
From: Ken Matsui @ 2023-09-04 15:00 UTC (permalink / raw)
  To: jason; +Cc: gcc-patches, libstdc++, Ken Matsui

Ping for __is_reference built-in.

Sincerely,
Ken Matsui


On Wed, Jul 12, 2023 at 7:56 PM Ken Matsui <kmatsui@cs.washington.edu> wrote:
>
> Hi,
>
> Here is the benchmark result for is_reference:
>
> https://github.com/ken-matsui/gcc-benches/blob/main/is_reference.md#wed-jul-12-074702-pm-pdt-2023
>
> Time: -8.15593%
> Peak Memory Usage: -4.48408%
> Total Memory Usage: -8.03783%
>
> Sincerely,
> Ken Matsui
>
> On Wed, Jul 12, 2023 at 7:39 PM Ken Matsui <kmatsui@gcc.gnu.org> wrote:
> >
> > This patch gets std::is_reference to dispatch to new built-in trait
> > __is_reference.
> >
> > libstdc++-v3/ChangeLog:
> >
> >         * include/std/type_traits (is_reference): Use __is_reference built-in
> >         trait.
> >         (is_reference_v): Likewise.
> >
> > Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> > ---
> >  libstdc++-v3/include/std/type_traits | 14 ++++++++++++++
> >  1 file changed, 14 insertions(+)
> >
> > diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
> > index 0e7a9c9c7f3..2a14df7e5f9 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -639,6 +639,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >    // Composite type categories.
> >
> >    /// is_reference
> > +#if __has_builtin(__is_reference)
> > +  template<typename _Tp>
> > +    struct is_reference
> > +    : public __bool_constant<__is_reference(_Tp)>
> > +    { };
> > +#else
> >    template<typename _Tp>
> >      struct is_reference
> >      : public false_type
> > @@ -653,6 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >      struct is_reference<_Tp&&>
> >      : public true_type
> >      { };
> > +#endif
> >
> >    /// is_arithmetic
> >    template<typename _Tp>
> > @@ -3192,12 +3199,19 @@ template <typename _Tp>
> >    inline constexpr bool is_class_v = __is_class(_Tp);
> >  template <typename _Tp>
> >    inline constexpr bool is_function_v = is_function<_Tp>::value;
> > +
> > +#if __has_builtin(__is_reference)
> > +template <typename _Tp>
> > +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> > +#else
> >  template <typename _Tp>
> >    inline constexpr bool is_reference_v = false;
> >  template <typename _Tp>
> >    inline constexpr bool is_reference_v<_Tp&> = true;
> >  template <typename _Tp>
> >    inline constexpr bool is_reference_v<_Tp&&> = true;
> > +#endif
> > +
> >  template <typename _Tp>
> >    inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
> >  template <typename _Tp>
> > --
> > 2.41.0
> >

^ permalink raw reply	[flat|nested] 92+ messages in thread

end of thread, other threads:[~2023-09-04 15:01 UTC | newest]

Thread overview: 92+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-26  4:30 [PATCH 00/10] c++, libstdc++: get std::is_object to dispatch to new built-in traits Ken Matsui
2023-03-26  4:30 ` [PATCH 01/10] c++: implement __is_reference built-in trait Ken Matsui
2023-03-26  4:30 ` [PATCH 02/10] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-03-26  4:30 ` [PATCH 03/10] c++: implement __is_function built-in trait Ken Matsui
2023-03-26  4:30 ` [PATCH 04/10] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-03-26  4:30 ` [PATCH 05/10] libstdc++: use std::is_void instead of __is_void in helper_functions.h Ken Matsui
2023-03-26  4:30 ` [PATCH 06/10] libstdc++: remove unused __is_void in cpp_type_traits.h Ken Matsui
2023-03-26  4:30 ` [PATCH 07/10] c++: rename __is_void defined in pr46567.C to ____is_void Ken Matsui
2023-03-26  4:30 ` [PATCH 08/10] c++: implement __is_void built-in trait Ken Matsui
2023-03-26  4:30 ` [PATCH 09/10] libstdc++: use new built-in trait __is_void for std::is_void Ken Matsui
2023-03-26  4:30 ` [PATCH 10/10] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-03-30 18:32 ` [PATCH 0/7] c++, libstdc++: get std::is_object to " Ken Matsui
2023-03-30 18:39 ` [PATCH v2 " Ken Matsui
2023-03-30 18:39   ` [PATCH v2 1/7] c++: implement __is_reference built-in trait Ken Matsui
2023-03-30 18:39   ` [PATCH v2 2/7] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-03-30 18:39   ` [PATCH v2 3/7] c++: implement __is_function built-in trait Ken Matsui
2023-03-30 18:39   ` [PATCH v2 4/7] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-03-30 18:39   ` [PATCH v2 5/7] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-03-30 18:39   ` [PATCH v2 6/7] libstdc++: use new built-in trait __is_void for std::is_void Ken Matsui
2023-03-30 18:39   ` [PATCH v2 7/7] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-04-02  7:53   ` [PATCH v3 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
2023-04-02  7:53     ` [PATCH v3 1/6] c++: implement __is_reference built-in trait Ken Matsui
2023-04-02  7:53     ` [PATCH v3 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-04-02  7:53     ` [PATCH v3 3/6] c++: implement __is_function built-in trait Ken Matsui
2023-04-02  7:53     ` [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-06-09 17:54       ` Patrick Palka
2023-06-09 23:53         ` Ken Matsui
2023-04-02  7:53     ` [PATCH v3 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-04-02  7:53     ` [PATCH v3 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-06-11  2:43     ` [PATCH v4 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
2023-06-11  2:43       ` [PATCH v4 1/6] c++: implement __is_reference built-in trait Ken Matsui
2023-06-11  2:43       ` [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-06-12 18:09         ` François Dumont
2023-06-12 18:13           ` Ken Matsui
2023-06-11  2:43       ` [PATCH v4 3/6] c++: implement __is_function built-in trait Ken Matsui
2023-06-11  2:43       ` [PATCH v4 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-06-11  2:43       ` [PATCH v4 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-06-11  2:43       ` [PATCH v4 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-06-12 22:22       ` [PATCH v5 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
2023-06-12 22:22         ` [PATCH v5 1/6] c++: implement __is_reference built-in trait Ken Matsui
2023-06-12 22:22         ` [PATCH v5 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-06-12 22:22         ` [PATCH v5 3/6] c++: implement __is_function built-in trait Ken Matsui
2023-06-12 22:22         ` [PATCH v5 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-06-12 22:22         ` [PATCH v5 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-06-12 22:22         ` [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-06-14  5:10           ` François Dumont
2023-06-14  5:25             ` Ken Matsui
2023-06-12 22:39         ` [PATCH v6 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
2023-06-12 22:39           ` [PATCH v6 1/6] c++: implement __is_reference built-in trait Ken Matsui
2023-06-12 22:39           ` [PATCH v6 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-06-12 22:39           ` [PATCH v6 3/6] c++: implement __is_function built-in trait Ken Matsui
2023-06-12 22:39           ` [PATCH v6 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-06-12 22:39           ` [PATCH v6 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-06-12 22:39           ` [PATCH v6 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-06-12 22:47           ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
2023-06-12 22:47             ` [PATCH v7 1/6] c++: implement __is_reference built-in trait Ken Matsui
2023-06-20 16:06               ` Patrick Palka
2023-06-12 22:47             ` [PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-06-20 16:07               ` Patrick Palka
2023-06-12 22:47             ` [PATCH v7 3/6] c++: implement __is_function built-in trait Ken Matsui
2023-06-20 16:05               ` Patrick Palka
2023-06-12 22:47             ` [PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-06-20 16:05               ` Patrick Palka
2023-06-12 22:47             ` [PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-06-20 16:00               ` Patrick Palka
2023-06-12 22:47             ` [PATCH v7 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-06-15 10:49             ` [PATCH v7 0/6] c++, libstdc++: get std::is_object to " Ken Matsui
2023-06-20 13:19               ` Ken Matsui
2023-06-20 15:32               ` Patrick Palka
2023-06-24 15:12                 ` Ken Matsui
2023-07-08  5:08                   ` [PATCH v8 " Ken Matsui
2023-07-08  5:08                     ` [PATCH v8 1/6] c++: implement __is_reference built-in trait Ken Matsui
2023-07-08  5:08                     ` [PATCH v8 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-07-12 10:08                       ` Jonathan Wakely
2023-07-08  5:08                     ` [PATCH v8 3/6] c++: implement __is_function built-in trait Ken Matsui
2023-07-08  5:08                     ` [PATCH v8 4/6] libstdc++: use new built-in trait __is_function for std::is_function Ken Matsui
2023-07-12 10:10                       ` Jonathan Wakely
2023-07-08  5:08                     ` [PATCH v8 5/6] c++, libstdc++: implement __is_void built-in trait Ken Matsui
2023-07-08  5:08                     ` [PATCH v8 6/6] libstdc++: make std::is_object dispatch to new built-in traits Ken Matsui
2023-07-13  2:33                     ` [PATCH v10 0/5] c++, libstdc++: Make " Ken Matsui
2023-07-13  2:33                       ` [PATCH v10 1/5] c++: Implement __is_reference built-in trait Ken Matsui
2023-07-13  2:33                       ` [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference Ken Matsui
2023-07-13  2:56                         ` Ken Matsui
2023-09-04 15:00                           ` [PING][PATCH " Ken Matsui
2023-07-13  2:33                       ` [PATCH v10 3/5] c++: Implement __is_function built-in trait Ken Matsui
2023-07-13  2:41                         ` Ken Matsui
2023-08-22 19:52                         ` Patrick Palka
2023-09-04 15:00                           ` [PING][PATCH " Ken Matsui
2023-07-13  2:33                       ` [PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function Ken Matsui
2023-08-08 20:35                         ` Jonathan Wakely
2023-07-13  2:33                       ` [PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits Ken Matsui
2023-09-01 13:00                         ` [PING][PATCH " Ken Matsui

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).