Skip to content

Commit

Permalink
c++: Implement __is_function built-in trait
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ken-matsui authored and ouuleilei-bot committed Jul 13, 2023
1 parent 81ab984 commit 902e46e
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 0 deletions.
3 changes: 3 additions & 0 deletions gcc/cp/constraint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3767,6 +3767,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;
Expand Down
1 change: 1 addition & 0 deletions gcc/cp/cp-trait.def
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
4 changes: 4 additions & 0 deletions gcc/cp/semantics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12022,6 +12022,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);

Expand Down Expand Up @@ -12243,6 +12246,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:
Expand Down
3 changes: 3 additions & 0 deletions gcc/testsuite/g++.dg/ext/has-builtin-1.C
Original file line number Diff line number Diff line change
Expand Up @@ -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
58 changes: 58 additions & 0 deletions gcc/testsuite/g++.dg/ext/is_function.C
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 902e46e

Please sign in to comment.