Re: [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function

2023-06-09 Thread Ken Matsui via Gcc-patches
On Fri, Jun 9, 2023 at 10:54 AM Patrick Palka  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 
> > ---
> >  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
> > +struct is_function
> > +: public __bool_constant<__is_function(_Tp)>
> > +{ };
> > +#else
> >template
> >  struct is_function
> >  : public __bool_constant::value> { };
> > @@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >template
> >  struct is_function<_Tp&&>
> >  : public false_type { };
> > +#endif
> >
> >  #define __cpp_lib_is_null_pointer 201309L
> >
> > --
> > 2.40.0
> >
> >
>


[PATCH v4 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits

2023-06-10 Thread Ken Matsui via Gcc-patches
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_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

This would instantiate only __bool_constant and __bool_constant,
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



[PATCH v4 1/6] c++: implement __is_reference built-in trait

2023-06-10 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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



[PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference

2023-06-10 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_reference
+: public __bool_constant<__is_reference(_Tp)>
+{ };
+#else
   template
 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
@@ -3193,11 +3200,7 @@ template 
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
 template 
-  inline constexpr bool is_reference_v = false;
-template 
-  inline constexpr bool is_reference_v<_Tp&> = true;
-template 
-  inline constexpr bool is_reference_v<_Tp&&> = true;
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v4 3/6] c++: implement __is_function built-in trait

2023-06-10 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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
+struct AHolder { };
+
+template
+struct AHolder
+{ 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::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_

[PATCH v4 5/6] c++, libstdc++: implement __is_void built-in trait

2023-06-10 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_vo

[PATCH v4 4/6] libstdc++: use new built-in trait __is_function for std::is_function

2023-06-10 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_function
+: public __bool_constant<__is_function(_Tp)>
+{ };
+#else
   template
 struct is_function
 : public __bool_constant::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_function<_Tp&&>
 : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3198,7 +3205,7 @@ template 
 template 
   inline constexpr bool is_class_v = __is_class(_Tp);
 template 
-  inline constexpr bool is_function_v = is_function<_Tp>::value;
+  inline constexpr bool is_function_v = __is_function(_Tp);
 template 
   inline constexpr bool is_reference_v = __is_reference(_Tp);
 template 
-- 
2.41.0



[PATCH v4 6/6] libstdc++: make std::is_object dispatch to new built-in traits

2023-06-10 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_object
+: public __bool_constant
+{ };
+#else
   template
 struct is_object
 : public __not_<__or_, is_reference<_Tp>,
   is_void<_Tp>>>::type
 { };
+#endif
 
   template
 struct is_member_pointer;
-- 
2.41.0



Re: [PATCH v4 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
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 
> > ---
> >   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
> > +struct is_reference
> > +: public __bool_constant<__is_reference(_Tp)>
> > +{ };
> > +#else
> > template
> >   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
> > @@ -3193,11 +3200,7 @@ template 
> >   template 
> > inline constexpr bool is_function_v = is_function<_Tp>::value;
> >   template 
> > -  inline constexpr bool is_reference_v = false;
> > -template 
> > -  inline constexpr bool is_reference_v<_Tp&> = true;
> > -template 
> > -  inline constexpr bool is_reference_v<_Tp&&> = true;
> > +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> ...but not here, why ?
>
> --
Sincerely,
Ken Matsui


[PATCH v5 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits

2023-06-12 Thread Ken Matsui via Gcc-patches
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_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

This would instantiate only __bool_constant and __bool_constant,
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



[PATCH v5 1/6] c++: implement __is_reference built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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



[PATCH v5 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_reference
+: public __bool_constant<__is_reference(_Tp)>
+{ };
+#else
   template
 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
@@ -3192,12 +3199,19 @@ template 
   inline constexpr bool is_class_v = __is_class(_Tp);
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template 
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template 
   inline constexpr bool is_reference_v = false;
 template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v5 3/6] c++: implement __is_function built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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
+struct AHolder { };
+
+template
+struct AHolder
+{ 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::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_

[PATCH v5 4/6] libstdc++: use new built-in trait __is_function for std::is_function

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_function
+: public __bool_constant<__is_function(_Tp)>
+{ };
+#else
   template
 struct is_function
 : public __bool_constant::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_function<_Tp&&>
 : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template 
   inline constexpr bool is_union_v = __is_union(_Tp);
 template 
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template 
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template 
-- 
2.41.0



[PATCH v5 5/6] c++, libstdc++: implement __is_void built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_

[PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_object
+: public __bool_constant<__is_object(_Tp)>
+{ };
+#else
   template
 struct is_object
 : public __not_<__or_, is_reference<_Tp>,
   is_void<_Tp>>>::type
 { };
+#endif
 
   template
 struct is_member_pointer;
@@ -3235,8 +3247,15 @@ template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#ifdef __is_object
+template 
+  inline constexpr bool is_object_v = __is_object(_Tp);
+#else
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v6 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits

2023-06-12 Thread Ken Matsui via Gcc-patches
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_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

This would instantiate only __bool_constant and __bool_constant,
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



[PATCH v6 1/6] c++: implement __is_reference built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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



[PATCH v6 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_reference
+: public __bool_constant<__is_reference(_Tp)>
+{ };
+#else
   template
 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
@@ -3192,12 +3199,19 @@ template 
   inline constexpr bool is_class_v = __is_class(_Tp);
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template 
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template 
   inline constexpr bool is_reference_v = false;
 template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v6 4/6] libstdc++: use new built-in trait __is_function for std::is_function

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_function
+: public __bool_constant<__is_function(_Tp)>
+{ };
+#else
   template
 struct is_function
 : public __bool_constant::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_function<_Tp&&>
 : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template 
   inline constexpr bool is_union_v = __is_union(_Tp);
 template 
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template 
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template 
-- 
2.41.0



[PATCH v6 3/6] c++: implement __is_function built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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
+struct AHolder { };
+
+template
+struct AHolder
+{ 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::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_

[PATCH v6 6/6] libstdc++: make std::is_object dispatch to new built-in traits

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_object
+: public __bool_constant
+{ };
+#else
   template
 struct is_object
 : public __not_<__or_, is_reference<_Tp>,
   is_void<_Tp>>>::type
 { };
+#endif
 
   template
 struct is_member_pointer;
@@ -3235,8 +3245,17 @@ template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+&& __has_builtin(__is_void)
+template 
+  inline constexpr bool is_object_v
+= !(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp));
+#else
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v6 5/6] c++, libstdc++: implement __is_void built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_

[PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits

2023-06-12 Thread Ken Matsui via Gcc-patches
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_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

This would instantiate only __bool_constant and __bool_constant,
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



[PATCH v7 1/6] c++: implement __is_reference built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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



[PATCH v7 2/6] libstdc++: use new built-in trait __is_reference for std::is_reference

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_reference
+: public __bool_constant<__is_reference(_Tp)>
+{ };
+#else
   template
 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
@@ -3192,12 +3199,19 @@ template 
   inline constexpr bool is_class_v = __is_class(_Tp);
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template 
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template 
   inline constexpr bool is_reference_v = false;
 template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v7 3/6] c++: implement __is_function built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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
+struct AHolder { };
+
+template
+struct AHolder
+{ 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::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_

[PATCH v7 4/6] libstdc++: use new built-in trait __is_function for std::is_function

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_function
+: public __bool_constant<__is_function(_Tp)>
+{ };
+#else
   template
 struct is_function
 : public __bool_constant::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_function<_Tp&&>
 : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,14 @@ template 
   inline constexpr bool is_union_v = __is_union(_Tp);
 template 
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
+template 
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+#endif
 
 #if __has_builtin(__is_reference)
 template 
-- 
2.41.0



[PATCH v7 5/6] c++, libstdc++: implement __is_void built-in trait

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..707f0d6875b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_void.C
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_

[PATCH v7 6/6] libstdc++: make std::is_object dispatch to new built-in traits

2023-06-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_object
+: public __bool_constant
+{ };
+#else
   template
 struct is_object
 : public __not_<__or_, is_reference<_Tp>,
   is_void<_Tp>>>::type
 { };
+#endif
 
   template
 struct is_member_pointer;
@@ -3235,8 +3244,17 @@ template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference) \
+&& __has_builtin(__is_void)
+template 
+  inline constexpr bool is_object_v
+= !(__is_function(_Tp) || __is_reference(_Tp) || __is_void(_Tp));
+#else
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-- 
2.41.0



Re: [PATCH v5 6/6] libstdc++: make std::is_object dispatch to new built-in traits

2023-06-13 Thread Ken Matsui via Gcc-patches
On Tue, Jun 13, 2023 at 10:10 PM François Dumont  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 
> > ---
> >   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
 struct is_object
 : public __not_<__or_, 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
> > +struct is_object
> > +: public __bool_constant<__is_object(_Tp)>
> > +{ };
> > +#else
> > template
> >   struct is_object
> >   : public __not_<__or_, is_reference<_Tp>,
> > is_void<_Tp>>>::type
> >   { };
> > +#endif
> >
> > template
> >   struct is_member_pointer;
> > @@ -3235,8 +3247,15 @@ template 
> > inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
> >   template 
> > inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> > +
> > +#ifdef __is_object
> > +template 
> > +  inline constexpr bool is_object_v = __is_object(_Tp);
> > +#else
> >   template 
> > inline constexpr bool is_object_v = is_object<_Tp>::value;
> > +#endif
> > +
> >   template 
> > inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
> >   template 


Re: [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits

2023-06-15 Thread Ken Matsui via Gcc-patches
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  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_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_void(_Tp))>
>
> This would instantiate only __bool_constant and __bool_constant,
> 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
>


[PATCH 1/2] c++: implement __remove_pointer built-in trait

2023-06-15 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::remove_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __remove_pointer.
* semantics.cc (finish_trait_type): Handle CPTK_REMOVE_POINTER.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 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/remove_pointer.C | 51 +++
 4 files changed, 59 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/remove_pointer.C

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..07823e55579 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -90,6 +90,7 @@ DEFTRAIT_EXPR (IS_DEDUCIBLE, "__is_deducible ", 2)
 DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
 DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
 DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
+DEFTRAIT_TYPE (REMOVE_POINTER, "__remove_pointer", 1)
 DEFTRAIT_TYPE (UNDERLYING_TYPE,  "__underlying_type", 1)
 DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
 
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..885c7a6fb64 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12373,6 +12373,10 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
   if (TYPE_REF_P (type1))
type1 = TREE_TYPE (type1);
   return cv_unqualified (type1);
+case CPTK_REMOVE_POINTER:
+  if (TYPE_PTR_P (type1))
+type1 = TREE_TYPE (type1);
+  return type1;
 
 case CPTK_TYPE_PACK_ELEMENT:
   return finish_type_pack_element (type1, type2, complain);
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..e21e0a95509 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 (__remove_pointer)
+# error "__has_builtin (__remove_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/remove_pointer.C 
b/gcc/testsuite/g++.dg/ext/remove_pointer.C
new file mode 100644
index 000..7b13db93950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/remove_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(__is_same(__remove_pointer(int), int));
+SA(__is_same(__remove_pointer(int*), int));
+SA(__is_same(__remove_pointer(int**), int*));
+
+SA(__is_same(__remove_pointer(const int*), const int));
+SA(__is_same(__remove_pointer(const int**), const int*));
+SA(__is_same(__remove_pointer(int* const), int));
+SA(__is_same(__remove_pointer(int** const), int*));
+SA(__is_same(__remove_pointer(int* const* const), int* const));
+
+SA(__is_same(__remove_pointer(volatile int*), volatile int));
+SA(__is_same(__remove_pointer(volatile int**), volatile int*));
+SA(__is_same(__remove_pointer(int* volatile), int));
+SA(__is_same(__remove_pointer(int** volatile), int*));
+SA(__is_same(__remove_pointer(int* volatile* volatile), int* volatile));
+
+SA(__is_same(__remove_pointer(const volatile int*), const volatile int));
+SA(__is_same(__remove_pointer(const volatile int**), const volatile int*));
+SA(__is_same(__remove_pointer(const int* volatile), const int));
+SA(__is_same(__remove_pointer(volatile int* const), volatile int));
+SA(__is_same(__remove_pointer(int* const volatile), int));
+SA(__is_same(__remove_pointer(const int** volatile), const int*));
+SA(__is_same(__remove_pointer(volatile int** const), volatile int*));
+SA(__is_same(__remove_pointer(int** const volatile), int*));
+SA(__is_same(__remove_pointer(int* const* const volatile), int* const));
+SA(__is_same(__remove_pointer(int* volatile* const volatile), int* volatile));
+SA(__is_same(__remove_pointer(int* const volatile* const volatile), int* const 
volatile));
+
+SA(__is_same(__remove_pointer(int&), int&));
+SA(__is_same(__remove_pointer(const int&), const int&));
+SA(__is_same(__remove_pointer(volatile int&), volatile int&));
+SA(__is_same(__remove_pointer(const volatile int&), const volatile int&));
+
+SA(__is_same(__remove_pointer(int&&), int&&));
+SA(__is_same(__remove_pointer(const int&&), const int&&));
+SA(__is_same(__remove_pointer(volatile int&&), volatile int&&));
+SA(__is_same(__remove_pointer(const volatile int&&), const volatile int&&));
+
+SA(__is_same(__remove_pointer(int[3]), int[3]));
+SA(__is_same(__remove_pointer(const int[3]), const int[3]));
+SA(__is_same(__remove_pointer(volatile int[3]), volatile int[3]));
+SA(__is_same(__remove_pointer(const volatile int[3]), const volatile int[3]));
+
+SA(__is_same(__remove_pointer(int(int)), int(int)));
+SA(__is_same(__remove_pointer(int(*const)(int)), int(int)));
+SA(__is_same(__remove_po

[PATCH 2/2] libstdc++: use new built-in trait __remove_pointer

2023-06-15 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __remove_pointer.

libstdc++-v3/ChangeLog:

* include/std/type_traits (remove_pointer): Use __remove_pointer 
built-in trait.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..81497e2f3e1 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2023,6 +2023,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Pointer modifications.
 
+  /// remove_pointer
+#if __has_builtin(__remove_pointer)
+  template
+struct remove_pointer
+{ using type = __remove_pointer(_Tp); };
+#else
   template
 struct __remove_pointer_helper
 { using type = _Tp; };
@@ -2031,11 +2037,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __remove_pointer_helper<_Tp, _Up*>
 { using type = _Up; };
 
-  /// remove_pointer
   template
 struct remove_pointer
 : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>>
 { };
+#endif
 
   template
 struct __add_pointer_helper
-- 
2.41.0



Re: [PATCH v2 2/2] libstdc++: use new built-in trait __is_scalar for std::is_scalar

2023-07-12 Thread Ken Matsui via Gcc-patches
On Wed, Jul 12, 2023 at 2:50 AM Jonathan Wakely  wrote:
>
> On Sat, 8 Jul 2023 at 05:47, Ken Matsui via Libstdc++
>  wrote:
> >
> > This patch gets std::is_scalar to dispatch to new built-in trait
> > __is_scalar.
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/std/type_traits (is_scalar): Use __is_scalar built-in
> > trait.
> > (is_scalar_v): Likewise.
>
> OK for trunk (conditional on the front-end change being committed
> first of course).
>

Thank you for your review!

Just to confirm, this approval does not include the [1/2] patch, does
it? Or, did you approve this entire patch series?

> conditional on the front-end change being committed first of course

Does this mean we want to commit this [2/2] patch before committing
the [1/2] patch in this case?

Also, can I tweak the commit message without being approved again,
such as attaching the benchmark result?

> >
> > Signed-off-by: Ken Matsui 
> > ---
> >  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..bc90b2c61ca 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -678,11 +678,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >  struct is_member_pointer;
> >
> >/// is_scalar
> > +#if __has_builtin(__is_scalar)
> > +  template
> > +struct is_scalar
> > +: public __bool_constant<__is_scalar(_Tp)>
> > +{ };
> > +#else
> >template
> >  struct is_scalar
> >  : public __or_, is_enum<_Tp>, is_pointer<_Tp>,
> > is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type
> >  { };
> > +#endif
> >
> >/// is_compound
> >template
> > @@ -3204,8 +3211,15 @@ template 
> >inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> >  template 
> >inline constexpr bool is_object_v = is_object<_Tp>::value;
> > +
> > +#if __has_builtin(__is_scalar)
> > +template 
> > +  inline constexpr bool is_scalar_v = __is_scalar(_Tp);
> > +#else
> >  template 
> >inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
> > +#endif
> > +
> >  template 
> >inline constexpr bool is_compound_v = is_compound<_Tp>::value;
> >  template 
> > --
> > 2.41.0
> >
>


Re: [PATCH v2 2/2] libstdc++: use new built-in trait __is_scalar for std::is_scalar

2023-07-12 Thread Ken Matsui via Gcc-patches
On Wed, Jul 12, 2023 at 11:56 AM Xi Ruoyao  wrote:
>
> On Wed, 2023-07-12 at 11:32 -0700, Ken Matsui via Gcc-patches wrote:
> > > conditional on the front-end change being committed first of course
> >
> > Does this mean we want to commit this [2/2] patch before committing
> > the [1/2] patch in this case?
>
> No, this mean you should get 1/2 reviewed and committed first.
>
> > Also, can I tweak the commit message without being approved again,
> > such as attaching the benchmark result?
>
> Yes, as long as the ChangeLog is still correct (the Git hook will reject
> a push with wrong ChangeLog format anyway).

I see. Thank you so much!

> --
> Xi Ruoyao 
> School of Aerospace Science and Technology, Xidian University


Re: [PATCH v2 2/2] libstdc++: use new built-in trait __is_scalar for std::is_scalar

2023-07-12 Thread Ken Matsui via Gcc-patches
On Wed, Jul 12, 2023 at 12:23 PM Jonathan Wakely  wrote:
>
>
>
> On Wed, 12 Jul 2023, 19:33 Ken Matsui via Libstdc++,  
> wrote:
>>
>> On Wed, Jul 12, 2023 at 2:50 AM Jonathan Wakely  wrote:
>> >
>> > On Sat, 8 Jul 2023 at 05:47, Ken Matsui via Libstdc++
>> >  wrote:
>> > >
>> > > This patch gets std::is_scalar to dispatch to new built-in trait
>> > > __is_scalar.
>> > >
>> > > libstdc++-v3/ChangeLog:
>> > >
>> > > * include/std/type_traits (is_scalar): Use __is_scalar built-in
>> > > trait.
>> > > (is_scalar_v): Likewise.
>> >
>> > OK for trunk (conditional on the front-end change being committed
>> > first of course).
>> >
>>
>> Thank you for your review!
>>
>> Just to confirm, this approval does not include the [1/2] patch, does
>> it? Or, did you approve this entire patch series?
>
>
> Only this patch. I cannot approve compiler changes, I'm only a reviewer for 
> libstdc++.
>
>
>>
>> > conditional on the front-end change being committed first of course
>>
>> Does this mean we want to commit this [2/2] patch before committing
>> the [1/2] patch in this case?
>
>
> The other way around, as Xi Ruoyao said.
>
>
>>
>> Also, can I tweak the commit message without being approved again,
>> such as attaching the benchmark result?
>
>
> Yes, that's fine.

Thank you!

>>
>> > >
>> > > Signed-off-by: Ken Matsui 
>> > > ---
>> > >  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..bc90b2c61ca 100644
>> > > --- a/libstdc++-v3/include/std/type_traits
>> > > +++ b/libstdc++-v3/include/std/type_traits
>> > > @@ -678,11 +678,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> > >  struct is_member_pointer;
>> > >
>> > >/// is_scalar
>> > > +#if __has_builtin(__is_scalar)
>> > > +  template
>> > > +struct is_scalar
>> > > +: public __bool_constant<__is_scalar(_Tp)>
>> > > +{ };
>> > > +#else
>> > >template
>> > >  struct is_scalar
>> > >  : public __or_, is_enum<_Tp>, is_pointer<_Tp>,
>> > > is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type
>> > >  { };
>> > > +#endif
>> > >
>> > >/// is_compound
>> > >template
>> > > @@ -3204,8 +3211,15 @@ template 
>> > >inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
>> > >  template 
>> > >inline constexpr bool is_object_v = is_object<_Tp>::value;
>> > > +
>> > > +#if __has_builtin(__is_scalar)
>> > > +template 
>> > > +  inline constexpr bool is_scalar_v = __is_scalar(_Tp);
>> > > +#else
>> > >  template 
>> > >inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
>> > > +#endif
>> > > +
>> > >  template 
>> > >inline constexpr bool is_compound_v = is_compound<_Tp>::value;
>> > >  template 
>> > > --
>> > > 2.41.0
>> > >
>> >


Re: [PATCH v2 1/2] c++, libstdc++: implement __is_pointer built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
On Wed, Jul 12, 2023 at 3:01 AM Jonathan Wakely  wrote:
>
> On Mon, 10 Jul 2023 at 06:51, Ken Matsui via Libstdc++
>  wrote:
> >
> > Hi,
> >
> > Here is the benchmark result for is_pointer:
> >
> > https://github.com/ken-matsui/gcc-benches/blob/main/is_pointer.md#sun-jul--9-103948-pm-pdt-2023
> >
> > Time: -62.1344%
> > Peak Memory Usage: -52.4281%
> > Total Memory Usage: -53.5889%
>
> Wow!
>
> Although maybe we could have improved our std::is_pointer_v anyway, like so:
>
> template 
>   inline constexpr bool is_pointer_v = false;
> template 
>   inline constexpr bool is_pointer_v<_Tp*> = true;
> template 
>   inline constexpr bool is_pointer_v<_Tp* const> = true;
> template 
>   inline constexpr bool is_pointer_v<_Tp* volatile> = true;
> template 
>   inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
>
> I'm not sure why I didn't already do that.
>
> Could you please benchmark that? And if it is better than the current
> impl using is_pointer<_Tp>::value then we should do this in the
> library:
>
> #if __has_builtin(__is_pointer)
> template 
>   inline constexpr bool is_pointer_v = __is_pointer(_Tp);
> #else
> template 
>   inline constexpr bool is_pointer_v = false;
> template 
>   inline constexpr bool is_pointer_v<_Tp*> = true;
> template 
>   inline constexpr bool is_pointer_v<_Tp* const> = true;
> template 
>   inline constexpr bool is_pointer_v<_Tp* volatile> = true;
> template 
>   inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
> #endif

Hi François and Jonathan,

Thank you for your reviews! I will rename the four underscores to the
appropriate name and take a benchmark once I get home.

If I apply your change on is_pointer_v, is it better to add the
`Co-authored-by:` line in the commit?


[PATCH v3 1/2] c++, libstdc++: Implement __is_pointer built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
* g++.dg/ext/is_pointer.C: New test.
* g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
(__is_ptr): ... this.
* g++.dg/torture/20070621-1.C: Likewise.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
(__is_ptr): ... this.
* include/bits/deque.tcc: Use __is_ptr instead.
* include/bits/stl_algobase.h: Likewise.

Signed-off-by: Ken Matsui 
---
 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_pointer.C   | 51 +
 gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
 gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
 libstdc++-v3/include/bits/deque.tcc |  6 +--
 libstdc++-v3/include/bits/stl_algobase.h|  6 +--
 11 files changed, 86 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..30266204eb5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", 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 8b7fece0cc8..b7c263e9a77 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_POINTER, "__is_pointer", 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 8fb47fd179e..68f8a4fe85b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_POINTER:
+  return TYPE_PTR_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_POINTER:
   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..9dace5cbd48 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_pointer)
+# error "__has_builtin (__is_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
b/gcc/testsuite/g++.dg/ext/is_pointer.C
new file mode 100644
index 000..d6e39565950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_pointer(int));
+SA(__is_pointer(int*));
+SA(__is_pointer(int**));
+
+SA(__is_pointer(const int*));
+SA(__is_pointer(const int**));
+SA(__is_pointer(int* const));
+SA(__is_pointer(int** const));
+SA(__is_pointer(int* const* const));
+
+SA(__is_pointer(volatile int*));
+SA(__is_pointer(volatile int**));
+SA(__is_pointer(int* volatile));
+SA(__is_pointer(int** volatile));
+SA(__is_pointer(int* volatile* volatile));
+
+SA(__is_pointer(const volatile int*));
+SA(__is_pointer(const volatile int**));
+SA(__is_pointer(const int* volatile));
+SA(__is_pointer(volatile int* const));
+SA(__is_pointer(int* const volatile));
+SA(__is_pointer(const int** volatile));
+SA(__is_pointer(volatile int** const));
+SA(__is_pointer(int** const volatile));
+SA(__

Re: [PATCH v3 1/2] c++, libstdc++: Implement __is_pointer built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
Hi,

Here is the updated benchmark result for is_pointer:

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

Time: -2.79488%
Peak Memory Usage: -2.39379%
Total Memory Usage: -3.39559%

Sincerely,
Ken Matsui

On Wed, Jul 12, 2023 at 6:12 PM Ken Matsui  wrote:
>
> This patch implements built-in trait for std::is_pointer.
>
> gcc/cp/ChangeLog:
>
> * cp-trait.def: Define __is_pointer.
> * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_POINTER.
> * semantics.cc (trait_expr_value): Likewise.
> (finish_trait_expr): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
> * g++.dg/ext/is_pointer.C: New test.
> * g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
> (__is_ptr): ... this.
> * g++.dg/torture/20070621-1.C: Likewise.
> * g++.dg/torture/pr57107.C: Likewise.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
> (__is_ptr): ... this.
> * include/bits/deque.tcc: Use __is_ptr instead.
> * include/bits/stl_algobase.h: Likewise.
>
> Signed-off-by: Ken Matsui 
> ---
>  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_pointer.C   | 51 +
>  gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
>  gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
>  gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
>  libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
>  libstdc++-v3/include/bits/deque.tcc |  6 +--
>  libstdc++-v3/include/bits/stl_algobase.h|  6 +--
>  11 files changed, 86 insertions(+), 24 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 8cf0f2d0974..30266204eb5 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
>  case CPTK_IS_UNION:
>inform (loc, "  %qT is not a union", t1);
>break;
> +case CPTK_IS_POINTER:
> +  inform (loc, "  %qT is not a pointer", 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 8b7fece0cc8..b7c263e9a77 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -82,6 +82,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_POINTER, "__is_pointer", 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 8fb47fd179e..68f8a4fe85b 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> tree type2)
>  case CPTK_IS_UNION:
>return type_code1 == UNION_TYPE;
>
> +case CPTK_IS_POINTER:
> +  return TYPE_PTR_P (type1);
> +
>  case CPTK_IS_ASSIGNABLE:
>return is_xible (MODIFY_EXPR, type1, type2);
>
> @@ -12296,6 +12299,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_POINTER:
>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..9dace5cbd48 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_pointer)
> +# error "__has_builtin (__is_pointer) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
> b/gcc/testsuite/g++.dg/ext/is_pointer.C
> new file mode 100644
> index 000..d6e39565950
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
> @@ -0,0 +1,51 @@
> +// { dg-do compile { target c++11 } }
> +
> +#define SA(X) static_assert((X),#X)
> +
> +SA(!__is_pointer(int));
> +SA(__is_pointer(int*));
> +SA(__is_pointer(int**));
> +
> +SA(__is_pointer(const int*));
> +SA(__is_pointer(const int**));
> +SA(__is_pointer(int* const));
> +SA(__is_pointer(int** const));
> +SA(_

[PATCH v3 2/2] libstdc++: Use new built-in trait __is_pointer

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_pointer.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_ptr): Use __is_pointer
built-in trait.
* include/std/type_traits (is_pointer): Likewise.
(is_pointer_v): Likewise. Optimize its implementation.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/cpp_type_traits.h |  8 +++
 libstdc++-v3/include/std/type_traits| 25 +++--
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index 3711e4be526..4da1e7c407c 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -363,6 +363,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   //
   // Pointer types
   //
+#if __has_builtin(__is_pointer)
+  template
+struct __is_ptr : __truth_type<__is_pointer(_Tp)>
+{
+  enum { __value = __is_pointer(_Tp) };
+};
+#else
   template
 struct __is_ptr
 {
@@ -376,6 +383,7 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   enum { __value = 1 };
   typedef __true_type __type;
 };
+#endif
 
   //
   // An arithmetic type is an integer type or a floating point type
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..181a50e48d0 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -515,6 +515,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_array<_Tp[]>
 : public true_type { };
 
+  /// is_pointer
+#if __has_builtin(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
   template
 struct __is_pointer_helper
 : public false_type { };
@@ -523,11 +530,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __is_pointer_helper<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
 struct is_pointer
 : public __is_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
+#endif
 
   /// is_lvalue_reference
   template
@@ -3168,8 +3175,22 @@ template 
 template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
 
+#if __has_builtin(__is_pointer)
 template 
-  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+  inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+#else
+template 
+  inline constexpr bool is_pointer_v = false;
+template 
+  inline constexpr bool is_pointer_v<_Tp*> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* volatile> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
+#endif
+
 template 
   inline constexpr bool is_lvalue_reference_v = false;
 template 
-- 
2.41.0



Re: [PATCH v3 1/2] c++, libstdc++: Implement __is_pointer built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
Also, here is the Kanban board for our GSoC project, which might be
useful for you to manage non-reviewed patches.

https://github.com/users/ken-matsui/projects/1/views/1

On Wed, Jul 12, 2023 at 6:13 PM Ken Matsui  wrote:
>
> Hi,
>
> Here is the updated benchmark result for is_pointer:
>
> https://github.com/ken-matsui/gcc-benches/blob/main/is_pointer.md#wed-jul-12-055654-pm-pdt-2023
>
> Time: -2.79488%
> Peak Memory Usage: -2.39379%
> Total Memory Usage: -3.39559%
>
> Sincerely,
> Ken Matsui
>
> On Wed, Jul 12, 2023 at 6:12 PM Ken Matsui  wrote:
> >
> > This patch implements built-in trait for std::is_pointer.
> >
> > gcc/cp/ChangeLog:
> >
> > * cp-trait.def: Define __is_pointer.
> > * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_POINTER.
> > * semantics.cc (trait_expr_value): Likewise.
> > (finish_trait_expr): Likewise.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
> > * g++.dg/ext/is_pointer.C: New test.
> > * g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
> > (__is_ptr): ... this.
> > * g++.dg/torture/20070621-1.C: Likewise.
> > * g++.dg/torture/pr57107.C: Likewise.
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
> > (__is_ptr): ... this.
> > * include/bits/deque.tcc: Use __is_ptr instead.
> > * include/bits/stl_algobase.h: Likewise.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >  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_pointer.C   | 51 +
> >  gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
> >  gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
> >  gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
> >  libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
> >  libstdc++-v3/include/bits/deque.tcc |  6 +--
> >  libstdc++-v3/include/bits/stl_algobase.h|  6 +--
> >  11 files changed, 86 insertions(+), 24 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C
> >
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index 8cf0f2d0974..30266204eb5 100644
> > --- a/gcc/cp/constraint.cc
> > +++ b/gcc/cp/constraint.cc
> > @@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
> >  case CPTK_IS_UNION:
> >inform (loc, "  %qT is not a union", t1);
> >break;
> > +case CPTK_IS_POINTER:
> > +  inform (loc, "  %qT is not a pointer", 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 8b7fece0cc8..b7c263e9a77 100644
> > --- a/gcc/cp/cp-trait.def
> > +++ b/gcc/cp/cp-trait.def
> > @@ -82,6 +82,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_POINTER, "__is_pointer", 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 8fb47fd179e..68f8a4fe85b 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> > tree type2)
> >  case CPTK_IS_UNION:
> >return type_code1 == UNION_TYPE;
> >
> > +case CPTK_IS_POINTER:
> > +  return TYPE_PTR_P (type1);
> > +
> >  case CPTK_IS_ASSIGNABLE:
> >return is_xible (MODIFY_EXPR, type1, type2);
> >
> > @@ -12296,6 +12299,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_POINTER:
> >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..9dace5cbd48 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_pointer)
> > +# error "__has_builtin (__is_pointer) failed"
> > +#endif
> > diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
> > b/gcc/testsuite/g++.dg/e

Re: [PATCH 1/2] c++, libstdc++: implement __is_signed built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
On Wed, Jul 12, 2023 at 3:20 AM Jonathan Wakely  wrote:
>
> On Sun, 9 Jul 2023 at 09:50, Ken Matsui via Libstdc++
>  wrote:
> >
> > This patch implements built-in trait for std::is_signed.
> >
> > gcc/cp/ChangeLog:
> >
> > * cp-trait.def: Define __is_signed.
> > * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_SIGNED.
> > * semantics.cc (trait_expr_value): Likewise.
> > (finish_trait_expr): Likewise.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/ext/has-builtin-1.C: Test existence of __is_signed.
> > * g++.dg/ext/is_signed.C: New test.
> > * g++.dg/tm/pr46567.C (__is_signed): Rename to ...
> > (is_signed): ... this.
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/ext/numeric_traits.h (__is_signed): Rename to ...
> > (is_signed): ... this.
>
> Again, please do not use four underscores.
>
> This data member of __numeric_traits_integer could be __signed or
> __is_signed_integer. I think I prefer __signed here, since the
> "integer" part is redundant with __numeric_traits_integer.
>

Thank you for your review. It appears that __signed is a keyword. I
will choose __is_signed_type since we also have __is_signed for
__numeric_traits_floating.

>
>
> > * include/bits/charconv.h: Use is_signed instead.
> > * include/bits/locale_facets.tcc: Likewise.
> > * include/bits/uniform_int_dist.h: Likewise.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >  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_signed.C | 47 
> >  gcc/testsuite/g++.dg/tm/pr46567.C| 12 ++---
> >  libstdc++-v3/include/bits/charconv.h |  2 +-
> >  libstdc++-v3/include/bits/locale_facets.tcc  |  6 +--
> >  libstdc++-v3/include/bits/uniform_int_dist.h |  4 +-
> >  libstdc++-v3/include/ext/numeric_traits.h| 18 
> >  10 files changed, 79 insertions(+), 21 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/ext/is_signed.C
> >
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index 8cf0f2d0974..73fcbfe39e8 100644
> > --- a/gcc/cp/constraint.cc
> > +++ b/gcc/cp/constraint.cc
> > @@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
> >  case CPTK_IS_UNION:
> >inform (loc, "  %qT is not a union", t1);
> >break;
> > +case CPTK_IS_SIGNED:
> > +  inform (loc, "  %qT is not a signed 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 8b7fece0cc8..576d5528d05 100644
> > --- a/gcc/cp/cp-trait.def
> > +++ b/gcc/cp/cp-trait.def
> > @@ -82,6 +82,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_SIGNED, "__is_signed", 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 8fb47fd179e..17aad992f96 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> > tree type2)
> >  case CPTK_IS_UNION:
> >return type_code1 == UNION_TYPE;
> >
> > +case CPTK_IS_SIGNED:
> > +  return ARITHMETIC_TYPE_P (type1) && TYPE_SIGN (type1) == SIGNED;
> > +
> >  case CPTK_IS_ASSIGNABLE:
> >return is_xible (MODIFY_EXPR, type1, type2);
> >
> > @@ -12296,6 +12299,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_SIGNED:
> >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..a43202d0d59 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_signed)
> > +# error "__has_builtin (__is_signed) failed"
> > +#endif
> > diff --git a/gcc/testsuite/g++.dg/ext/is_signed.C 
> > b/gcc/testsuite/g++.dg/ext/is_signed.C
> > new file mode 100644
> > index 000..a04b5481

[PATCH v2 1/2] c++, libstdc++: Implement __is_signed built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_signed.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

libstdc++-v3/ChangeLog:

* include/ext/numeric_traits.h (__is_signed): Rename to ...
(__is_signed_type): ... this.
* include/bits/charconv.h: Use __is_signed_type instead.
* include/bits/locale_facets.tcc: Likewise.
* include/bits/uniform_int_dist.h: Likewise.

Signed-off-by: Ken Matsui 
---
 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_signed.C | 47 
 gcc/testsuite/g++.dg/tm/pr46567.C| 12 ++---
 libstdc++-v3/include/bits/charconv.h |  2 +-
 libstdc++-v3/include/bits/locale_facets.tcc  |  6 +--
 libstdc++-v3/include/bits/uniform_int_dist.h |  4 +-
 libstdc++-v3/include/ext/numeric_traits.h| 18 
 10 files changed, 79 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_signed.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..73fcbfe39e8 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_SIGNED:
+  inform (loc, "  %qT is not a signed 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 8b7fece0cc8..576d5528d05 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_SIGNED, "__is_signed", 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 8fb47fd179e..17aad992f96 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_SIGNED:
+  return ARITHMETIC_TYPE_P (type1) && TYPE_SIGN (type1) == SIGNED;
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_SIGNED:
   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..a43202d0d59 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_signed)
+# error "__has_builtin (__is_signed) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_signed.C 
b/gcc/testsuite/g++.dg/ext/is_signed.C
new file mode 100644
index 000..a04b548105d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_signed.C
@@ -0,0 +1,47 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, X, expect) \
+  SA(TRAIT(X) == expect);  \
+  SA(TRAIT(const X) == expect);\
+  SA(TRAIT(volatile X) == expect); \
+  SA(TRAIT(const volatile X) == expect)
+
+SA_TEST_CATEGORY(__is_signed, void, false);
+
+SA_TEST_CATEGORY(__is_signed, bool, bool(-1) < bool(0));
+SA_TEST_CATEGORY(__is_signed, char, char(-1) < char(0));
+SA_TEST_CATEGORY(__is_signed, signed char, true);
+SA_TEST_CATEGORY(__is_signed, unsigned char, false);
+SA_TEST_CATEGORY(__is_signed, wchar_t, wchar_t(-1) < wchar_t(0));
+SA_TEST_CATEGORY(__is_signed, short, true);
+SA_TEST_CATEGORY(__is_signed, unsigned short, false);
+SA_TEST_CATEGORY(__is_signed, int, true);
+SA_TEST_CATEGORY(__is_signed, unsigned int, fa

[PATCH v2 2/2] libstdc++: Use new built-in trait __is_signed

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_signed.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_signed): Use __is_signed built-in trait.
(is_signed_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..23ab5a4b1e5 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -865,6 +865,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __bool_constant<__is_abstract(_Tp)>
 { };
 
+  /// is_signed
+#if __has_builtin(__is_signed)
+  template
+struct is_signed
+: public __bool_constant<__is_signed(_Tp)>
+{ };
+#else
   /// @cond undocumented
   template::value>
@@ -877,11 +884,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
   /// @endcond
 
-  /// is_signed
   template
 struct is_signed
 : public __is_signed_helper<_Tp>::type
 { };
+#endif
 
   /// is_unsigned
   template
@@ -3240,8 +3247,14 @@ template 
 template 
   inline constexpr bool is_final_v = __is_final(_Tp);
 
+#if __has_builtin(__is_signed)
+template 
+  inline constexpr bool is_signed_v = __is_signed(_Tp);
+#else
 template 
   inline constexpr bool is_signed_v = is_signed<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
 
-- 
2.41.0



[PATCH v10 0/5] c++, libstdc++: Make std::is_object dispatch to new built-in traits

2023-07-12 Thread Ken Matsui via Gcc-patches
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_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::value)>

This would instantiate only __bool_constant and __bool_constant,
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



[PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference

2023-07-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_reference
+: public __bool_constant<__is_reference(_Tp)>
+{ };
+#else
   template
 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
@@ -3192,12 +3199,19 @@ template 
   inline constexpr bool is_class_v = __is_class(_Tp);
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if __has_builtin(__is_reference)
+template 
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template 
   inline constexpr bool is_reference_v = false;
 template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v10 1/5] c++: Implement __is_reference built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..b5ce4db7afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_reference.C
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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



[PATCH v10 3/5] c++: Implement __is_function built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
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 
---
 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 000..2e1594b12ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_function.C
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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
+struct AHolder { };
+
+template
+struct AHolder
+{ 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::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_

[PATCH v10 4/5] libstdc++: Use new built-in trait __is_function for std::is_function

2023-07-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_function
+: public __bool_constant<__is_function(_Tp)>
+{ };
+#else
   template
 struct is_function
 : public __bool_constant::value> { };
@@ -605,6 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_function<_Tp&&>
 : public false_type { };
+#endif
 
 #define __cpp_lib_is_null_pointer 201309L
 
@@ -3197,8 +3204,18 @@ template 
   inline constexpr bool is_union_v = __is_union(_Tp);
 template 
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if __has_builtin(__is_function)
 template 
-  inline constexpr bool is_function_v = is_function<_Tp>::value;
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
+template 
+  inline constexpr bool is_function_v = !is_const_v;
+template 
+  inline constexpr bool is_function_v<_Tp&> = false;
+template 
+  inline constexpr bool is_function_v<_Tp&&> = false;
+#endif
 
 #if __has_builtin(__is_reference)
 template 
-- 
2.41.0



Re: [PATCH v10 3/5] c++: Implement __is_function built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
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  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 
> ---
>  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 000..2e1594b12ad
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_function.C
> @@ -0,0 +1,58 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include 
> +
> +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
> +struct AHolder { };
> +
> +template
> +struct AHolder
> +{ 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::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(__

[PATCH v10 5/5] libstdc++: Make std::is_object dispatch to new built-in traits

2023-07-12 Thread Ken Matsui via Gcc-patches
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 
---
 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
+struct is_object
+: public __bool_constant
+{ };
+#else
   template
 struct is_object
 : public __not_<__or_, is_reference<_Tp>,
   is_void<_Tp>>>::type
 { };
+#endif
 
   template
 struct is_member_pointer;
@@ -3233,8 +3242,16 @@ template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if __has_builtin(__is_function) && __has_builtin(__is_reference)
+template 
+  inline constexpr bool is_object_v
+= !(__is_function(_Tp) || __is_reference(_Tp) || is_void<_Tp>::value);
+#else
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-- 
2.41.0



Re: [PATCH v10 2/5] libstdc++: Use new built-in trait __is_reference for std::is_reference

2023-07-12 Thread Ken Matsui via Gcc-patches
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  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 
> ---
>  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
> +struct is_reference
> +: public __bool_constant<__is_reference(_Tp)>
> +{ };
> +#else
>template
>  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
> @@ -3192,12 +3199,19 @@ template 
>inline constexpr bool is_class_v = __is_class(_Tp);
>  template 
>inline constexpr bool is_function_v = is_function<_Tp>::value;
> +
> +#if __has_builtin(__is_reference)
> +template 
> +  inline constexpr bool is_reference_v = __is_reference(_Tp);
> +#else
>  template 
>inline constexpr bool is_reference_v = false;
>  template 
>inline constexpr bool is_reference_v<_Tp&> = true;
>  template 
>inline constexpr bool is_reference_v<_Tp&&> = true;
> +#endif
> +
>  template 
>inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
>  template 
> --
> 2.41.0
>


[PATCH v4 1/2] c++, libstdc++: Implement __is_pointer built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
* g++.dg/ext/is_pointer.C: New test.
* g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
(__is_ptr): ... this.
* g++.dg/torture/20070621-1.C: Likewise.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
(__is_ptr): ... this.
* include/bits/deque.tcc: Use __is_ptr instead.
* include/bits/stl_algobase.h: Likewise.

Signed-off-by: Ken Matsui 
---
 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_pointer.C   | 51 +
 gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
 gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
 libstdc++-v3/include/bits/deque.tcc |  6 +--
 libstdc++-v3/include/bits/stl_algobase.h|  6 +--
 11 files changed, 86 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..30266204eb5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", 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 8b7fece0cc8..b7c263e9a77 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_POINTER, "__is_pointer", 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 8fb47fd179e..68f8a4fe85b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_POINTER:
+  return TYPE_PTR_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_POINTER:
   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..9dace5cbd48 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_pointer)
+# error "__has_builtin (__is_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
b/gcc/testsuite/g++.dg/ext/is_pointer.C
new file mode 100644
index 000..d6e39565950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_pointer(int));
+SA(__is_pointer(int*));
+SA(__is_pointer(int**));
+
+SA(__is_pointer(const int*));
+SA(__is_pointer(const int**));
+SA(__is_pointer(int* const));
+SA(__is_pointer(int** const));
+SA(__is_pointer(int* const* const));
+
+SA(__is_pointer(volatile int*));
+SA(__is_pointer(volatile int**));
+SA(__is_pointer(int* volatile));
+SA(__is_pointer(int** volatile));
+SA(__is_pointer(int* volatile* volatile));
+
+SA(__is_pointer(const volatile int*));
+SA(__is_pointer(const volatile int**));
+SA(__is_pointer(const int* volatile));
+SA(__is_pointer(volatile int* const));
+SA(__is_pointer(int* const volatile));
+SA(__is_pointer(const int** volatile));
+SA(__is_pointer(volatile int** const));
+SA(__is_pointer(int** const volatile));
+SA(__

[PATCH v4 2/2] libstdc++: Use new built-in trait __is_pointer

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_pointer.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_ptr): Use __is_pointer
built-in trait.
* include/std/type_traits (is_pointer): Likewise. Optimize its
implementation.
(is_pointer_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/cpp_type_traits.h |  8 
 libstdc++-v3/include/std/type_traits| 45 +
 2 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index 3711e4be526..4da1e7c407c 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -363,6 +363,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   //
   // Pointer types
   //
+#if __has_builtin(__is_pointer)
+  template
+struct __is_ptr : __truth_type<__is_pointer(_Tp)>
+{
+  enum { __value = __is_pointer(_Tp) };
+};
+#else
   template
 struct __is_ptr
 {
@@ -376,6 +383,7 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   enum { __value = 1 };
   typedef __true_type __type;
 };
+#endif
 
   //
   // An arithmetic type is an integer type or a floating point type
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..0743db4cb51 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -515,19 +515,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_array<_Tp[]>
 : public true_type { };
 
-  template
-struct __is_pointer_helper
+  /// is_pointer
+#if __has_builtin(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
+  template
+struct is_pointer
 : public false_type { };
+{ };
 
   template
-struct __is_pointer_helper<_Tp*>
+struct is_pointer<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
-struct is_pointer
-: public __is_pointer_helper<__remove_cv_t<_Tp>>::type
-{ };
+struct is_pointer<_Tp* const>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* volatile>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* const volatile>
+: public true_type { };
+#endif
 
   /// is_lvalue_reference
   template
@@ -3168,8 +3183,22 @@ template 
 template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
 
+#if __has_builtin(__is_pointer)
+template 
+  inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+#else
+template 
+  inline constexpr bool is_pointer_v = false;
+template 
+  inline constexpr bool is_pointer_v<_Tp*> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const> = true;
 template 
-  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+  inline constexpr bool is_pointer_v<_Tp* volatile> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
+#endif
+
 template 
   inline constexpr bool is_lvalue_reference_v = false;
 template 
-- 
2.41.0



[PATCH v5 1/2] c++, libstdc++: Implement __is_pointer built-in trait

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
* g++.dg/ext/is_pointer.C: New test.
* g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
(__is_ptr): ... this.
* g++.dg/torture/20070621-1.C: Likewise.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
(__is_ptr): ... this.
* include/bits/deque.tcc: Use __is_ptr instead.
* include/bits/stl_algobase.h: Likewise.

Signed-off-by: Ken Matsui 
---
 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_pointer.C   | 51 +
 gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
 gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
 libstdc++-v3/include/bits/deque.tcc |  6 +--
 libstdc++-v3/include/bits/stl_algobase.h|  6 +--
 11 files changed, 86 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..30266204eb5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", 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 8b7fece0cc8..b7c263e9a77 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_POINTER, "__is_pointer", 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 8fb47fd179e..68f8a4fe85b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_POINTER:
+  return TYPE_PTR_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_POINTER:
   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..9dace5cbd48 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_pointer)
+# error "__has_builtin (__is_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
b/gcc/testsuite/g++.dg/ext/is_pointer.C
new file mode 100644
index 000..d6e39565950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_pointer(int));
+SA(__is_pointer(int*));
+SA(__is_pointer(int**));
+
+SA(__is_pointer(const int*));
+SA(__is_pointer(const int**));
+SA(__is_pointer(int* const));
+SA(__is_pointer(int** const));
+SA(__is_pointer(int* const* const));
+
+SA(__is_pointer(volatile int*));
+SA(__is_pointer(volatile int**));
+SA(__is_pointer(int* volatile));
+SA(__is_pointer(int** volatile));
+SA(__is_pointer(int* volatile* volatile));
+
+SA(__is_pointer(const volatile int*));
+SA(__is_pointer(const volatile int**));
+SA(__is_pointer(const int* volatile));
+SA(__is_pointer(volatile int* const));
+SA(__is_pointer(int* const volatile));
+SA(__is_pointer(const int** volatile));
+SA(__is_pointer(volatile int** const));
+SA(__is_pointer(int** const volatile));
+SA(__

[PATCH v5 2/2] libstdc++: Use new built-in trait __is_pointer

2023-07-12 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_pointer.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_ptr): Use __is_pointer
built-in trait.
* include/std/type_traits (is_pointer): Likewise. Optimize its
implementation.
(is_pointer_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/cpp_type_traits.h |  8 
 libstdc++-v3/include/std/type_traits| 44 +
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index 3711e4be526..4da1e7c407c 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -363,6 +363,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   //
   // Pointer types
   //
+#if __has_builtin(__is_pointer)
+  template
+struct __is_ptr : __truth_type<__is_pointer(_Tp)>
+{
+  enum { __value = __is_pointer(_Tp) };
+};
+#else
   template
 struct __is_ptr
 {
@@ -376,6 +383,7 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   enum { __value = 1 };
   typedef __true_type __type;
 };
+#endif
 
   //
   // An arithmetic type is an integer type or a floating point type
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..16b2f6de536 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -515,19 +515,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_array<_Tp[]>
 : public true_type { };
 
-  template
-struct __is_pointer_helper
+  /// is_pointer
+#if __has_builtin(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
+  template
+struct is_pointer
 : public false_type { };
 
   template
-struct __is_pointer_helper<_Tp*>
+struct is_pointer<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
-struct is_pointer
-: public __is_pointer_helper<__remove_cv_t<_Tp>>::type
-{ };
+struct is_pointer<_Tp* const>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* volatile>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* const volatile>
+: public true_type { };
+#endif
 
   /// is_lvalue_reference
   template
@@ -3168,8 +3182,22 @@ template 
 template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
 
+#if __has_builtin(__is_pointer)
+template 
+  inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+#else
 template 
-  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+  inline constexpr bool is_pointer_v = false;
+template 
+  inline constexpr bool is_pointer_v<_Tp*> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* volatile> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
+#endif
+
 template 
   inline constexpr bool is_lvalue_reference_v = false;
 template 
-- 
2.41.0



Re: [PATCH v2 1/2] c++, libstdc++: implement __is_pointer built-in trait

2023-07-13 Thread Ken Matsui via Gcc-patches
On Thu, Jul 13, 2023 at 2:22 AM Jonathan Wakely  wrote:
>
> On Wed, 12 Jul 2023 at 21:42, Ken Matsui  wrote:
> >
> > On Wed, Jul 12, 2023 at 3:01 AM Jonathan Wakely  wrote:
> > >
> > > On Mon, 10 Jul 2023 at 06:51, Ken Matsui via Libstdc++
> > >  wrote:
> > > >
> > > > Hi,
> > > >
> > > > Here is the benchmark result for is_pointer:
> > > >
> > > > https://github.com/ken-matsui/gcc-benches/blob/main/is_pointer.md#sun-jul--9-103948-pm-pdt-2023
> > > >
> > > > Time: -62.1344%
> > > > Peak Memory Usage: -52.4281%
> > > > Total Memory Usage: -53.5889%
> > >
> > > Wow!
> > >
> > > Although maybe we could have improved our std::is_pointer_v anyway, like 
> > > so:
> > >
> > > template 
> > >   inline constexpr bool is_pointer_v = false;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp*> = true;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp* const> = true;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp* volatile> = true;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
> > >
> > > I'm not sure why I didn't already do that.
> > >
> > > Could you please benchmark that? And if it is better than the current
> > > impl using is_pointer<_Tp>::value then we should do this in the
> > > library:
> > >
> > > #if __has_builtin(__is_pointer)
> > > template 
> > >   inline constexpr bool is_pointer_v = __is_pointer(_Tp);
> > > #else
> > > template 
> > >   inline constexpr bool is_pointer_v = false;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp*> = true;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp* const> = true;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp* volatile> = true;
> > > template 
> > >   inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
> > > #endif
> >
> > Hi François and Jonathan,
> >
> > Thank you for your reviews! I will rename the four underscores to the
> > appropriate name and take a benchmark once I get home.
> >
> > If I apply your change on is_pointer_v, is it better to add the
> > `Co-authored-by:` line in the commit?
>
> Yes, that would be the correct thing to do (although in this case the
> change is small enough that I don't really care about getting credit
> for it :-)
>
Thank you! I will include it in my commit :) I see that you included
the DCO sign-off in the MAINTAINERS file. However, if a reviewer
doesn't, should I include the `Signed-off-by:` line for the reviewer
as well?


[PATCH v6 1/2] c++, libstdc++: Implement __is_pointer built-in trait

2023-07-13 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
* g++.dg/ext/is_pointer.C: New test.
* g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
(__is_ptr): ... this.
* g++.dg/torture/20070621-1.C: Likewise.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
(__is_ptr): ... this.
* include/bits/deque.tcc: Use __is_ptr instead.
* include/bits/stl_algobase.h: Likewise.

Signed-off-by: Ken Matsui 
---
 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_pointer.C   | 51 +
 gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
 gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
 libstdc++-v3/include/bits/deque.tcc |  6 +--
 libstdc++-v3/include/bits/stl_algobase.h|  6 +--
 11 files changed, 86 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..30266204eb5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", 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 8b7fece0cc8..b7c263e9a77 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_POINTER, "__is_pointer", 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 8fb47fd179e..68f8a4fe85b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_POINTER:
+  return TYPE_PTR_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_POINTER:
   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..9dace5cbd48 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_pointer)
+# error "__has_builtin (__is_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
b/gcc/testsuite/g++.dg/ext/is_pointer.C
new file mode 100644
index 000..d6e39565950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_pointer(int));
+SA(__is_pointer(int*));
+SA(__is_pointer(int**));
+
+SA(__is_pointer(const int*));
+SA(__is_pointer(const int**));
+SA(__is_pointer(int* const));
+SA(__is_pointer(int** const));
+SA(__is_pointer(int* const* const));
+
+SA(__is_pointer(volatile int*));
+SA(__is_pointer(volatile int**));
+SA(__is_pointer(int* volatile));
+SA(__is_pointer(int** volatile));
+SA(__is_pointer(int* volatile* volatile));
+
+SA(__is_pointer(const volatile int*));
+SA(__is_pointer(const volatile int**));
+SA(__is_pointer(const int* volatile));
+SA(__is_pointer(volatile int* const));
+SA(__is_pointer(int* const volatile));
+SA(__is_pointer(const int** volatile));
+SA(__is_pointer(volatile int** const));
+SA(__is_pointer(int** const volatile));
+SA(__

[PATCH v6 2/2] libstdc++: Use new built-in trait __is_pointer

2023-07-13 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_pointer.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_ptr): Use __is_pointer
built-in trait.
* include/std/type_traits (is_pointer): Likewise. Optimize its
implementation.
(is_pointer_v): Likewise.

Co-authored-by: Jonathan Wakely 
Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/cpp_type_traits.h |  8 
 libstdc++-v3/include/std/type_traits| 44 +
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index 3711e4be526..4da1e7c407c 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -363,6 +363,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   //
   // Pointer types
   //
+#if __has_builtin(__is_pointer)
+  template
+struct __is_ptr : __truth_type<__is_pointer(_Tp)>
+{
+  enum { __value = __is_pointer(_Tp) };
+};
+#else
   template
 struct __is_ptr
 {
@@ -376,6 +383,7 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   enum { __value = 1 };
   typedef __true_type __type;
 };
+#endif
 
   //
   // An arithmetic type is an integer type or a floating point type
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..16b2f6de536 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -515,19 +515,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_array<_Tp[]>
 : public true_type { };
 
-  template
-struct __is_pointer_helper
+  /// is_pointer
+#if __has_builtin(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
+  template
+struct is_pointer
 : public false_type { };
 
   template
-struct __is_pointer_helper<_Tp*>
+struct is_pointer<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
-struct is_pointer
-: public __is_pointer_helper<__remove_cv_t<_Tp>>::type
-{ };
+struct is_pointer<_Tp* const>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* volatile>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* const volatile>
+: public true_type { };
+#endif
 
   /// is_lvalue_reference
   template
@@ -3168,8 +3182,22 @@ template 
 template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
 
+#if __has_builtin(__is_pointer)
+template 
+  inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+#else
 template 
-  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+  inline constexpr bool is_pointer_v = false;
+template 
+  inline constexpr bool is_pointer_v<_Tp*> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* volatile> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
+#endif
+
 template 
   inline constexpr bool is_lvalue_reference_v = false;
 template 
-- 
2.41.0



Re: [PATCH v2 1/2] c++, libstdc++: implement __is_pointer built-in trait

2023-07-14 Thread Ken Matsui via Gcc-patches
On Fri, Jul 14, 2023 at 3:49 AM Jonathan Wakely  wrote:
>
> On Fri, 14 Jul 2023 at 11:48, Jonathan Wakely  wrote:
> >
> > On Thu, 13 Jul 2023 at 21:04, Ken Matsui  wrote:
> > >
> > > On Thu, Jul 13, 2023 at 2:22 AM Jonathan Wakely  
> > > wrote:
> > > >
> > > > On Wed, 12 Jul 2023 at 21:42, Ken Matsui  
> > > > wrote:
> > > > >
> > > > > On Wed, Jul 12, 2023 at 3:01 AM Jonathan Wakely  
> > > > > wrote:
> > > > > >
> > > > > > On Mon, 10 Jul 2023 at 06:51, Ken Matsui via Libstdc++
> > > > > >  wrote:
> > > > > > >
> > > > > > > Hi,
> > > > > > >
> > > > > > > Here is the benchmark result for is_pointer:
> > > > > > >
> > > > > > > https://github.com/ken-matsui/gcc-benches/blob/main/is_pointer.md#sun-jul--9-103948-pm-pdt-2023
> > > > > > >
> > > > > > > Time: -62.1344%
> > > > > > > Peak Memory Usage: -52.4281%
> > > > > > > Total Memory Usage: -53.5889%
> > > > > >
> > > > > > Wow!
> > > > > >
> > > > > > Although maybe we could have improved our std::is_pointer_v anyway, 
> > > > > > like so:
> > > > > >
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v = false;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp*> = true;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp* const> = true;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp* volatile> = true;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
> > > > > >
> > > > > > I'm not sure why I didn't already do that.
> > > > > >
> > > > > > Could you please benchmark that? And if it is better than the 
> > > > > > current
> > > > > > impl using is_pointer<_Tp>::value then we should do this in the
> > > > > > library:
> > > > > >
> > > > > > #if __has_builtin(__is_pointer)
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v = __is_pointer(_Tp);
> > > > > > #else
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v = false;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp*> = true;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp* const> = true;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp* volatile> = true;
> > > > > > template 
> > > > > >   inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
> > > > > > #endif
> > > > >
> > > > > Hi François and Jonathan,
> > > > >
> > > > > Thank you for your reviews! I will rename the four underscores to the
> > > > > appropriate name and take a benchmark once I get home.
> > > > >
> > > > > If I apply your change on is_pointer_v, is it better to add the
> > > > > `Co-authored-by:` line in the commit?
> > > >
> > > > Yes, that would be the correct thing to do (although in this case the
> > > > change is small enough that I don't really care about getting credit
> > > > for it :-)
> > > >
> > > Thank you! I will include it in my commit :) I see that you included
> > > the DCO sign-off in the MAINTAINERS file. However, if a reviewer
> > > doesn't, should I include the `Signed-off-by:` line for the reviewer
> > > as well?
> >
> > No, reviewers should not sign-off, that's for the code author. And
> > authors should add that themselves (or clearly state that they agree
> > to the DCO terms). You should not sign-off on someone else's behalf.
>
> You can add Reviewed-by: if you want to record that information.
>
I see. Thank you!


