[v15,11/39] c++: Implement __is_bounded_array built-in trait

Message ID 20231010095229.3364786-12-kmatsui@gcc.gnu.org
State Unresolved
Headers
Series Optimize type traits performance |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Ken Matsui Oct. 10, 2023, 9:46 a.m. UTC
  This patch implements built-in trait for std::is_bounded_array.

gcc/cp/ChangeLog:

	* cp-trait.def: Define __is_bounded_array.
	* cp-trait.gperf: Reflect cp-trait.def change.
	* cp-trait.h: Likewise.
	* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_BOUNDED_ARRAY.
	* semantics.cc (trait_expr_value): Likewise.
	(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/ext/has-builtin-1.C: Test existence of __is_bounded_array.
	* g++.dg/ext/is_bounded_array.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/cp-trait.gperf                       |  1 +
 gcc/cp/cp-trait.h                           | 86 +++++++++++----------
 gcc/cp/semantics.cc                         |  4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C    |  3 +
 gcc/testsuite/g++.dg/ext/is_bounded_array.C | 38 +++++++++
 7 files changed, 94 insertions(+), 42 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_bounded_array.C
  

Patch

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 751ac61b25a..d09252a56b6 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3723,6 +3723,9 @@  diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_BASE_OF:
       inform (loc, "  %qT is not a base of %qT", t1, t2);
       break;
+    case CPTK_IS_BOUNDED_ARRAY:
+      inform (loc, "  %qT is not a bounded array", t1);
+      break;
     case CPTK_IS_CLASS:
       inform (loc, "  %qT is not a class", t1);
       break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 4e02f68e4a9..6d6dff7a4c3 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -62,6 +62,7 @@  DEFTRAIT_EXPR (IS_AGGREGATE, "__is_aggregate", 1)
 DEFTRAIT_EXPR (IS_ARRAY, "__is_array", 1)
 DEFTRAIT_EXPR (IS_ASSIGNABLE, "__is_assignable", 2)
 DEFTRAIT_EXPR (IS_BASE_OF, "__is_base_of", 2)
+DEFTRAIT_EXPR (IS_BOUNDED_ARRAY, "__is_bounded_array", 1)
 DEFTRAIT_EXPR (IS_CLASS, "__is_class", 1)
 DEFTRAIT_EXPR (IS_CONST, "__is_const", 1)
 DEFTRAIT_EXPR (IS_CONSTRUCTIBLE, "__is_constructible", -1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 8059e1e8d9e..86d7453c9f8 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -43,6 +43,7 @@  struct cp_trait {
 "__is_array", CPTK_IS_ARRAY, false, false, false
 "__is_assignable", CPTK_IS_ASSIGNABLE, true, false, false
 "__is_base_of", CPTK_IS_BASE_OF, true, false, false
+"__is_bounded_array", CPTK_IS_BOUNDED_ARRAY, false, false, false
 "__is_class", CPTK_IS_CLASS, false, false, false
 "__is_const", CPTK_IS_CONST, false, false, false
 "__is_constructible", CPTK_IS_CONSTRUCTIBLE, false, true, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index b52f2985a66..a44498b4b90 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -82,7 +82,7 @@  cp_trait_lookup::hash (const char *str, size_t len)
       116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
       116, 116, 116, 116, 116,  20, 116,  45,   5,  20,
        50,   0,  30,   5, 116,   0, 116, 116,   5,  10,
-       30,   0,   5, 116,  10,  30,   5,   0,   5, 116,
+       30,   0,   5, 116,  10,  30,   5,   0,  25, 116,
       116,   5, 116, 116, 116, 116, 116, 116, 116, 116,
       116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
       116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
@@ -118,7 +118,7 @@  cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 49,
+      TOTAL_KEYWORDS = 50,
       MIN_WORD_LENGTH = 7,
       MAX_WORD_LENGTH = 37,
       MIN_HASH_VALUE = 7,
@@ -127,54 +127,56 @@  cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
     {
-#line 78 "../../gcc/cp/cp-trait.gperf"
+#line 79 "../../gcc/cp/cp-trait.gperf"
       {"__bases", CPTK_BASES, false, false, true},
-#line 51 "../../gcc/cp/cp-trait.gperf"
+#line 52 "../../gcc/cp/cp-trait.gperf"
       {"__is_enum", CPTK_IS_ENUM, false, false, false},
-#line 68 "../../gcc/cp/cp-trait.gperf"
+#line 69 "../../gcc/cp/cp-trait.gperf"
       {"__is_union", CPTK_IS_UNION, false, false, false},
-#line 72 "../../gcc/cp/cp-trait.gperf"
-      {"__remove_cv", CPTK_REMOVE_CV, false, false, true},
 #line 73 "../../gcc/cp/cp-trait.gperf"
+      {"__remove_cv", CPTK_REMOVE_CV, false, false, true},
+#line 74 "../../gcc/cp/cp-trait.gperf"
       {"__remove_cvref", CPTK_REMOVE_CVREF, false, false, true},
-#line 50 "../../gcc/cp/cp-trait.gperf"
+#line 51 "../../gcc/cp/cp-trait.gperf"
       {"__is_empty", CPTK_IS_EMPTY, false, false, false},
-#line 63 "../../gcc/cp/cp-trait.gperf"
+#line 64 "../../gcc/cp/cp-trait.gperf"
       {"__is_trivial", CPTK_IS_TRIVIAL, false, false, false},
-#line 74 "../../gcc/cp/cp-trait.gperf"
+#line 75 "../../gcc/cp/cp-trait.gperf"
       {"__remove_reference", CPTK_REMOVE_REFERENCE, false, false, true},
-#line 79 "../../gcc/cp/cp-trait.gperf"
+#line 80 "../../gcc/cp/cp-trait.gperf"
       {"__direct_bases", CPTK_DIRECT_BASES, false, false, true},
-#line 76 "../../gcc/cp/cp-trait.gperf"
+#line 77 "../../gcc/cp/cp-trait.gperf"
       {"__underlying_type", CPTK_UNDERLYING_TYPE, false, false, true},
-#line 69 "../../gcc/cp/cp-trait.gperf"
-      {"__is_volatile", CPTK_IS_VOLATILE, false, false, false},
-#line 75 "../../gcc/cp/cp-trait.gperf"
+#line 46 "../../gcc/cp/cp-trait.gperf"
+      {"__is_bounded_array", CPTK_IS_BOUNDED_ARRAY, false, false, false},
+#line 76 "../../gcc/cp/cp-trait.gperf"
       {"__type_pack_element", CPTK_TYPE_PACK_ELEMENT, false, true, true},
-#line 67 "../../gcc/cp/cp-trait.gperf"
+#line 68 "../../gcc/cp/cp-trait.gperf"
       {"__is_unbounded_array", CPTK_IS_UNBOUNDED_ARRAY, false, false, false},
-#line 60 "../../gcc/cp/cp-trait.gperf"
+#line 61 "../../gcc/cp/cp-trait.gperf"
       {"__is_polymorphic", CPTK_IS_POLYMORPHIC, false, false, false},
-#line 54 "../../gcc/cp/cp-trait.gperf"
+#line 55 "../../gcc/cp/cp-trait.gperf"
       {"__is_literal_type", CPTK_IS_LITERAL_TYPE, false, false, false},
-#line 66 "../../gcc/cp/cp-trait.gperf"
+#line 67 "../../gcc/cp/cp-trait.gperf"
       {"__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, false, false, false},
-#line 64 "../../gcc/cp/cp-trait.gperf"
+#line 65 "../../gcc/cp/cp-trait.gperf"
       {"__is_trivially_assignable", CPTK_IS_TRIVIALLY_ASSIGNABLE, true, false, false},
-#line 53 "../../gcc/cp/cp-trait.gperf"
+#line 54 "../../gcc/cp/cp-trait.gperf"
       {"__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, true, false, false},
-#line 65 "../../gcc/cp/cp-trait.gperf"
+#line 66 "../../gcc/cp/cp-trait.gperf"
       {"__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, false, true, false},
-#line 71 "../../gcc/cp/cp-trait.gperf"
+#line 72 "../../gcc/cp/cp-trait.gperf"
       {"__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMPORARY, true, false, false},
-#line 70 "../../gcc/cp/cp-trait.gperf"
+#line 71 "../../gcc/cp/cp-trait.gperf"
       {"__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, true, false, false},
 #line 34 "../../gcc/cp/cp-trait.gperf"
       {"__has_nothrow_copy", CPTK_HAS_NOTHROW_COPY, false, false, false},
 #line 32 "../../gcc/cp/cp-trait.gperf"
       {"__has_nothrow_assign", CPTK_HAS_NOTHROW_ASSIGN, false, false, false},
-#line 58 "../../gcc/cp/cp-trait.gperf"
+#line 59 "../../gcc/cp/cp-trait.gperf"
       {"__is_pointer_interconvertible_base_of", CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF, true, false, false},
+#line 70 "../../gcc/cp/cp-trait.gperf"
+      {"__is_volatile", CPTK_IS_VOLATILE, false, false, false},
 #line 40 "../../gcc/cp/cp-trait.gperf"
       {"__has_virtual_destructor", CPTK_HAS_VIRTUAL_DESTRUCTOR, false, false, false},
 #line 33 "../../gcc/cp/cp-trait.gperf"
@@ -183,7 +185,7 @@  cp_trait_lookup::find (const char *str, size_t len)
       {"__is_base_of", CPTK_IS_BASE_OF, true, false, false},
 #line 37 "../../gcc/cp/cp-trait.gperf"
       {"__has_trivial_copy", CPTK_HAS_TRIVIAL_COPY, false, false, false},
-#line 61 "../../gcc/cp/cp-trait.gperf"
+#line 62 "../../gcc/cp/cp-trait.gperf"
       {"__is_same", CPTK_IS_SAME, true, false, false},
 #line 35 "../../gcc/cp/cp-trait.gperf"
       {"__has_trivial_assign", CPTK_HAS_TRIVIAL_ASSIGN, false, false, false},
@@ -193,27 +195,27 @@  cp_trait_lookup::find (const char *str, size_t len)
       {"__has_trivial_destructor", CPTK_HAS_TRIVIAL_DESTRUCTOR, false, false, false},
 #line 36 "../../gcc/cp/cp-trait.gperf"
       {"__has_trivial_constructor", CPTK_HAS_TRIVIAL_CONSTRUCTOR, false, false, false},
-#line 55 "../../gcc/cp/cp-trait.gperf"
+#line 56 "../../gcc/cp/cp-trait.gperf"
       {"__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, true, false, false},
-#line 57 "../../gcc/cp/cp-trait.gperf"
+#line 58 "../../gcc/cp/cp-trait.gperf"
       {"__is_nothrow_convertible", CPTK_IS_NOTHROW_CONVERTIBLE, true, false, false},
-#line 47 "../../gcc/cp/cp-trait.gperf"
+#line 48 "../../gcc/cp/cp-trait.gperf"
       {"__is_const", CPTK_IS_CONST, false, false, false},
-#line 56 "../../gcc/cp/cp-trait.gperf"
+#line 57 "../../gcc/cp/cp-trait.gperf"
       {"__is_nothrow_constructible", CPTK_IS_NOTHROW_CONSTRUCTIBLE, false, true, false},
-#line 59 "../../gcc/cp/cp-trait.gperf"
+#line 60 "../../gcc/cp/cp-trait.gperf"
       {"__is_pod", CPTK_IS_POD, false, false, false},
 #line 42 "../../gcc/cp/cp-trait.gperf"
       {"__is_aggregate", CPTK_IS_AGGREGATE, false, false, false},
 #line 43 "../../gcc/cp/cp-trait.gperf"
       {"__is_array", CPTK_IS_ARRAY, false, false, false},
-#line 49 "../../gcc/cp/cp-trait.gperf"
+#line 50 "../../gcc/cp/cp-trait.gperf"
       {"__is_convertible", CPTK_IS_CONVERTIBLE, true, false, false},
-#line 48 "../../gcc/cp/cp-trait.gperf"
+#line 49 "../../gcc/cp/cp-trait.gperf"
       {"__is_constructible", CPTK_IS_CONSTRUCTIBLE, false, true, false},
-#line 52 "../../gcc/cp/cp-trait.gperf"
+#line 53 "../../gcc/cp/cp-trait.gperf"
       {"__is_final", CPTK_IS_FINAL, false, false, false},
-#line 46 "../../gcc/cp/cp-trait.gperf"
+#line 47 "../../gcc/cp/cp-trait.gperf"
       {"__is_class", CPTK_IS_CLASS, false, false, false},
 #line 39 "../../gcc/cp/cp-trait.gperf"
       {"__has_unique_object_representations", CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS, false, false, false},
@@ -221,9 +223,9 @@  cp_trait_lookup::find (const char *str, size_t len)
       {"__is_abstract", CPTK_IS_ABSTRACT, false, false, false},
 #line 44 "../../gcc/cp/cp-trait.gperf"
       {"__is_assignable", CPTK_IS_ASSIGNABLE, true, false, false},
-#line 62 "../../gcc/cp/cp-trait.gperf"
+#line 63 "../../gcc/cp/cp-trait.gperf"
       {"__is_standard_layout", CPTK_IS_STD_LAYOUT, false, false, false},
-#line 77 "../../gcc/cp/cp-trait.gperf"
+#line 78 "../../gcc/cp/cp-trait.gperf"
       {"__is_deducible ", CPTK_IS_DEDUCIBLE, true, false, false}
     };
 
@@ -232,12 +234,12 @@  cp_trait_lookup::find (const char *str, size_t len)
       -1, -1, -1, -1, -1, -1, -1,  0, -1,  1,  2,  3, -1, -1,
        4,  5, -1,  6,  7,  8, -1, -1,  9, 10, 11, 12, 13, 14,
       15, -1, 16, -1, 17, 18, -1, 19, -1, 20, 21, -1, 22, -1,
-      23, -1, 24, 25, -1, 26, 27, 28, 29, -1, 30, -1, 31, 32,
-      -1, -1, 33, 34, 35, 36, -1, 37, 38, 39, 40, -1, 41, -1,
-      42, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, 44, -1, -1, 45, -1, 46, -1, -1, -1, -1, 47, -1, -1,
+      23, 24, 25, 26, -1, 27, 28, 29, 30, -1, 31, -1, 32, 33,
+      -1, -1, 34, 35, 36, 37, -1, 38, 39, 40, 41, -1, 42, -1,
+      43, -1, -1, -1, -1, 44, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, 45, -1, -1, 46, -1, 47, -1, -1, -1, -1, 48, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, 48
+      -1, -1, -1, 49
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 0a2699be476..32880754020 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12154,6 +12154,9 @@  trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
 	      && (same_type_ignoring_top_level_qualifiers_p (type1, type2)
 		  || DERIVED_FROM_P (type1, type2)));
 
+    case CPTK_IS_BOUNDED_ARRAY:
+      return type_code1 == ARRAY_TYPE && TYPE_DOMAIN (type1);
+
     case CPTK_IS_CLASS:
       return NON_UNION_CLASS_TYPE_P (type1);
 
@@ -12383,6 +12386,7 @@  finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
       break;
 
     case CPTK_IS_ARRAY:
+    case CPTK_IS_BOUNDED_ARRAY:
     case CPTK_IS_CLASS:
     case CPTK_IS_CONST:
     case CPTK_IS_ENUM:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 90997210c12..4142da518b1 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -65,6 +65,9 @@ 
 #if !__has_builtin (__is_base_of)
 # error "__has_builtin (__is_base_of) failed"
 #endif
+#if !__has_builtin (__is_bounded_array)
+# error "__has_builtin (__is_bounded_array) failed"
+#endif
 #if !__has_builtin (__is_class)
 # error "__has_builtin (__is_class) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/is_bounded_array.C b/gcc/testsuite/g++.dg/ext/is_bounded_array.C
new file mode 100644
index 00000000000..346790eba12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_bounded_array.C
@@ -0,0 +1,38 @@ 
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+
+#define SA_TEST_CONST(TRAIT, TYPE, EXPECT)	\
+  SA(TRAIT(TYPE) == EXPECT);			\
+  SA(TRAIT(const TYPE) == EXPECT)
+
+#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_bounded_array, int[2], true);
+SA_TEST_CATEGORY(__is_bounded_array, int[], false);
+SA_TEST_CATEGORY(__is_bounded_array, int[2][3], true);
+SA_TEST_CATEGORY(__is_bounded_array, int[][3], false);
+SA_TEST_CATEGORY(__is_bounded_array, float*[2], true);
+SA_TEST_CATEGORY(__is_bounded_array, float*[], false);
+SA_TEST_CATEGORY(__is_bounded_array, float*[2][3], true);
+SA_TEST_CATEGORY(__is_bounded_array, float*[][3], false);
+SA_TEST_CATEGORY(__is_bounded_array, ClassType[2], true);
+SA_TEST_CATEGORY(__is_bounded_array, ClassType[], false);
+SA_TEST_CATEGORY(__is_bounded_array, ClassType[2][3], true);
+SA_TEST_CATEGORY(__is_bounded_array, ClassType[][3], false);
+SA_TEST_CATEGORY(__is_bounded_array, int(*)[2], false);
+SA_TEST_CATEGORY(__is_bounded_array, int(*)[], false);
+SA_TEST_CATEGORY(__is_bounded_array, int(&)[2], false);
+SA_TEST_CONST(__is_bounded_array, int(&)[], false);
+
+// Sanity check.
+SA_TEST_CATEGORY(__is_bounded_array, ClassType, false);
+SA_TEST_CONST(__is_bounded_array, void(), false);