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