[PATCH] libstdc++: Use __bool_constant entirely

2023-07-14 Thread Ken Matsui via Gcc-patches
This patch uses __bool_constant entirely instead of integral_constant
in the type_traits header, specifically for true_type, false_type,
and bool_constant.

libstdc++-v3/ChangeLog:

* include/std/type_traits (true_type): Use __bool_constant
instead.
(false_type): Likewise.
(bool_constant): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 9f086992ebc..7dc5791a7c5 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -78,24 +78,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 constexpr _Tp integral_constant<_Tp, __v>::value;
 #endif
 
-  /// The type used as a compile-time boolean with true value.
-  using true_type =  integral_constant;
-
-  /// The type used as a compile-time boolean with false value.
-  using false_type = integral_constant;
-
   /// @cond undocumented
   /// bool_constant for C++11
   template
 using __bool_constant = integral_constant;
   /// @endcond
 
+  /// The type used as a compile-time boolean with true value.
+  using true_type =  __bool_constant;
+
+  /// The type used as a compile-time boolean with false value.
+  using false_type = __bool_constant;
+
 #if __cplusplus >= 201703L
 # define __cpp_lib_bool_constant 201505L
   /// Alias template for compile-time boolean constant types.
   /// @since C++17
   template
-using bool_constant = integral_constant;
+using bool_constant = __bool_constant<__v>;
 #endif
 
   // Metaprogramming helper types.
