Re: [PATCH v3 4/6] libstdc++: use new built-in trait __is_function for std::is_function
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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