-- 
2.41.0



[PATCH v2 1/3] c++, libstdc++: Implement __is_arithmetic built-in trait

2023-07-14 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_arithmetic.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
* g++.dg/ext/is_arithmetic.C: New test.
* g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
(is_arithmetic): ... this.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
(is_arithmetic): ... this.
* include/c_global/cmath: Use is_arithmetic instead.
* include/c_std/cmath: Likewise.
* include/tr1/cmath: Likewise.

Signed-off-by: Ken Matsui 
---
 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_arithmetic.C| 33 ++
 gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
 libstdc++-v3/include/c_global/cmath | 48 ++---
 libstdc++-v3/include/c_std/cmath| 24 +--
 libstdc++-v3/include/tr1/cmath  | 24 +--
 11 files changed, 99 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..bd517d08843 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_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
+case CPTK_IS_ARITHMETIC:
+  inform (loc, "  %qT is not an arithmetic type", t1);
+  break;
 case CPTK_IS_TRIVIALLY_COPYABLE:
   inform (loc, "  %qT is not trivially copyable", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..a95aeeaf778 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_ARITHMETIC, "__is_arithmetic", 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 8fb47fd179e..4531f047d73 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_ARITHMETIC:
+  return ARITHMETIC_TYPE_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_ARITHMETIC:
   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..3d63b0101d1 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_arithmetic)
+# error "__has_builtin (__is_arithmetic) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
new file mode 100644
index 000..fd35831f646
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_arithmetic, void, false);
+
+SA_TEST_CATEGORY(__is_arithmetic, char, true);
+SA_TEST_CATEGORY(__is_arithmetic, signed char, true);
+SA_TEST_CATEGORY(__is_arithmetic, unsigned char, true);
+SA_TEST_CATEGORY(__is_arithmetic, wchar_t, true);
+SA_TEST_CATEGORY(__is_arithmetic, short, tr

[PATCH v2 2/3] libstdc++: Optimize is_arithmetic performance by __is_arithmetic built-in

2023-07-14 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_arithmetic trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_arithmetic): Use __is_arithmetic
built-in trait.
(is_arithmetic_v): Likewise.

Signed-off-by: Ken Matsui 
---
 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..7ebbe04c77b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -655,10 +655,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_arithmetic
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_arithmetic
+: public __bool_constant<__is_arithmetic(_Tp)>
+{ };
+#else
   template
 struct is_arithmetic
 : public __or_, is_floating_point<_Tp>>::type
 { };
+#endif
 
   /// is_fundamental
   template
@@ -3198,8 +3205,15 @@ template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+
+#if __has_builtin(__is_arithmetic)
+template 
+  inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+#else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v2 3/3] libstdc++: Optimize is_fundamental performance by __is_arithmetic built-in

2023-07-14 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_fundamental trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_fundamental_v): Use __is_arithmetic
built-in trait.
(is_fundamental): Likewise. Optimize the original implementation.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 7ebbe04c77b..cf24de2fcac 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   /// is_fundamental
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_fundamental
+: public __bool_constant<__is_arithmetic(_Tp)
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
+{ };
+#else
   template
 struct is_fundamental
-: public __or_, is_void<_Tp>,
-  is_null_pointer<_Tp>>::type
+: public __bool_constant::value
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
 { };
+#endif
 
   /// is_object
   template
@@ -3209,13 +3219,16 @@ template 
 #if __has_builtin(__is_arithmetic)
 template 
   inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+template 
+  inline constexpr bool is_fundamental_v
+= __is_arithmetic(_Tp) || is_void_v<_Tp> || is_null_pointer_v<_Tp>;
 #else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
-#endif
-
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
 template 
-- 
2.41.0



Re: [PATCH v2 3/3] libstdc++: Optimize is_fundamental performance by __is_arithmetic built-in

2023-07-14 Thread Ken Matsui via Gcc-patches
Hi,

Here are the benchmarks for this change:

* is_fundamental

https://github.com/ken-matsui/gcc-benches/blob/main/is_fundamental.md#fri-jul-14-091146-pm-pdt-2023

Time: -37.1619%
Peak Memory Usage: -29.4294%
Total Memory Usage: -29.4783%

* is_fundamental_v

https://github.com/ken-matsui/gcc-benches/blob/main/is_fundamental_v.md#fri-jul-14-091757-pm-pdt-2023

Time: -35.5446%
Peak Memory Usage: -30.0096%
Total Memory Usage: -30.6021%

* is_fundamental with bool_constant (on trunk
[18dac101678b8c0aed4bd995351e47f26cd54dec])

https://github.com/ken-matsui/gcc-benches/blob/main/is_fundamental-bool_constant.md#fri-jul-14-094237-pm-pdt-2023

Time: -28.3908%
Peak Memory Usage: -18.5403%
Total Memory Usage: -19.9045%

---

It appears using bool_constant is better than disjunction. If my
understanding is correct, disjunction can avoid later instantiations
when short-circuiting, but might the evaluation of disjunction be more
expensive than evaluating is_void and is_null_pointer? Or my benchmark
might be just incorrect.

Sincerely,
Ken Matsui

On Fri, Jul 14, 2023 at 9:57 PM Ken Matsui  wrote:
>
> This patch optimizes the performance of the is_fundamental trait by
> dispatching to the new __is_arithmetic built-in trait.
>
> libstdc++-v3/ChangeLog:
>
> * include/std/type_traits (is_fundamental_v): Use __is_arithmetic
> built-in trait.
> (is_fundamental): Likewise. Optimize the original implementation.
>
> Signed-off-by: Ken Matsui 
> ---
>  libstdc++-v3/include/std/type_traits | 21 +
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/type_traits 
> b/libstdc++-v3/include/std/type_traits
> index 7ebbe04c77b..cf24de2fcac 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  #endif
>
>/// is_fundamental
> +#if __has_builtin(__is_arithmetic)
> +  template
> +struct is_fundamental
> +: public __bool_constant<__is_arithmetic(_Tp)
> + || is_void<_Tp>::value
> + || is_null_pointer<_Tp>::value>
> +{ };
> +#else
>template
>  struct is_fundamental
> -: public __or_, is_void<_Tp>,
> -  is_null_pointer<_Tp>>::type
> +: public __bool_constant::value
> + || is_void<_Tp>::value
> + || is_null_pointer<_Tp>::value>
>  { };
> +#endif
>
>/// is_object
>template
> @@ -3209,13 +3219,16 @@ template 
>  #if __has_builtin(__is_arithmetic)
>  template 
>inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
> +template 
> +  inline constexpr bool is_fundamental_v
> += __is_arithmetic(_Tp) || is_void_v<_Tp> || is_null_pointer_v<_Tp>;
>  #else
>  template 
>inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
> -#endif
> -
>  template 
>inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> +#endif
> +
>  template 
>inline constexpr bool is_object_v = is_object<_Tp>::value;
>  template 
> --
> 2.41.0
>


Re: [PATCH v2 1/3] c++, libstdc++: Implement __is_arithmetic built-in trait

2023-07-16 Thread Ken Matsui via Gcc-patches
On Sun, Jul 16, 2023 at 5:28 AM François Dumont  wrote:
>
>
> On 15/07/2023 06:55, Ken Matsui via Libstdc++ wrote:
> > This patch implements built-in trait for std::is_arithmetic.
> >
> > gcc/cp/ChangeLog:
> >
> >   * cp-trait.def: Define __is_arithmetic.
> >   * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_ARITHMETIC.
> >   * semantics.cc (trait_expr_value): Likewise.
> >   (finish_trait_expr): Likewise.
> >
> > gcc/testsuite/ChangeLog:
> >
> >   * g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
> >   * g++.dg/ext/is_arithmetic.C: New test.
> >   * g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
> >   (is_arithmetic): ... this.
> >   * g++.dg/torture/pr57107.C: Likewise.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
> >   (is_arithmetic): ... this.
> >   * include/c_global/cmath: Use is_arithmetic instead.
> >   * include/c_std/cmath: Likewise.
> >   * include/tr1/cmath: Likewise.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >   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_arithmetic.C| 33 ++
> >   gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
> >   gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
> >   libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
> >   libstdc++-v3/include/c_global/cmath | 48 ++---
> >   libstdc++-v3/include/c_std/cmath| 24 +--
> >   libstdc++-v3/include/tr1/cmath  | 24 +--
> >   11 files changed, 99 insertions(+), 55 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C
> >
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index 8cf0f2d0974..bd517d08843 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_AGGREGATE:
> > inform (loc, "  %qT is not an aggregate", t1);
> > break;
> > +case CPTK_IS_ARITHMETIC:
> > +  inform (loc, "  %qT is not an arithmetic type", t1);
> > +  break;
> >   case CPTK_IS_TRIVIALLY_COPYABLE:
> > inform (loc, "  %qT is not trivially copyable", t1);
> > break;
> > diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> > index 8b7fece0cc8..a95aeeaf778 100644
> > --- a/gcc/cp/cp-trait.def
> > +++ b/gcc/cp/cp-trait.def
> > @@ -82,6 +82,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_ARITHMETIC, "__is_arithmetic", 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 8fb47fd179e..4531f047d73 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> > tree type2)
> >   case CPTK_IS_UNION:
> > return type_code1 == UNION_TYPE;
> >
> > +case CPTK_IS_ARITHMETIC:
> > +  return ARITHMETIC_TYPE_P (type1);
> > +
> >   case CPTK_IS_ASSIGNABLE:
> > return is_xible (MODIFY_EXPR, type1, type2);
> >
> > @@ -12296,6 +12299,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_ARITHMETIC:
> > 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..3d63b0101d1 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_arithmetic)
> > +# error "__has_builtin (__is_arithmetic) failed"
> > +#endif
> > diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
> > b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
> > new file mode 100644
> > index 000..fd35831f646
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
> > @@ -0,0 +1,33 @@
> > +// { dg-do compile { target c++11 } }
> > +
> > +#include 
> > +
> > +using namespace __gnu_test;
> > +
> > +#define SA(X) static_assert((X),#

Re: [PATCH v2 2/3] libstdc++: Optimize is_arithmetic performance by __is_arithmetic built-in

2023-07-16 Thread Ken Matsui via Gcc-patches
On Sun, Jul 16, 2023 at 5:32 AM François Dumont  wrote:
>
>
> On 15/07/2023 06:55, Ken Matsui via Libstdc++ wrote:
> > This patch optimizes the performance of the is_arithmetic trait by
> > dispatching to the new __is_arithmetic built-in trait.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/std/type_traits (is_arithmetic): Use __is_arithmetic
> >   built-in trait.
> >   (is_arithmetic_v): Likewise.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >   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..7ebbe04c77b 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -655,10 +655,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >   { };
> >
> > /// is_arithmetic
> > +#if __has_builtin(__is_arithmetic)
> > +  template
> > +struct is_arithmetic
> > +: public __bool_constant<__is_arithmetic(_Tp)>
> > +{ };
> > +#else
> > template
> >   struct is_arithmetic
> >   : public __or_, is_floating_point<_Tp>>::type
> >   { };
> > +#endif
> >
> > /// is_fundamental
> > template
> > @@ -3198,8 +3205,15 @@ template 
> > inline constexpr bool is_reference_v<_Tp&> = true;
> >   template 
> > inline constexpr bool is_reference_v<_Tp&&> = true;
> > +
> > +#if __has_builtin(__is_arithmetic)
> > +template 
> > +  inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
> > +#else
> >   template 
> > inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
> > +#endif
> > +
> >   template 
> > inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
> >   template 
>
> Same remark as the one I did for __is_pointer in cpp_type_traits.h. You
> could implement it as:
>
>template
>  struct __is_arithmetic_t
>  : public __truth_type<__is_arithmetic(_Tp)>
>  { };
>
> François
>
Thank you for your review! This is from the type_traits header, so the
name should be as-is.


Re: [PATCH v2 3/3] libstdc++: Optimize is_fundamental performance by __is_arithmetic built-in

2023-07-16 Thread Ken Matsui via Gcc-patches
On Sun, Jul 16, 2023 at 5:41 AM François Dumont  wrote:
>
>
> On 15/07/2023 06:55, Ken Matsui via Libstdc++ wrote:
> > This patch optimizes the performance of the is_fundamental trait by
> > dispatching to the new __is_arithmetic built-in trait.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/std/type_traits (is_fundamental_v): Use __is_arithmetic
> >   built-in trait.
> >   (is_fundamental): Likewise. Optimize the original implementation.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >   libstdc++-v3/include/std/type_traits | 21 +
> >   1 file changed, 17 insertions(+), 4 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/std/type_traits 
> > b/libstdc++-v3/include/std/type_traits
> > index 7ebbe04c77b..cf24de2fcac 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >   #endif
> >
> > /// is_fundamental
> > +#if __has_builtin(__is_arithmetic)
> > +  template
> > +struct is_fundamental
> > +: public __bool_constant<__is_arithmetic(_Tp)
> > + || is_void<_Tp>::value
> > + || is_null_pointer<_Tp>::value>
> > +{ };
>
> What about doing this ?
>
>template
>  struct is_fundamental
>  : public __bool_constant<__is_arithmetic(_Tp)
>   || __or_,
>   is_null_pointer<_Tp>>::value>
>  { };
>
> Based on your benches it seems that builtin __is_arithmetic is much better 
> that std::is_arithmetic. But __or_ could still avoid instantiation of 
> is_null_pointer.
>
Let me take a benchmark for this later.


Re: [PATCH v2 3/3] libstdc++: Optimize is_fundamental performance by __is_arithmetic built-in

2023-07-17 Thread Ken Matsui via Gcc-patches
Hi,

I took a benchmark for this.

https://github.com/ken-matsui/gcc-benches/blob/main/is_fundamental-disjunction.md#mon-jul-17-105937-pm-pdt-2023

template
struct is_fundamental
: public std::bool_constant<__is_arithmetic(_Tp)
|| std::is_void<_Tp>::value
|| std::is_null_pointer<_Tp>::value>
{ };

is faster than:

template
struct is_fundamental
: public std::bool_constant<__is_arithmetic(_Tp)
|| std::disjunction,
std::is_null_pointer<_Tp>
>::value>
{ };

Time: -32.2871%
Peak Memory: -18.5071%
Total Memory: -20.1991%

Sincerely,
Ken Matsui

On Sun, Jul 16, 2023 at 9:49 PM Ken Matsui  wrote:
>
> On Sun, Jul 16, 2023 at 5:41 AM François Dumont  wrote:
> >
> >
> > On 15/07/2023 06:55, Ken Matsui via Libstdc++ wrote:
> > > This patch optimizes the performance of the is_fundamental trait by
> > > dispatching to the new __is_arithmetic built-in trait.
> > >
> > > libstdc++-v3/ChangeLog:
> > >
> > >   * include/std/type_traits (is_fundamental_v): Use __is_arithmetic
> > >   built-in trait.
> > >   (is_fundamental): Likewise. Optimize the original implementation.
> > >
> > > Signed-off-by: Ken Matsui 
> > > ---
> > >   libstdc++-v3/include/std/type_traits | 21 +
> > >   1 file changed, 17 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/libstdc++-v3/include/std/type_traits 
> > > b/libstdc++-v3/include/std/type_traits
> > > index 7ebbe04c77b..cf24de2fcac 100644
> > > --- a/libstdc++-v3/include/std/type_traits
> > > +++ b/libstdc++-v3/include/std/type_traits
> > > @@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >   #endif
> > >
> > > /// is_fundamental
> > > +#if __has_builtin(__is_arithmetic)
> > > +  template
> > > +struct is_fundamental
> > > +: public __bool_constant<__is_arithmetic(_Tp)
> > > + || is_void<_Tp>::value
> > > + || is_null_pointer<_Tp>::value>
> > > +{ };
> >
> > What about doing this ?
> >
> >template
> >  struct is_fundamental
> >  : public __bool_constant<__is_arithmetic(_Tp)
> >   || __or_,
> >   is_null_pointer<_Tp>>::value>
> >  { };
> >
> > Based on your benches it seems that builtin __is_arithmetic is much better 
> > that std::is_arithmetic. But __or_ could still avoid instantiation of 
> > is_null_pointer.
> >
> Let me take a benchmark for this later.


Re: [PATCH v2 3/3] libstdc++: Optimize is_fundamental performance by __is_arithmetic built-in

2023-07-17 Thread Ken Matsui via Gcc-patches
I will eventually work on disjunction to somehow optimize, but in the
meantime, this might be a better implementation. Of course, my
benchmark could be wrong.

On Mon, Jul 17, 2023 at 11:24 PM Ken Matsui  wrote:
>
> Hi,
>
> I took a benchmark for this.
>
> https://github.com/ken-matsui/gcc-benches/blob/main/is_fundamental-disjunction.md#mon-jul-17-105937-pm-pdt-2023
>
> template
> struct is_fundamental
> : public std::bool_constant<__is_arithmetic(_Tp)
> || std::is_void<_Tp>::value
> || std::is_null_pointer<_Tp>::value>
> { };
>
> is faster than:
>
> template
> struct is_fundamental
> : public std::bool_constant<__is_arithmetic(_Tp)
> || std::disjunction,
> std::is_null_pointer<_Tp>
> >::value>
> { };
>
> Time: -32.2871%
> Peak Memory: -18.5071%
> Total Memory: -20.1991%
>
> Sincerely,
> Ken Matsui
>
> On Sun, Jul 16, 2023 at 9:49 PM Ken Matsui  wrote:
> >
> > On Sun, Jul 16, 2023 at 5:41 AM François Dumont  
> > wrote:
> > >
> > >
> > > On 15/07/2023 06:55, Ken Matsui via Libstdc++ wrote:
> > > > This patch optimizes the performance of the is_fundamental trait by
> > > > dispatching to the new __is_arithmetic built-in trait.
> > > >
> > > > libstdc++-v3/ChangeLog:
> > > >
> > > >   * include/std/type_traits (is_fundamental_v): Use __is_arithmetic
> > > >   built-in trait.
> > > >   (is_fundamental): Likewise. Optimize the original implementation.
> > > >
> > > > Signed-off-by: Ken Matsui 
> > > > ---
> > > >   libstdc++-v3/include/std/type_traits | 21 +
> > > >   1 file changed, 17 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/libstdc++-v3/include/std/type_traits 
> > > > b/libstdc++-v3/include/std/type_traits
> > > > index 7ebbe04c77b..cf24de2fcac 100644
> > > > --- a/libstdc++-v3/include/std/type_traits
> > > > +++ b/libstdc++-v3/include/std/type_traits
> > > > @@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > > >   #endif
> > > >
> > > > /// is_fundamental
> > > > +#if __has_builtin(__is_arithmetic)
> > > > +  template
> > > > +struct is_fundamental
> > > > +: public __bool_constant<__is_arithmetic(_Tp)
> > > > + || is_void<_Tp>::value
> > > > + || is_null_pointer<_Tp>::value>
> > > > +{ };
> > >
> > > What about doing this ?
> > >
> > >template
> > >  struct is_fundamental
> > >  : public __bool_constant<__is_arithmetic(_Tp)
> > >   || __or_,
> > >   is_null_pointer<_Tp>>::value>
> > >  { };
> > >
> > > Based on your benches it seems that builtin __is_arithmetic is much 
> > > better that std::is_arithmetic. But __or_ could still avoid instantiation 
> > > of is_null_pointer.
> > >
> > Let me take a benchmark for this later.


[PATCH v3 1/3] c++, libstdc++: Implement __is_arithmetic built-in trait

2023-07-17 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_arithmetic.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
* g++.dg/ext/is_arithmetic.C: New test.
* g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
(__is_arith): ... this.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
(__is_arith): ... this.
* include/c_global/cmath: Use __is_arith instead.
* include/c_std/cmath: Likewise.
* include/tr1/cmath: Likewise.

Signed-off-by: Ken Matsui 
---
 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_arithmetic.C| 33 ++
 gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
 libstdc++-v3/include/c_global/cmath | 48 ++---
 libstdc++-v3/include/c_std/cmath| 24 +--
 libstdc++-v3/include/tr1/cmath  | 24 +--
 11 files changed, 99 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..bd517d08843 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_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
+case CPTK_IS_ARITHMETIC:
+  inform (loc, "  %qT is not an arithmetic type", t1);
+  break;
 case CPTK_IS_TRIVIALLY_COPYABLE:
   inform (loc, "  %qT is not trivially copyable", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..a95aeeaf778 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_ARITHMETIC, "__is_arithmetic", 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 8fb47fd179e..4531f047d73 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_ARITHMETIC:
+  return ARITHMETIC_TYPE_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_ARITHMETIC:
   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..3d63b0101d1 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_arithmetic)
+# error "__has_builtin (__is_arithmetic) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
new file mode 100644
index 000..fd35831f646
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_arithmetic, void, false);
+
+SA_TEST_CATEGORY(__is_arithmetic, char, true);
+SA_TEST_CATEGORY(__is_arithmetic, signed char, true);
+SA_TEST_CATEGORY(__is_arithmetic, unsigned char, true);
+SA_TEST_CATEGORY(__is_arithmetic, wchar_t, true);
+SA_TEST_CATEGORY(__is_arithmetic, short, true);
+SA_TEST_CATEGOR

[PATCH v3 2/3] libstdc++: Optimize is_arithmetic performance by __is_arithmetic built-in

2023-07-17 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_arithmetic trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_arithmetic): Use __is_arithmetic
built-in trait.
(is_arithmetic_v): Likewise.

Signed-off-by: Ken Matsui 
---
 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..7ebbe04c77b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -655,10 +655,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_arithmetic
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_arithmetic
+: public __bool_constant<__is_arithmetic(_Tp)>
+{ };
+#else
   template
 struct is_arithmetic
 : public __or_, is_floating_point<_Tp>>::type
 { };
+#endif
 
   /// is_fundamental
   template
@@ -3198,8 +3205,15 @@ template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+
+#if __has_builtin(__is_arithmetic)
+template 
+  inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+#else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v3 3/3] libstdc++: Optimize is_fundamental performance by __is_arithmetic built-in

2023-07-17 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_fundamental trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_fundamental_v): Use __is_arithmetic
built-in trait.
(is_fundamental): Likewise. Optimize the original implementation.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 7ebbe04c77b..cf24de2fcac 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   /// is_fundamental
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_fundamental
+: public __bool_constant<__is_arithmetic(_Tp)
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
+{ };
+#else
   template
 struct is_fundamental
-: public __or_, is_void<_Tp>,
-  is_null_pointer<_Tp>>::type
+: public __bool_constant::value
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
 { };
+#endif
 
   /// is_object
   template
@@ -3209,13 +3219,16 @@ template 
 #if __has_builtin(__is_arithmetic)
 template 
   inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+template 
+  inline constexpr bool is_fundamental_v
+= __is_arithmetic(_Tp) || is_void_v<_Tp> || is_null_pointer_v<_Tp>;
 #else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
-#endif
-
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v4 1/4] c++, libstdc++: Implement __is_arithmetic built-in trait

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_arithmetic.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
* g++.dg/ext/is_arithmetic.C: New test.
* g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
(__is_arith): ... this.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
(__is_arith): ... this.
* include/c_global/cmath: Use __is_arith instead.
* include/c_std/cmath: Likewise.
* include/tr1/cmath: Likewise.

Signed-off-by: Ken Matsui 
---
 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_arithmetic.C| 33 ++
 gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
 libstdc++-v3/include/c_global/cmath | 48 ++---
 libstdc++-v3/include/c_std/cmath| 24 +--
 libstdc++-v3/include/tr1/cmath  | 24 +--
 11 files changed, 99 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..bd517d08843 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_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
+case CPTK_IS_ARITHMETIC:
+  inform (loc, "  %qT is not an arithmetic type", t1);
+  break;
 case CPTK_IS_TRIVIALLY_COPYABLE:
   inform (loc, "  %qT is not trivially copyable", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..a95aeeaf778 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_ARITHMETIC, "__is_arithmetic", 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 8fb47fd179e..4531f047d73 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_ARITHMETIC:
+  return ARITHMETIC_TYPE_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,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_ARITHMETIC:
   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..3d63b0101d1 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_arithmetic)
+# error "__has_builtin (__is_arithmetic) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
new file mode 100644
index 000..fd35831f646
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+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_arithmetic, void, false);
+
+SA_TEST_CATEGORY(__is_arithmetic, char, true);
+SA_TEST_CATEGORY(__is_arithmetic, signed char, true);
+SA_TEST_CATEGORY(__is_arithmetic, unsigned char, true);
+SA_TEST_CATEGORY(__is_arithmetic, wchar_t, true);
+SA_TEST_CATEGORY(__is_arithmetic, short, true);
+SA_TEST_CATEGOR

[PATCH v4 2/4] libstdc++: Optimize is_arithmetic trait performance

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_arithmetic trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_arithmetic): Use __is_arithmetic
built-in trait.
(is_arithmetic_v): Likewise.

Signed-off-by: Ken Matsui 
---
 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..7ebbe04c77b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -655,10 +655,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_arithmetic
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_arithmetic
+: public __bool_constant<__is_arithmetic(_Tp)>
+{ };
+#else
   template
 struct is_arithmetic
 : public __or_, is_floating_point<_Tp>>::type
 { };
+#endif
 
   /// is_fundamental
   template
@@ -3198,8 +3205,15 @@ template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+
+#if __has_builtin(__is_arithmetic)
+template 
+  inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+#else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v4 3/4] libstdc++: Optimize is_fundamental trait performance

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_fundamental trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_fundamental_v): Use __is_arithmetic
built-in trait.
(is_fundamental): Likewise. Optimize the original implementation.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 7ebbe04c77b..cf24de2fcac 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -668,11 +668,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   /// is_fundamental
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_fundamental
+: public __bool_constant<__is_arithmetic(_Tp)
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
+{ };
+#else
   template
 struct is_fundamental
-: public __or_, is_void<_Tp>,
-  is_null_pointer<_Tp>>::type
+: public __bool_constant::value
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
 { };
+#endif
 
   /// is_object
   template
@@ -3209,13 +3219,16 @@ template 
 #if __has_builtin(__is_arithmetic)
 template 
   inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+template 
+  inline constexpr bool is_fundamental_v
+= __is_arithmetic(_Tp) || is_void_v<_Tp> || is_null_pointer_v<_Tp>;
 #else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
-#endif
-
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
 template 
-- 
2.41.0



[PATCH v4 4/4] libstdc++: Optimize is_compound trait performance

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch optimizes the performance of the is_compound trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_compound): Use __is_arithmetic
built-in trait.
(is_compound_v): Use is_fundamental_v instead.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index cf24de2fcac..73d9a2b16fc 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -702,9 +702,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_compound
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_compound
+: public __bool_constant::value
+ || is_null_pointer<_Tp>::value)>
+{ };
+#else
   template
 struct is_compound
 : public __not_>::type { };
+#endif
 
   /// @cond undocumented
   template
@@ -3234,7 +3243,7 @@ template 
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-  inline constexpr bool is_compound_v = is_compound<_Tp>::value;
+  inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>;
 template 
   inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
 template 
-- 
2.41.0



[PATCH] libstdc++: Define _GLIBCXX_HAS_BUILTIN_TRAIT

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch defines _GLIBCXX_HAS_BUILTIN_TRAIT, which will be used as a
flag to toggle built-in traits in the type_traits header. Through this
macro function and _GLIBCXX_NO_BUILTIN_TRAITS macro, we can switch the
use of built-in traits without needing to modify the source code.

libstdc++-v3/ChangeLog:

* include/bits/c++config (_GLIBCXX_HAS_BUILTIN_TRAIT): Define.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/c++config | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index dd47f274d5f..de13f61db71 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -854,7 +854,11 @@ namespace __gnu_cxx
 # define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1
 #endif
 
-#undef _GLIBCXX_HAS_BUILTIN
+// Returns true if _GLIBCXX_NO_BUILTIN_TRAITS is not defined and the compiler
+// has a corresponding built-in type trait. _GLIBCXX_NO_BUILTIN_TRAITS is
+// defined to disable the use of built-in traits.
+#define _GLIBCXX_HAS_BUILTIN_TRAIT(BT)  \
+  (!defined(_GLIBCXX_NO_BUILTIN_TRAITS) && _GLIBCXX_HAS_BUILTIN(BT))
 
 // Mark code that should be ignored by the compiler, but seen by Doxygen.
 #define _GLIBCXX_DOXYGEN_ONLY(X)
-- 
2.41.0



[PATCH 0/8] Tweak predicate macros in tree

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch series tweaks predicate macros in tree.h to make the code more
readable. TYPE_REF_P is moved to tree.h and used for INDIRECT_TYPE_P and
TYPE_REF_IS_LVALUE. TYPE_PTR_P is also moved to tree.h and used for
INDIRECT_TYPE_P. POINTER_TYPE_P in tree.h is replaced with INDIRECT_TYPE_P
since it is ambiguous. TYPE_REF_IS_LVALUE is defined in tree.h through
TYPE_REF_P and TYPE_REF_IS_RVALUE. The same behavior codes with those
predicate macros are replaced for clarity.

These works were all the way up to implementing __is_lvalue_reference
built-in trait and optimizing the is_lvalue_reference trait. However, those
changes were dropped since I did not observe any performance improvements.
For those who are interested in the benchmark results, they can be found
below:

1. is_lvalue_reference

https://github.com/ken-matsui/gcc-benches/blob/main/is_lvalue_reference.md#tue-jul-18-033708-pm-pdt-2023

Time: +1.35432%
Peak Memory Usage: -0.103283%
Total Memory Usage: No difference

2. is_lvalue_reference_v

https://github.com/ken-matsui/gcc-benches/blob/main/is_lvalue_reference_v.md#tue-jul-18-034236-pm-pdt-2023

Time: No difference
Peak Memory Usage: -0.426872%
Total Memory Usage: -0.677638%

Ken Matsui (8):
  c++, tree: Move TYPE_REF_P to tree.h
  gcc: Use TYPE_REF_P
  c++, tree: Move TYPE_PTR_P to tree.h
  c++, tree: Move INDIRECT_TYPE_P to tree.h
  gcc: Use INDIRECT_TYPE_P instead of POINTER_TYPE_P
  tree: Remove POINTER_TYPE_P
  tree: Define TYPE_REF_IS_LVALUE
  c++, lto: Use TYPE_REF_IS_LVALUE

 gcc/ada/gcc-interface/ada-tree.h   |   2 +-
 gcc/ada/gcc-interface/decl.cc  |   6 +-
 gcc/ada/gcc-interface/trans.cc |  16 +--
 gcc/ada/gcc-interface/utils.cc |  12 +-
 gcc/ada/gcc-interface/utils2.cc|  14 +-
 gcc/alias.cc   |  12 +-
 gcc/analyzer/analyzer.cc   |   4 +-
 gcc/analyzer/call-details.h|   2 +-
 gcc/analyzer/call-summary.cc   |   2 +-
 gcc/analyzer/checker-event.cc  |   4 +-
 gcc/analyzer/constraint-manager.cc |   2 +-
 gcc/analyzer/engine.cc |   4 +-
 gcc/analyzer/program-state.cc  |   2 +-
 gcc/analyzer/region-model-manager.cc   |   6 +-
 gcc/analyzer/region-model.cc   |   6 +-
 gcc/analyzer/sm.cc |   4 +-
 gcc/analyzer/svalue.cc |   2 +-
 gcc/analyzer/varargs.cc|   2 +-
 gcc/asan.cc|   4 +-
 gcc/builtins.cc|  24 ++--
 gcc/c-family/c-ada-spec.cc |   2 +-
 gcc/c-family/c-attribs.cc  |  32 ++---
 gcc/c-family/c-common.cc   |  41 +++---
 gcc/c-family/c-omp.cc  |   8 +-
 gcc/c-family/c-pretty-print.cc |   4 +-
 gcc/c-family/c-ubsan.cc|  10 +-
 gcc/c-family/c-warn.cc |  34 ++---
 gcc/c/c-decl.cc|   8 +-
 gcc/c/c-parser.cc  |   4 +-
 gcc/c/c-typeck.cc  |  40 +++---
 gcc/c/gimple-parser.cc |   8 +-
 gcc/calls.cc   |   2 +-
 gcc/cfgexpand.cc   |   6 +-
 gcc/cgraph.cc  |   2 +-
 gcc/cgraphunit.cc  |   2 +-
 gcc/config/aarch64/aarch64-builtins.cc |   2 +-
 gcc/config/aarch64/aarch64-sve-builtins.cc |   2 +-
 gcc/config/aarch64/aarch64.cc  |   6 +-
 gcc/config/arc/arc.cc  |   2 +-
 gcc/config/arm/arm-builtins.cc |   6 +-
 gcc/config/arm/arm-mve-builtins.cc |   2 +-
 gcc/config/avr/avr.cc  |   6 +-
 gcc/config/epiphany/epiphany.cc|   2 +-
 gcc/config/gcn/gcn-tree.cc |   2 +-
 gcc/config/gcn/gcn.cc  |   6 +-
 gcc/config/i386/i386-builtins.cc   |   2 +-
 gcc/config/i386/i386-options.cc|   2 +-
 gcc/config/i386/i386.cc|  10 +-
 gcc/config/m32c/m32c.cc|   2 +-
 gcc/config/m68k/m68k.cc|   4 +-
 gcc/config/mips/mips.cc|   2 +-
 gcc/config/mn10300/mn10300.cc  |   2 +-
 gcc/config/msp430/msp430.cc|   2 +-
 gcc/config/nios2/nios2.cc  |   2 +-
 gcc/config/pa/pa.cc|   4 +-
 gcc/config/pru/pru-passes.cc   |   2 +-
 gcc/config/pru/pru.cc  |   2 +-
 gcc/config/rs6000/rs6000-builtin.cc|   4 +-
 gcc/config/rs6000/rs6000-c.cc  |  10 +-
 gcc/config/rs6000/rs6000.cc|   4 +-
 gcc/config/s390/s390-c.cc  |   2 +-
 gcc/config/s390/s390.cc|  12 +-
 gcc/config/sparc/sparc.cc  |   2 +-
 gcc/convert.cc |   4 +-
 gcc/cp/class.cc|   4 +-
 gcc/cp/constexpr.cc

[PATCH 1/8] c++, tree: Move TYPE_REF_P to tree.h

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch moves TYPE_REF_P from cp/cp-tree.h to tree.h to simplify the
same code as it and to declare TYPE_REF_IS_LVALUE that determines if a
type is a C++ lvalue reference.

gcc/cp/ChangeLog:

* cp-tree.h (TYPE_REF_P): Remove.

gcc/ChangeLog:

* tree.h (TYPE_REF_P): Define.

Signed-off-by: Ken Matsui 
---
 gcc/cp/cp-tree.h | 4 
 gcc/tree.h   | 4 
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3de0e154c12..8c96d868650 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4710,10 +4710,6 @@ get_vec_init_expr (tree t)
 #define TYPE_PTR_P(NODE)   \
   (TREE_CODE (NODE) == POINTER_TYPE)
 
-/* Returns true if NODE is a reference.  */
-#define TYPE_REF_P(NODE)   \
-  (TREE_CODE (NODE) == REFERENCE_TYPE)
-
 /* Returns true if NODE is a pointer or a reference.  */
 #define INDIRECT_TYPE_P(NODE)  \
   (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
diff --git a/gcc/tree.h b/gcc/tree.h
index 4c04245e2b1..ca3e0ce8f5e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -678,6 +678,10 @@ extern void omp_clause_range_check_failed (const_tree, 
const char *, int,
 #define AGGREGATE_TYPE_P(TYPE) \
   (TREE_CODE (TYPE) == ARRAY_TYPE || RECORD_OR_UNION_TYPE_P (TYPE))
 
+/* Nonzero if this type is a reference.  */
+#define TYPE_REF_P(NODE)   \
+  (TREE_CODE (NODE) == REFERENCE_TYPE)
+
 /* Nonzero if TYPE represents a pointer or reference type.
(It should be renamed to INDIRECT_TYPE_P.)  Keep these checks in
ascending code order.  */
-- 
2.41.0



[PATCH 2/8] gcc: Use TYPE_REF_P

2023-07-18 Thread Ken Matsui via Gcc-patches
gcc/ada/ChangeLog:

* gcc-interface/trans.cc (return_slot_opt_for_pure_call_p): Use 
TYPE_REF_P.
* gcc-interface/utils2.cc (build_unary_op): Likewise.

gcc/ChangeLog:

* alias.cc (get_alias_set): Use TYPE_REF_P.
* config/gcn/gcn-tree.cc (gcn_goacc_get_worker_red_decl): Likewise.
* fold-const.cc (fold_unary_loc): Likewise.
* gimple.cc (gimple_call_nonnull_result_p): Likewise.
* gimplify.cc (gimplify_decl_expr): Likewise.
(omp_notice_variable): Likewise.
(omp_accumulate_sibling_list): Likewise.
(omp_build_struct_sibling_lists): Likewise.
(gimplify_scan_omp_clauses): Likewise.
(omp_shared_to_firstprivate_optimizable_decl_p): Likewise.
(gimplify_adjust_omp_clauses_1): Likewise.
(gimplify_omp_taskloop_expr): Likewise.
* ipa-free-lang-data.cc (find_decls_types_r): Likewise.
* ipa-sra.cc (create_parameter_descriptors): Likewise.
* langhooks.cc (lhd_omp_scalar_p): Likewise.
* match.pd: Likewise.
* omp-low.cc (scan_sharing_clauses): Likewise.
(lower_rec_input_clauses): Likewise.
(create_task_copyfn): Likewise.
(lower_omp_target): Likewise.
(lower_omp_1): Likewise.
* omp-simd-clone.cc (simd_clone_clauses_extract): Likewise.
(simd_clone_linear_addend): Likewise.
(simd_clone_adjust): Likewise.
* tree-inline.cc (remap_type_1): Likewise.
* tree.cc (reconstruct_complex_type): Likewise.
(verify_type_variant): Likewise.
(verify_type): Likewise.
(nonnull_arg_p): Likewise.
* tree.h (POINTER_TYPE_P): Likewise.
* var-tracking.cc (prepare_call_arguments): Likewise.
(vt_add_function_parameter): Likewise.

gcc/c-family/ChangeLog:

* c-attribs.cc (has_attribute): Use TYPE_REF_P.
* c-common.cc (c_common_truthvalue_conversion): Likewise.
(c_apply_type_quals_to_decl): Likewise.
* c-pretty-print.cc (c_pretty_printer::unary_expression): Likewise.
* c-ubsan.cc (ubsan_maybe_instrument_reference_or_call): Likewise.
* c-warn.cc (warn_if_unused_value): Likewise.

gcc/cp/ChangeLog:

* constexpr.cc (check_bit_cast_type): Use TYPE_REF_P.
* coroutines.cc (analyze_fn_parms): Likewise.
* decl.cc (finish_function): Likewise.
* init.cc (find_allocator_temps_r): Likewise.
* method.cc (early_check_defaulted_comparison): Likewise.
(build_comparison_op): Likewise.
* pt.cc (value_dependent_expression_p): Likewise.
* semantics.cc (cp_oacc_check_attachments): Likewise.
(finish_omp_target_clauses_r): Likewise.
(finish_omp_target_clauses): Likewise.

gcc/d/ChangeLog:

* d-builtins.cc (build_frontend_type): Use TYPE_REF_P.
* d-codegen.cc (indirect_ref): Likewise.
* d-convert.cc (d_truthvalue_conversion): Likewise.

gcc/fortran/ChangeLog:

* trans-array.cc (gfc_conv_descriptor_data_get): Use TYPE_REF_P.
(structure_alloc_comps): Likewise.
* trans-decl.cc (gfc_generate_function_code): Likewise.
* trans-expr.cc (gfc_conv_class_to_class): Likewise.
* trans-intrinsic.cc (gfc_conv_intrinsic_caf_get): Likewise.
(conv_caf_send): Likewise.
(trans_caf_is_present): Likewise.
(conv_intrinsic_atomic_op): Likewise.
(conv_intrinsic_atomic_ref): Likewise.
(conv_intrinsic_atomic_cas): Likewise.
* trans-openmp.cc (gfc_omp_privatize_by_reference): Likewise.
(gfc_omp_finish_clause): Likewise.
(gfc_omp_scalar_p): Likewise.
(gfc_trans_omp_array_reduction_or_udr): Likewise.
(gfc_trans_omp_clauses): Likewise.

gcc/lto/ChangeLog:

* lto-common.cc (lto_fixup_prevailing_type): Use TYPE_REF_P.

gcc/m2/ChangeLog:

* gm2-gcc/m2tree.cc (m2tree_skip_reference_type): Use TYPE_REF_P.
* gm2-gcc/m2treelib.cc (m2treelib_get_set_value): Likewise.
* m2pp.cc (m2pp_parameter): Likewise.
(m2pp_param_type): Likewise.

gcc/objc/ChangeLog:

* objc-act.cc: Use TYPE_REF_P.

Signed-off-by: Ken Matsui 
---
 gcc/ada/gcc-interface/trans.cc  |  2 +-
 gcc/ada/gcc-interface/utils2.cc |  2 +-
 gcc/alias.cc|  2 +-
 gcc/c-family/c-attribs.cc   |  2 +-
 gcc/c-family/c-common.cc|  7 +++
 gcc/c-family/c-pretty-print.cc  |  2 +-
 gcc/c-family/c-ubsan.cc |  4 ++--
 gcc/c-family/c-warn.cc  |  2 +-
 gcc/config/gcn/gcn-tree.cc  |  2 +-
 gcc/cp/constexpr.cc |  2 +-
 gcc/cp/coroutines.cc|  2 +-
 gcc/cp/decl.cc  |  2 +-
 gcc/cp/init.cc  |  2 +-
 gcc/cp/method.cc|  4 ++--
 gcc/cp/pt.cc|  2 +-
 gcc/cp/semantics.cc | 10 +-
 gcc/d/d-builtins.cc |  2 +-
 gcc/d/d-codegen.cc  |  2 +-
 gcc/d/d-convert.cc  |  4 ++--
 gcc/fold-const.cc   |  2 

[PATCH 3/8] c++, tree: Move TYPE_PTR_P to tree.h

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch moves TYPE_PTR_P from cp/cp-tree.h to tree.h to unify
POINTER_TYPE_P in tree.h to INDIRECT_TYPE_P in cp/cp-tree.h, which are
equivalent.

gcc/cp/ChangeLog:

* cp-tree.h (TYPE_PTR_P): Remove.

gcc/ChangeLog:

* tree.h (TYPE_PTR_P): Define.

Signed-off-by: Ken Matsui 
---
 gcc/cp/cp-tree.h | 4 
 gcc/tree.h   | 4 
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8c96d868650..681aa95e57f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4706,10 +4706,6 @@ get_vec_init_expr (tree t)
 #define TYPE_PTRDATAMEM_P(NODE)\
   (TREE_CODE (NODE) == OFFSET_TYPE)
 
-/* Returns true if NODE is a pointer.  */
-#define TYPE_PTR_P(NODE)   \
-  (TREE_CODE (NODE) == POINTER_TYPE)
-
 /* Returns true if NODE is a pointer or a reference.  */
 #define INDIRECT_TYPE_P(NODE)  \
   (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
diff --git a/gcc/tree.h b/gcc/tree.h
index d0d19153f91..48d57764d9c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -678,6 +678,10 @@ extern void omp_clause_range_check_failed (const_tree, 
const char *, int,
 #define AGGREGATE_TYPE_P(TYPE) \
   (TREE_CODE (TYPE) == ARRAY_TYPE || RECORD_OR_UNION_TYPE_P (TYPE))
 
+/* Nonzero if this type is a pointer.  */
+#define TYPE_PTR_P(NODE)   \
+  (TREE_CODE (NODE) == POINTER_TYPE)
+
 /* Nonzero if this type is a reference.  */
 #define TYPE_REF_P(NODE)   \
   (TREE_CODE (NODE) == REFERENCE_TYPE)
-- 
2.41.0



[PATCH 4/8] c++, tree: Move INDIRECT_TYPE_P to tree.h

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch moves INDIRECT_TYPE_P from cp/cp-tree.h to tree.h to unify
POINTER_TYPE_P in tree.h to INDIRECT_TYPE_P, which are equivalent.

gcc/cp/ChangeLog:

* cp-tree.h (INDIRECT_TYPE_P): Remove.

gcc/ChangeLog:

* tree.h (INDIRECT_TYPE_P): Define.

Signed-off-by: Ken Matsui 
---
 gcc/cp/cp-tree.h | 4 
 gcc/tree.h   | 5 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 681aa95e57f..5236b168ecc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4706,10 +4706,6 @@ get_vec_init_expr (tree t)
 #define TYPE_PTRDATAMEM_P(NODE)\
   (TREE_CODE (NODE) == OFFSET_TYPE)
 
-/* Returns true if NODE is a pointer or a reference.  */
-#define INDIRECT_TYPE_P(NODE)  \
-  (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
-
 /* Returns true if NODE is an object type:
 
  [basic.types]
diff --git a/gcc/tree.h b/gcc/tree.h
index 48d57764d9c..c369b8470ab 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -686,6 +686,11 @@ extern void omp_clause_range_check_failed (const_tree, 
const char *, int,
 #define TYPE_REF_P(NODE)   \
   (TREE_CODE (NODE) == REFERENCE_TYPE)
 
+/* Nonzero if TYPE represents a pointer or reference type.
+   Keep these checks in ascending code order.  */
+#define INDIRECT_TYPE_P(NODE)  \
+  (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
+
 /* Nonzero if TYPE represents a pointer or reference type.
(It should be renamed to INDIRECT_TYPE_P.)  Keep these checks in
ascending code order.  */
-- 
2.41.0



[PATCH 6/8] tree: Remove POINTER_TYPE_P

2023-07-18 Thread Ken Matsui via Gcc-patches
Since POINTER_TYPE_P was completely replaced by INDIRECT_TYPE_P, it can
be deleted.

gcc/ChangeLog:

* tree.h (POINTER_TYPE_P): Remove.

Signed-off-by: Ken Matsui 
---
 gcc/tree.h | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/gcc/tree.h b/gcc/tree.h
index d548dce63f7..347e676e737 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -691,13 +691,6 @@ extern void omp_clause_range_check_failed (const_tree, 
const char *, int,
 #define INDIRECT_TYPE_P(NODE)  \
   (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
 
-/* Nonzero if TYPE represents a pointer or reference type.
-   (It should be renamed to INDIRECT_TYPE_P.)  Keep these checks in
-   ascending code order.  */
-
-#define POINTER_TYPE_P(TYPE) \
-  (TREE_CODE (TYPE) == POINTER_TYPE || TYPE_REF_P (TYPE))
-
 /* Nonzero if TYPE represents a pointer to function.  */
 #define FUNCTION_POINTER_TYPE_P(TYPE) \
   (INDIRECT_TYPE_P (TYPE) && TREE_CODE (TREE_TYPE (TYPE)) == FUNCTION_TYPE)
-- 
2.41.0



[PATCH 7/8] tree: Define TYPE_REF_IS_LVALUE

2023-07-18 Thread Ken Matsui via Gcc-patches
This patch defines TYPE_REF_IS_LVALUE to determine if a type is a C++
lvalue reference.

gcc/ChangeLog:

* tree.h (TYPE_REF_IS_LVALUE): Define.

Signed-off-by: Ken Matsui 
---
 gcc/tree.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/tree.h b/gcc/tree.h
index 347e676e737..0b2cb894241 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1054,6 +1054,10 @@ extern void omp_clause_range_check_failed (const_tree, 
const char *, int,
 #define TYPE_REF_IS_RVALUE(NODE) \
   (REFERENCE_TYPE_CHECK (NODE)->base.private_flag)
 
+/* True if reference type NODE is a C++ lvalue reference.  */
+#define TYPE_REF_IS_LVALUE(NODE) \
+  (TYPE_REF_P (NODE) && !TYPE_REF_IS_RVALUE (NODE))
+
 /* Nonzero in a _DECL if the use of the name is defined as a
deprecated feature by __attribute__((deprecated)).  */
 #define TREE_DEPRECATED(NODE) \
-- 
2.41.0



[PATCH 8/8] c++, lto: Use TYPE_REF_IS_LVALUE

2023-07-18 Thread Ken Matsui via Gcc-patches
gcc/cp/ChangeLog:

* decl.cc (copy_fn_p): Use TYPE_REF_IS_LVALUE.
* init.cc (maybe_warn_list_ctor): Likewise.
* method.cc (early_check_defaulted_comparison): Likewise.
* pt.cc (maybe_adjust_types_for_deduction): Likewise.
(invalid_nontype_parm_type_p): Likewise.
* tree.cc (structural_type_p): Likewise.

gcc/lto/ChangeLog:

* lto-common.cc (lto_fixup_prevailing_type): Use
TYPE_REF_IS_LVALUE.

Signed-off-by: Ken Matsui 
---
 gcc/cp/decl.cc| 3 +--
 gcc/cp/init.cc| 3 +--
 gcc/cp/method.cc  | 3 +--
 gcc/cp/pt.cc  | 6 ++
 gcc/cp/tree.cc| 2 +-
 gcc/lto/lto-common.cc | 2 +-
 6 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index c08056ca3d2..5e84f6a6f78 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -15250,8 +15250,7 @@ copy_fn_p (const_tree d)
   /* Pass by value copy assignment operator.  */
   result = -1;
 }
-  else if (TYPE_REF_P (arg_type)
-  && !TYPE_REF_IS_RVALUE (arg_type)
+  else if (TYPE_REF_IS_LVALUE (arg_type)
   && TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
 {
   if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 01eb4b55889..8006576bfd6 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -778,8 +778,7 @@ maybe_warn_list_ctor (tree member, tree init)
   tree initlist = non_reference (parm);
 
   /* Do not warn if the parameter is an lvalue reference to non-const.  */
-  if (TYPE_REF_P (parm) && !TYPE_REF_IS_RVALUE (parm)
-  && !CP_TYPE_CONST_P (initlist))
+  if (TYPE_REF_IS_LVALUE (parm) && !CP_TYPE_CONST_P (initlist))
 return;
 
   tree targs = CLASSTYPE_TI_ARGS (initlist);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 524efc4e260..59be43d12c6 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1207,8 +1207,7 @@ early_check_defaulted_comparison (tree fn)
   tree parmtype = TREE_VALUE (parmnode);
   if (CLASS_TYPE_P (parmtype))
saw_byval = true;
-  else if (TYPE_REF_P (parmtype)
-  && !TYPE_REF_IS_RVALUE (parmtype)
+  else if (TYPE_REF_IS_LVALUE (parmtype)
   && TYPE_QUALS (TREE_TYPE (parmtype)) == TYPE_QUAL_CONST)
{
  saw_byref = true;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index cb82e1b268b..56207411a7d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -22772,8 +22772,7 @@ maybe_adjust_types_for_deduction (tree tparms,
 too, but here handle it by stripping the reference from PARM
 rather than by adding it to ARG.  */
   if (forwarding_reference_p (*parm, TPARMS_PRIMARY_TEMPLATE (tparms))
- && TYPE_REF_P (*arg)
- && !TYPE_REF_IS_RVALUE (*arg))
+ && TYPE_REF_IS_LVALUE (*arg))
*parm = TREE_TYPE (*parm);
   /* Nothing else to do in this case.  */
   return 0;
@@ -27595,8 +27594,7 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t 
complain)
 return false;
   else if (TYPE_PTR_P (type))
 return false;
-  else if (TYPE_REF_P (type)
-  && !TYPE_REF_IS_RVALUE (type))
+  else if (TYPE_REF_IS_LVALUE (type))
 return false;
   else if (TYPE_PTRMEM_P (type))
 return false;
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 799183dc646..1ba7539b497 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -4928,7 +4928,7 @@ structural_type_p (tree t, bool explain)
   if (SCALAR_TYPE_P (t))
 return true;
   /* an lvalue reference type, or */
-  if (TYPE_REF_P (t) && !TYPE_REF_IS_RVALUE (t))
+  if (TYPE_REF_IS_LVALUE (t))
 return true;
   /* a literal class type with the following properties:
  - all base classes and non-static data members are public and non-mutable
diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc
index 4b748ced87f..6321a70d04a 100644
--- a/gcc/lto/lto-common.cc
+++ b/gcc/lto/lto-common.cc
@@ -998,7 +998,7 @@ lto_fixup_prevailing_type (tree t)
  TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
  TYPE_POINTER_TO (TREE_TYPE (t)) = t;
}
-  else if (TYPE_REF_P (t) && !TYPE_REF_IS_RVALUE (t))
+  else if (TYPE_REF_IS_LVALUE (t))
{
  TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
  TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
-- 
2.41.0



Re: [PATCH 0/8] Tweak predicate macros in tree

2023-07-19 Thread Ken Matsui via Gcc-patches
On Wed, Jul 19, 2023 at 12:08 AM Richard Biener
 wrote:
>
> On Wed, Jul 19, 2023 at 1:34 AM Ken Matsui via Gcc-patches
>  wrote:
> >
> > This patch series tweaks predicate macros in tree.h to make the code more
> > readable. TYPE_REF_P is moved to tree.h and used for INDIRECT_TYPE_P and
> > TYPE_REF_IS_LVALUE. TYPE_PTR_P is also moved to tree.h and used for
> > INDIRECT_TYPE_P. POINTER_TYPE_P in tree.h is replaced with INDIRECT_TYPE_P
> > since it is ambiguous. TYPE_REF_IS_LVALUE is defined in tree.h through
> > TYPE_REF_P and TYPE_REF_IS_RVALUE. The same behavior codes with those
> > predicate macros are replaced for clarity.
> >
> > These works were all the way up to implementing __is_lvalue_reference
> > built-in trait and optimizing the is_lvalue_reference trait. However, those
> > changes were dropped since I did not observe any performance improvements.
> > For those who are interested in the benchmark results, they can be found
> > below:
> >
> > 1. is_lvalue_reference
> >
> > https://github.com/ken-matsui/gcc-benches/blob/main/is_lvalue_reference.md#tue-jul-18-033708-pm-pdt-2023
> >
> > Time: +1.35432%
> > Peak Memory Usage: -0.103283%
> > Total Memory Usage: No difference
> >
> > 2. is_lvalue_reference_v
> >
> > https://github.com/ken-matsui/gcc-benches/blob/main/is_lvalue_reference_v.md#tue-jul-18-034236-pm-pdt-2023
> >
> > Time: No difference
> > Peak Memory Usage: -0.426872%
> > Total Memory Usage: -0.677638%
> >
> > Ken Matsui (8):
> >   c++, tree: Move TYPE_REF_P to tree.h
> >   gcc: Use TYPE_REF_P
> >   c++, tree: Move TYPE_PTR_P to tree.h
> >   c++, tree: Move INDIRECT_TYPE_P to tree.h
> >   gcc: Use INDIRECT_TYPE_P instead of POINTER_TYPE_P
>
> No, please not.  Definitely not.  The tree code of POINTER_TYPE_P is
> POINTER_TYPE so the predicate name is exactly correct.
> REFERENCE_TYPE_P would be the canonical predicate for REFERENCE_TYPE,
> not TYPE_REF_P.
>
> I don't think the C++ frontend should be the one to decide about middle-end
> tree predicate macros.
>

Hi Richard,

Thank you for your review! This is because of the comment, which
states that POINTER_TYPE_P should be renamed to INDIRECT_TYPE_P.

  /* Nonzero if TYPE represents a pointer or reference type.
 (It should be renamed to INDIRECT_TYPE_P.)  Keep these checks in
 ascending code order.  */

  #define POINTER_TYPE_P(TYPE) \
(TREE_CODE (TYPE) == POINTER_TYPE || TYPE_REF_P (TYPE))

Also, INDIRECT_TYPE_P is equivalent to POINTER_TYPE_P.

  #define INDIRECT_TYPE_P(NODE)  \
(TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))

  #define TYPE_PTR_P(NODE)   \
(TREE_CODE (NODE) == POINTER_TYPE)

IMHO, POINTER_TYPE_P and TYPE_PTR_P are confusing since POINTER_TYPE_P
involves TYPE_REF_P but TYPE_PTR_P does not. If this renaming is still
incorrect, I think we should at least remove the comment in
POINTER_TYPE_P. Could you please confirm whether or not this patch is
correct? Thank you!

Sincerely,
Ken

> >   tree: Remove POINTER_TYPE_P
> >   tree: Define TYPE_REF_IS_LVALUE
> >   c++, lto: Use TYPE_REF_IS_LVALUE
> >
> >  gcc/ada/gcc-interface/ada-tree.h   |   2 +-
> >  gcc/ada/gcc-interface/decl.cc  |   6 +-
> >  gcc/ada/gcc-interface/trans.cc |  16 +--
> >  gcc/ada/gcc-interface/utils.cc |  12 +-
> >  gcc/ada/gcc-interface/utils2.cc|  14 +-
> >  gcc/alias.cc   |  12 +-
> >  gcc/analyzer/analyzer.cc   |   4 +-
> >  gcc/analyzer/call-details.h|   2 +-
> >  gcc/analyzer/call-summary.cc   |   2 +-
> >  gcc/analyzer/checker-event.cc  |   4 +-
> >  gcc/analyzer/constraint-manager.cc |   2 +-
> >  gcc/analyzer/engine.cc |   4 +-
> >  gcc/analyzer/program-state.cc  |   2 +-
> >  gcc/analyzer/region-model-manager.cc   |   6 +-
> >  gcc/analyzer/region-model.cc   |   6 +-
> >  gcc/analyzer/sm.cc |   4 +-
> >  gcc/analyzer/svalue.cc |   2 +-
> >  gcc/analyzer/varargs.cc|   2 +-
> >  gcc/asan.cc|   4 +-
> >  gcc/builtins.cc|  24 ++--
> >  gcc/c-family/c-ada-spec.cc |   2 +-
> >  gcc/c-family/c-attribs.cc  |  32 ++---
> >  gcc/c-family/c-common.cc   |  41 +++---
> >  gcc/c-family/c-omp.cc  |   8 +-
> >  gcc/c-family/c-pretty-print.cc |   4 +-
> >  gcc/c-family/c-ubsan.cc

Re: [PATCH] libstdc++: Define _GLIBCXX_HAS_BUILTIN_TRAIT

2023-07-19 Thread Ken Matsui via Gcc-patches
On Wed, Jul 19, 2023 at 11:48 AM Patrick Palka  wrote:
>
> On Tue, 18 Jul 2023, Ken Matsui via Libstdc++ wrote:
>
> > This patch defines _GLIBCXX_HAS_BUILTIN_TRAIT, which will be used as a
> > flag to toggle built-in traits in the type_traits header. Through this
> > macro function and _GLIBCXX_NO_BUILTIN_TRAITS macro, we can switch the
> > use of built-in traits without needing to modify the source code.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/bits/c++config (_GLIBCXX_HAS_BUILTIN_TRAIT): Define.
>
> The ChangeLog entry should also mention the change to _GLIBCXX_HAS_BUILTIN,
> e.g.
>
> (_GLIBCXX_HAS_BUILTIN): Keep defined.
>
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >  libstdc++-v3/include/bits/c++config | 6 +-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > diff --git a/libstdc++-v3/include/bits/c++config 
> > b/libstdc++-v3/include/bits/c++config
> > index dd47f274d5f..de13f61db71 100644
> > --- a/libstdc++-v3/include/bits/c++config
> > +++ b/libstdc++-v3/include/bits/c++config
> > @@ -854,7 +854,11 @@ namespace __gnu_cxx
> >  # define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1
> >  #endif
> >
> > -#undef _GLIBCXX_HAS_BUILTIN
> > +// Returns true if _GLIBCXX_NO_BUILTIN_TRAITS is not defined and the 
> > compiler
> > +// has a corresponding built-in type trait. _GLIBCXX_NO_BUILTIN_TRAITS is
> > +// defined to disable the use of built-in traits.
> > +#define _GLIBCXX_HAS_BUILTIN_TRAIT(BT)  \
> > +  (!defined(_GLIBCXX_NO_BUILTIN_TRAITS) && _GLIBCXX_HAS_BUILTIN(BT))
>
> Since we don't expect _GLIBCXX_NO_BUILTIN_TRAITS to get
> defined/undefined in the middle of preprocessing, perhaps we should
> factor out the _GLIBCXX_NO_BUILTIN_TRAITS test from the macro function
> and instead conditionally define the macro function to 0 according
> _GLIBCXX_NO_BUILTIN_TRAITS?
>
Hi, thank you for your review! I totally agree with your ideas and
will update this patch.

> >
> >  // Mark code that should be ignored by the compiler, but seen by Doxygen.
> >  #define _GLIBCXX_DOXYGEN_ONLY(X)
> > --
> > 2.41.0
> >
> >
>


[PATCH v2] libstdc++: Define _GLIBCXX_HAS_BUILTIN_TRAIT

2023-07-19 Thread Ken Matsui via Gcc-patches
This patch defines _GLIBCXX_HAS_BUILTIN_TRAIT macro, which will be used
as a flag to toggle the use of built-in traits in the type_traits header
through _GLIBCXX_NO_BUILTIN_TRAITS macro, without needing to modify the
source code.

libstdc++-v3/ChangeLog:

* include/bits/c++config (_GLIBCXX_HAS_BUILTIN_TRAIT): Define.
(_GLIBCXX_HAS_BUILTIN): Keep defined.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/c++config | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index dd47f274d5f..984985d6fff 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -854,7 +854,15 @@ namespace __gnu_cxx
 # define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1
 #endif
 
-#undef _GLIBCXX_HAS_BUILTIN
+// Returns 1 if _GLIBCXX_NO_BUILTIN_TRAITS is not defined and the compiler
+// has a corresponding built-in type trait, 0 otherwise.
+// _GLIBCXX_NO_BUILTIN_TRAITS can be defined to disable the use of built-in
+// traits.
+#ifndef _GLIBCXX_NO_BUILTIN_TRAITS
+# define _GLIBCXX_HAS_BUILTIN_TRAIT(BT) _GLIBCXX_HAS_BUILTIN(BT)
+#else
+# define _GLIBCXX_HAS_BUILTIN_TRAIT(BT) 0
+#endif
 
 // Mark code that should be ignored by the compiler, but seen by Doxygen.
 #define _GLIBCXX_DOXYGEN_ONLY(X)
-- 
2.41.0



[PATCH v3 1/2] libstdc++: Define _GLIBCXX_HAS_BUILTIN_TRAIT

2023-07-27 Thread Ken Matsui via Gcc-patches
This patch defines _GLIBCXX_HAS_BUILTIN_TRAIT macro, which will be used
as a flag to toggle the use of built-in traits in the type_traits header
through _GLIBCXX_NO_BUILTIN_TRAITS macro, without needing to modify the
source code.

libstdc++-v3/ChangeLog:

* include/bits/c++config (_GLIBCXX_HAS_BUILTIN_TRAIT): Define.
(_GLIBCXX_HAS_BUILTIN): Keep defined.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/c++config | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index dd47f274d5f..984985d6fff 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -854,7 +854,15 @@ namespace __gnu_cxx
 # define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1
 #endif
 
-#undef _GLIBCXX_HAS_BUILTIN
+// Returns 1 if _GLIBCXX_NO_BUILTIN_TRAITS is not defined and the compiler
+// has a corresponding built-in type trait, 0 otherwise.
+// _GLIBCXX_NO_BUILTIN_TRAITS can be defined to disable the use of built-in
+// traits.
+#ifndef _GLIBCXX_NO_BUILTIN_TRAITS
+# define _GLIBCXX_HAS_BUILTIN_TRAIT(BT) _GLIBCXX_HAS_BUILTIN(BT)
+#else
+# define _GLIBCXX_HAS_BUILTIN_TRAIT(BT) 0
+#endif
 
 // Mark code that should be ignored by the compiler, but seen by Doxygen.
 #define _GLIBCXX_DOXYGEN_ONLY(X)
-- 
2.41.0



[PATCH v3 2/2] libstdc++: Use _GLIBCXX_HAS_BUILTIN_TRAIT

2023-07-27 Thread Ken Matsui via Gcc-patches
This patch uses _GLIBCXX_HAS_BUILTIN_TRAIT macro instead of
__has_builtin in the type_traits header. This macro supports to toggle
the use of built-in traits in the type_traits header through
_GLIBCXX_NO_BUILTIN_TRAITS macro, without needing to modify the
source code.

libstdc++-v3/ChangeLog:

* include/std/type_traits (__has_builtin): Replace with ...
(_GLIBCXX_HAS_BUILTIN): ... this.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 9f086992ebc..12423361b6e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1411,7 +1411,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __bool_constant<__is_base_of(_Base, _Derived)>
 { };
 
-#if __has_builtin(__is_convertible)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__is_convertible)
   template
 struct is_convertible
 : public __bool_constant<__is_convertible(_From, _To)>
@@ -1462,7 +1462,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 202002L
 #define __cpp_lib_is_nothrow_convertible 201806L
 
-#if __has_builtin(__is_nothrow_convertible)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__is_nothrow_convertible)
   /// is_nothrow_convertible_v
   template
 inline constexpr bool is_nothrow_convertible_v
@@ -1537,7 +1537,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { using type = _Tp; };
 
   /// remove_cv
-#if __has_builtin(__remove_cv)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__remove_cv)
   template
 struct remove_cv
 { using type = __remove_cv(_Tp); };
@@ -1606,7 +1606,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Reference transformations.
 
   /// remove_reference
-#if __has_builtin(__remove_reference)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__remove_reference)
   template
 struct remove_reference
 { using type = __remove_reference(_Tp); };
@@ -2963,7 +2963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template(_S_get())),
   typename = decltype(_S_conv<_Tp>(_S_get())),
-#if __has_builtin(__reference_converts_from_temporary)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__reference_converts_from_temporary)
   bool _Dangle = __reference_converts_from_temporary(_Tp, _Res_t)
 #else
   bool _Dangle = false
@@ -3420,7 +3420,7 @@ template
*/
 #define __cpp_lib_remove_cvref 201711L
 
-#if __has_builtin(__remove_cvref)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__remove_cvref)
   template
 struct remove_cvref
 { using type = __remove_cvref(_Tp); };
@@ -3515,7 +3515,7 @@ template
 : public bool_constant>
 { };
 
-#if __has_builtin(__is_layout_compatible)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__is_layout_compatible)
 
   /// @since C++20
   template
@@ -3529,7 +3529,7 @@ template
 constexpr bool is_layout_compatible_v
   = __is_layout_compatible(_Tp, _Up);
 
-#if __has_builtin(__builtin_is_corresponding_member)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__builtin_is_corresponding_member)
 #define __cpp_lib_is_layout_compatible 201907L
 
   /// @since C++20
@@ -3540,7 +3540,7 @@ template
 #endif
 #endif
 
-#if __has_builtin(__is_pointer_interconvertible_base_of)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__is_pointer_interconvertible_base_of)
   /// True if `_Derived` is standard-layout and has a base class of type 
`_Base`
   /// @since C++20
   template
@@ -3554,7 +3554,7 @@ template
 constexpr bool is_pointer_interconvertible_base_of_v
   = __is_pointer_interconvertible_base_of(_Base, _Derived);
 
-#if __has_builtin(__builtin_is_pointer_interconvertible_with_class)
+#if 
_GLIBCXX_HAS_BUILTIN_TRAIT(__builtin_is_pointer_interconvertible_with_class)
 #define __cpp_lib_is_pointer_interconvertible 201907L
 
   /// True if `__mp` points to the first member of a standard-layout type
@@ -3590,8 +3590,8 @@ template
   template
 inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value;
 
-#if __has_builtin(__reference_constructs_from_temporary) \
-  && __has_builtin(__reference_converts_from_temporary)
+#if _GLIBCXX_HAS_BUILTIN_TRAIT(__reference_constructs_from_temporary) \
+  && _GLIBCXX_HAS_BUILTIN_TRAIT(__reference_converts_from_temporary)
 
 #define __cpp_lib_reference_from_temporary 202202L
 
@@ -3632,7 +3632,7 @@ template
   template
 inline constexpr bool reference_converts_from_temporary_v
   = reference_converts_from_temporary<_Tp, _Up>::value;
-#endif // __has_builtin for reference_from_temporary
+#endif // _GLIBCXX_HAS_BUILTIN_TRAIT for reference_from_temporary
 #endif // C++23
 
 #if _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED
-- 
2.41.0



Re: [PATCH 1/2] c++: implement __remove_pointer built-in trait

2023-06-17 Thread Ken Matsui via Gcc-patches
Hi,

I conducted a benchmark for remove_pointer as well as is_object. Just
like the is_object benchmark, here is the benchmark code:

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

On my computer, using the gcc HEAD of this patch for a release build,
the patch with -DUSE_BUILTIN took 8.7% less time and used 4.3-4.9%
less memory on average compared to not using it. Although the
performance improvement was not as significant as with is_object, the
benchmark demonstrated that the compilation was consistently more
efficient.

Sincerely,
Ken Matsui

On Thu, Jun 15, 2023 at 5:22 AM Ken Matsui  wrote:
>
> This patch implements built-in trait for std::remove_pointer.
>
> gcc/cp/ChangeLog:
>
> * cp-trait.def: Define __remove_pointer.
> * semantics.cc (finish_trait_type): Handle CPTK_REMOVE_POINTER.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/ext/has-builtin-1.C: Test existence of __remove_pointer.
> * g++.dg/ext/remove_pointer.C: New test.
>
> Signed-off-by: Ken Matsui 
> ---
>  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/remove_pointer.C | 51 +++
>  4 files changed, 59 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/ext/remove_pointer.C
>
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 8b7fece0cc8..07823e55579 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -90,6 +90,7 @@ DEFTRAIT_EXPR (IS_DEDUCIBLE, "__is_deducible ", 2)
>  DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
>  DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
>  DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
> +DEFTRAIT_TYPE (REMOVE_POINTER, "__remove_pointer", 1)
>  DEFTRAIT_TYPE (UNDERLYING_TYPE,  "__underlying_type", 1)
>  DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
>
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 8fb47fd179e..885c7a6fb64 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12373,6 +12373,10 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
> tree type2,
>if (TYPE_REF_P (type1))
> type1 = TREE_TYPE (type1);
>return cv_unqualified (type1);
> +case CPTK_REMOVE_POINTER:
> +  if (TYPE_PTR_P (type1))
> +type1 = TREE_TYPE (type1);
> +  return type1;
>
>  case CPTK_TYPE_PACK_ELEMENT:
>return finish_type_pack_element (type1, type2, complain);
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
> b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index f343e153e56..e21e0a95509 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 (__remove_pointer)
> +# error "__has_builtin (__remove_pointer) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/remove_pointer.C 
> b/gcc/testsuite/g++.dg/ext/remove_pointer.C
> new file mode 100644
> index 000..7b13db93950
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/remove_pointer.C
> @@ -0,0 +1,51 @@
> +// { dg-do compile { target c++11 } }
> +
> +#define SA(X) static_assert((X),#X)
> +
> +SA(__is_same(__remove_pointer(int), int));
> +SA(__is_same(__remove_pointer(int*), int));
> +SA(__is_same(__remove_pointer(int**), int*));
> +
> +SA(__is_same(__remove_pointer(const int*), const int));
> +SA(__is_same(__remove_pointer(const int**), const int*));
> +SA(__is_same(__remove_pointer(int* const), int));
> +SA(__is_same(__remove_pointer(int** const), int*));
> +SA(__is_same(__remove_pointer(int* const* const), int* const));
> +
> +SA(__is_same(__remove_pointer(volatile int*), volatile int));
> +SA(__is_same(__remove_pointer(volatile int**), volatile int*));
> +SA(__is_same(__remove_pointer(int* volatile), int));
> +SA(__is_same(__remove_pointer(int** volatile), int*));
> +SA(__is_same(__remove_pointer(int* volatile* volatile), int* volatile));
> +
> +SA(__is_same(__remove_pointer(const volatile int*), const volatile int));
> +SA(__is_same(__remove_pointer(const volatile int**), const volatile int*));
> +SA(__is_same(__remove_pointer(const int* volatile), const int));
> +SA(__is_same(__remove_pointer(volatile int* const), volatile int));
> +SA(__is_same(__remove_pointer(int* const volatile), int));
> +SA(__is_same(__remove_pointer(const int** volatile), const int*));
> +SA(__is_same(__remove_pointer(volatile int** const), volatile int*));
> +SA(__is_same(__remove_pointer(int** const volatile), int*));
> +SA(__is_same(__remove_pointer(int* const* const volatile), int* const));
> +SA(__is_same(__remove_pointer(int* volatile* const volatile), int* 
> volatile));
> +SA(__is_same(__remove_pointer(int* const volatile* const volatile), int* 
> const volatile));
> +
> +SA(__is_same(__remove_pointer(int&), int&));
> +SA(__is_same(__remo

Re: [PATCH v7 0/6] c++, libstdc++: get std::is_object to dispatch to new built-in traits

2023-06-20 Thread Ken Matsui via Gcc-patches
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  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  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_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_void(_Tp))>
> >
> > This would instantiate only __bool_constant and 
> > __bool_constant,
> > 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
> >


Re: [PATCH 1/2] c++: implement __remove_pointer built-in trait

2023-06-20 Thread Ken Matsui via Gcc-patches
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/remove_pointer.cc.
I have also created a report file which can be found at
https://github.com/ken-matsui/gcc-benches/blob/main/remove_pointer.md.

On Sat, Jun 17, 2023 at 5:35 AM Ken Matsui  wrote:
>
> Hi,
>
> I conducted a benchmark for remove_pointer as well as is_object. Just
> like the is_object benchmark, here is the benchmark code:
>
> https://github.com/ken-matsui/gcc-benches/blob/main/remove_pointer_benchmark.cc
>
> On my computer, using the gcc HEAD of this patch for a release build,
> the patch with -DUSE_BUILTIN took 8.7% less time and used 4.3-4.9%
> less memory on average compared to not using it. Although the
> performance improvement was not as significant as with is_object, the
> benchmark demonstrated that the compilation was consistently more
> efficient.
>
> Sincerely,
> Ken Matsui
>
> On Thu, Jun 15, 2023 at 5:22 AM Ken Matsui  wrote:
> >
> > This patch implements built-in trait for std::remove_pointer.
> >
> > gcc/cp/ChangeLog:
> >
> > * cp-trait.def: Define __remove_pointer.
> > * semantics.cc (finish_trait_type): Handle CPTK_REMOVE_POINTER.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/ext/has-builtin-1.C: Test existence of __remove_pointer.
> > * g++.dg/ext/remove_pointer.C: New test.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >  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/remove_pointer.C | 51 +++
> >  4 files changed, 59 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/ext/remove_pointer.C
> >
> > diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> > index 8b7fece0cc8..07823e55579 100644
> > --- a/gcc/cp/cp-trait.def
> > +++ b/gcc/cp/cp-trait.def
> > @@ -90,6 +90,7 @@ DEFTRAIT_EXPR (IS_DEDUCIBLE, "__is_deducible ", 2)
> >  DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
> >  DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
> >  DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
> > +DEFTRAIT_TYPE (REMOVE_POINTER, "__remove_pointer", 1)
> >  DEFTRAIT_TYPE (UNDERLYING_TYPE,  "__underlying_type", 1)
> >  DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
> >
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 8fb47fd179e..885c7a6fb64 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -12373,6 +12373,10 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
> > tree type2,
> >if (TYPE_REF_P (type1))
> > type1 = TREE_TYPE (type1);
> >return cv_unqualified (type1);
> > +case CPTK_REMOVE_POINTER:
> > +  if (TYPE_PTR_P (type1))
> > +type1 = TREE_TYPE (type1);
> > +  return type1;
> >
> >  case CPTK_TYPE_PACK_ELEMENT:
> >return finish_type_pack_element (type1, type2, complain);
> > diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
> > b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> > index f343e153e56..e21e0a95509 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 (__remove_pointer)
> > +# error "__has_builtin (__remove_pointer) failed"
> > +#endif
> > diff --git a/gcc/testsuite/g++.dg/ext/remove_pointer.C 
> > b/gcc/testsuite/g++.dg/ext/remove_pointer.C
> > new file mode 100644
> > index 000..7b13db93950
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/ext/remove_pointer.C
> > @@ -0,0 +1,51 @@
> > +// { dg-do compile { target c++11 } }
> > +
> > +#define SA(X) static_assert((X),#X)
> > +
> > +SA(__is_same(__remove_pointer(int), int));
> > +SA(__is_same(__remove_pointer(int*), int));
> > +SA(__is_same(__remove_pointer(int**), int*));
> > +
> > +SA(__is_same(__remove_pointer(const int*), const int));
> > +SA(__is_same(__remove_pointer(const int**), const int*));
> > +SA(__is_same(__remove_pointer(int* const), int));
> > +SA(__is_same(__remove_pointer(int** const), int*));
> > +SA(__is_same(__remove_pointer(int* const* const), int* const));
> > +
> > +SA(__is_same(__remove_pointer(volatile int*), volatile int));
> > +SA(__is_same(__remove_pointer(volatile int**), volatile int*));
> > +SA(__is_same(__remove_pointer(int* volatile), int));
> > +SA(__is_same(__remove_pointer(int** volatile), int*));
> > +SA(__is_same(__remove_pointer(int* volatile* volatile), int* volatile));
> > +
> > +SA(__is_same(__remove_pointer(const volatile int*), const volatile int));
> > +SA(__is_same(__remove_pointer(const volatile int**), const volatile int*));
> > +SA(__is_same(__remove_pointer(const int* volatile), const int));
> > +SA(__is_same(__remove_pointer(volatile int* const), volatile int));
> > +SA(__is_same(__remove_pointer(int* con

Re: [PATCH 1/2] c++: implement __remove_pointer built-in trait

2023-06-24 Thread Ken Matsui via Gcc-patches
On Tue, Jun 20, 2023 at 8:22 AM Patrick Palka  wrote:
>
> On Sat, 17 Jun 2023, Ken Matsui via Gcc-patches wrote:
>
> > Hi,
> >
> > I conducted a benchmark for remove_pointer as well as is_object. Just
> > like the is_object benchmark, here is the benchmark code:
> >
> > https://github.com/ken-matsui/gcc-benches/blob/main/remove_pointer_benchmark.cc
> >
> > On my computer, using the gcc HEAD of this patch for a release build,
> > the patch with -DUSE_BUILTIN took 8.7% less time and used 4.3-4.9%
> > less memory on average compared to not using it. Although the
> > performance improvement was not as significant as with is_object, the
> > benchmark demonstrated that the compilation was consistently more
> > efficient.
>
> Thanks for the benchmark.  The improvement is lesser than I expected,
> but that might be because the benchmark is "biased":
>
>   template 
>   struct Instantiator : Instantiator {
>   static_assert(!std::is_pointer_v>);
>   };
>
> This only invokes remove_pointer_t on the non-pointer type Instantiator,
> and so the benchmark doesn't factor in the performance of the trait when
> invoked on pointer types, and traits typically will have different
> performance characteristics depending on the kind of type it's given.
>
> To more holistically assess the real-world performance of the trait the
> benchmark should also consider pointer types and maybe also cv-qualified
> types (given that the original implementation is in terms of
> __remove_cv_t and thus performance of the original implementation may be
> sensitive to cv-qualification).  So we should probably uniformly
> benchmark these classes of types, via doing e.g.:
>
>   static_assert(!std::is_pointer_v>);
>   static_assert(!std::is_pointer_v>);
>   static_assert(!std::is_pointer_v>);
>   static_assert(!std::is_pointer_v>);
>
> (We could consider other kinds of types too, e.g. reference types and
> integral types, but it seems clear based on the implementations being
> benchmarked that performance won't be sensitive to reference-ness
> or integral-ness.)

Thank you for your review! I totally agree with your opinion that the
benchmark should have been exhaustive. I conducted a benchmark for
this new change:

https://github.com/ken-matsui/gcc-benches/blob/main/remove_pointer.md#tue-jun-20-030313-pm-pdt-2023

Time: -27.918%
Peak Memory Usage: -19.0755%
Total Memory Usage: -20.0199%

> >
> > Sincerely,
> > Ken Matsui
> >
> > On Thu, Jun 15, 2023 at 5:22 AM Ken Matsui  
> > wrote:
> > >
> > > This patch implements built-in trait for std::remove_pointer.
> > >
> > > gcc/cp/ChangeLog:
> > >
> > > * cp-trait.def: Define __remove_pointer.
> > > * semantics.cc (finish_trait_type): Handle CPTK_REMOVE_POINTER.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * g++.dg/ext/has-builtin-1.C: Test existence of __remove_pointer.
> > > * g++.dg/ext/remove_pointer.C: New test.
> > >
> > > Signed-off-by: Ken Matsui 
> > > ---
> > >  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/remove_pointer.C | 51 +++
> > >  4 files changed, 59 insertions(+)
> > >  create mode 100644 gcc/testsuite/g++.dg/ext/remove_pointer.C
> > >
> > > diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> > > index 8b7fece0cc8..07823e55579 100644
> > > --- a/gcc/cp/cp-trait.def
> > > +++ b/gcc/cp/cp-trait.def
> > > @@ -90,6 +90,7 @@ DEFTRAIT_EXPR (IS_DEDUCIBLE, "__is_deducible ", 2)
> > >  DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
> > >  DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
> > >  DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
> > > +DEFTRAIT_TYPE (REMOVE_POINTER, "__remove_pointer", 1)
> > >  DEFTRAIT_TYPE (UNDERLYING_TYPE,  "__underlying_type", 1)
> > >  DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
> > >
> > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > > index 8fb47fd179e..885c7a6fb64 100644
> > > --- a/gcc/cp/semantics.cc
> > > +++ b/gcc/cp/semantics.cc
> > > @@ -12373,6 +12373,10 @@ finish_trait_type (cp_trait_kind kind, tree 
> > > type1, tree type2,
> > >if (TYPE_REF_P (type1))
> > > type1 = TREE_TYPE (type1);

[PATCH 1/2] c++: implement __remove_pointer built-in trait

2023-06-24 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::remove_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __remove_pointer.
* semantics.cc (finish_trait_type): Handle CPTK_REMOVE_POINTER.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/cp-trait.def   |  1 +
 gcc/cp/semantics.cc   |  5 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  |  3 ++
 gcc/testsuite/g++.dg/ext/remove_pointer.C | 51 +++
 4 files changed, 60 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/remove_pointer.C

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..07823e55579 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -90,6 +90,7 @@ DEFTRAIT_EXPR (IS_DEDUCIBLE, "__is_deducible ", 2)
 DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
 DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
 DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
+DEFTRAIT_TYPE (REMOVE_POINTER, "__remove_pointer", 1)
 DEFTRAIT_TYPE (UNDERLYING_TYPE,  "__underlying_type", 1)
 DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
 
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..a3b283ce938 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12374,6 +12374,11 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
type1 = TREE_TYPE (type1);
   return cv_unqualified (type1);
 
+case CPTK_REMOVE_POINTER:
+  if (TYPE_PTR_P (type1))
+type1 = TREE_TYPE (type1);
+  return type1;
+
 case CPTK_TYPE_PACK_ELEMENT:
   return finish_type_pack_element (type1, type2, complain);
 
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..e21e0a95509 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 (__remove_pointer)
+# error "__has_builtin (__remove_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/remove_pointer.C 
b/gcc/testsuite/g++.dg/ext/remove_pointer.C
new file mode 100644
index 000..7b13db93950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/remove_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(__is_same(__remove_pointer(int), int));
+SA(__is_same(__remove_pointer(int*), int));
+SA(__is_same(__remove_pointer(int**), int*));
+
+SA(__is_same(__remove_pointer(const int*), const int));
+SA(__is_same(__remove_pointer(const int**), const int*));
+SA(__is_same(__remove_pointer(int* const), int));
+SA(__is_same(__remove_pointer(int** const), int*));
+SA(__is_same(__remove_pointer(int* const* const), int* const));
+
+SA(__is_same(__remove_pointer(volatile int*), volatile int));
+SA(__is_same(__remove_pointer(volatile int**), volatile int*));
+SA(__is_same(__remove_pointer(int* volatile), int));
+SA(__is_same(__remove_pointer(int** volatile), int*));
+SA(__is_same(__remove_pointer(int* volatile* volatile), int* volatile));
+
+SA(__is_same(__remove_pointer(const volatile int*), const volatile int));
+SA(__is_same(__remove_pointer(const volatile int**), const volatile int*));
+SA(__is_same(__remove_pointer(const int* volatile), const int));
+SA(__is_same(__remove_pointer(volatile int* const), volatile int));
+SA(__is_same(__remove_pointer(int* const volatile), int));
+SA(__is_same(__remove_pointer(const int** volatile), const int*));
+SA(__is_same(__remove_pointer(volatile int** const), volatile int*));
+SA(__is_same(__remove_pointer(int** const volatile), int*));
+SA(__is_same(__remove_pointer(int* const* const volatile), int* const));
+SA(__is_same(__remove_pointer(int* volatile* const volatile), int* volatile));
+SA(__is_same(__remove_pointer(int* const volatile* const volatile), int* const 
volatile));
+
+SA(__is_same(__remove_pointer(int&), int&));
+SA(__is_same(__remove_pointer(const int&), const int&));
+SA(__is_same(__remove_pointer(volatile int&), volatile int&));
+SA(__is_same(__remove_pointer(const volatile int&), const volatile int&));
+
+SA(__is_same(__remove_pointer(int&&), int&&));
+SA(__is_same(__remove_pointer(const int&&), const int&&));
+SA(__is_same(__remove_pointer(volatile int&&), volatile int&&));
+SA(__is_same(__remove_pointer(const volatile int&&), const volatile int&&));
+
+SA(__is_same(__remove_pointer(int[3]), int[3]));
+SA(__is_same(__remove_pointer(const int[3]), const int[3]));
+SA(__is_same(__remove_pointer(volatile int[3]), volatile int[3]));
+SA(__is_same(__remove_pointer(const volatile int[3]), const volatile int[3]));
+
+SA(__is_same(__remove_pointer(int(int)), int(int)));
+SA(__is_same(__remove_pointer(int(*const)(int)), int(int)));
+SA(__is_same(__remove_pointer(int(*volatile)(int))

[PATCH 2/2] libstdc++: use new built-in trait __remove_pointer

2023-06-24 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __remove_pointer.

libstdc++-v3/ChangeLog:

* include/std/type_traits (remove_pointer): Use __remove_pointer 
built-in trait.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..81497e2f3e1 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2023,6 +2023,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Pointer modifications.
 
+  /// remove_pointer
+#if __has_builtin(__remove_pointer)
+  template
+struct remove_pointer
+{ using type = __remove_pointer(_Tp); };
+#else
   template
 struct __remove_pointer_helper
 { using type = _Tp; };
@@ -2031,11 +2037,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __remove_pointer_helper<_Tp, _Up*>
 { using type = _Up; };
 
-  /// remove_pointer
   template
 struct remove_pointer
 : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>>
 { };
+#endif
 
   template
 struct __add_pointer_helper
-- 
2.41.0



[PATCH 1/2] c++: implement __is_const built-in trait

2023-06-24 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_const.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 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_const.C  | 19 +++
 5 files changed, 30 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_const.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..ff4ae831def 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_CONST:
+  inform (loc, "  %qT is not a const 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 8b7fece0cc8..b40b475b86d 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,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_CONST, "__is_const", 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 8fb47fd179e..011ba8e46e1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12079,6 +12079,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_ENUM:
   return type_code1 == ENUMERAL_TYPE;
 
+case CPTK_IS_CONST:
+  return CP_TYPE_CONST_P (type1);
+
 case CPTK_IS_FINAL:
   return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
 
@@ -12296,6 +12299,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_CONST:
   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..965309a333a 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_const)
+# error "__has_builtin (__is_const) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_const.C 
b/gcc/testsuite/g++.dg/ext/is_const.C
new file mode 100644
index 000..8f2d7c2fce9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_const.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+
+// Positive tests.
+SA(__is_const(const int));
+SA(__is_const(const volatile int));
+SA(__is_const(cClassType));
+SA(__is_const(cvClassType));
+
+// Negative tests.
+SA(!__is_const(int));
+SA(!__is_const(volatile int));
+SA(!__is_const(ClassType));
+SA(!__is_const(vClassType));
-- 
2.41.0



[PATCH 2/2] libstdc++: use new built-in trait __is_const

2023-06-24 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_const.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_const): Use __is_const built-in trait.
(is_const_v): Likewise.

Signed-off-by: Ken Matsui 
---
 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..3a46eca5377 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -764,6 +764,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Type properties.
 
   /// is_const
+#if __has_builtin(__is_const)
+  template
+struct is_const
+: public __bool_constant<__is_const(_Tp)>
+{ };
+#else
   template
 struct is_const
 : public false_type { };
@@ -771,6 +777,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_const<_Tp const>
 : public true_type { };
+#endif
 
   /// is_volatile
   template
@@ -3210,10 +3217,17 @@ template 
   inline constexpr bool is_compound_v = is_compound<_Tp>::value;
 template 
   inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
+
+#if __has_builtin(__is_const)
+template 
+  inline constexpr bool is_const_v = __is_const(_Tp);
+#else
 template 
   inline constexpr bool is_const_v = false;
 template 
   inline constexpr bool is_const_v = true;
+#endif
+
 template 
   inline constexpr bool is_volatile_v = false;
 template 
-- 
2.41.0



  1   2   3   4   5   >