Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3628.txt>

gcc/ChangeLog:

        * doc/extend.texi (Syntax Extensions): Document _Maxof & _Minof.

gcc/c-family/ChangeLog:

        * c-common.cc (c_common_reswords): Add _Maxof & _Minof keywords.
        (c_maxof_type, c_minof_type): New functions.
        * c-common.def (MAXOF_EXPR, MINOF_EXPR): New trees.
        * c-common.h (enum rid): Add RID_MAXOF & RID_MINOF.
        (c_maxof_type, c_minof_type): New prototypes.

gcc/c/ChangeLog:

        * c-parser.cc (c_parser_maxof_expression): New function.
        (c_parser_minof_expression): New function.
        (c_parser_maxof_or_minof_expression): New function.
        (c_parser_unary_expression): Add RID_MAXOF & RID_MINOF entries.
        * c-tree.h (c_expr_maxof_type): New prototype.
        (c_expr_minof_type): New prototype.
        * c-typeck.cc (in_maxof, in_minof): New global variables.

Signed-off-by: Alejandro Colomar <[email protected]>
---
 gcc/c-family/c-common.cc                     |  42 +++++++
 gcc/c-family/c-common.def                    |   6 +
 gcc/c-family/c-common.h                      |   4 +-
 gcc/c/c-parser.cc                            | 113 ++++++++++++++++++-
 gcc/c/c-tree.h                               |   2 +
 gcc/c/c-typeck.cc                            |  54 +++++++++
 gcc/doc/extend.texi                          |  19 ++++
 gcc/testsuite/gcc.dg/maxof-compat.c          |   5 +
 gcc/testsuite/gcc.dg/maxof-compile.c         | 110 ++++++++++++++++++
 gcc/testsuite/gcc.dg/maxof-no-compat.c       |   5 +
 gcc/testsuite/gcc.dg/maxof-pedantic-errors.c |   5 +
 gcc/testsuite/gcc.dg/maxof-pedantic.c        |   5 +
 12 files changed, 368 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/maxof-compat.c
 create mode 100644 gcc/testsuite/gcc.dg/maxof-compile.c
 create mode 100644 gcc/testsuite/gcc.dg/maxof-no-compat.c
 create mode 100644 gcc/testsuite/gcc.dg/maxof-pedantic-errors.c
 create mode 100644 gcc/testsuite/gcc.dg/maxof-pedantic.c

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 54e16f708134..2127ba41e94f 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -397,6 +397,8 @@ const struct c_common_resword c_common_reswords[] =
   { "_Alignas",                RID_ALIGNAS,   D_CONLY },
   { "_Alignof",                RID_ALIGNOF,   D_CONLY },
   { "_Countof",                RID_COUNTOF,   D_CONLY },
+  { "_Maxof",          RID_MAXOF,     D_CONLY },
+  { "_Minof",          RID_MINOF,     D_CONLY },
   { "_Atomic",         RID_ATOMIC,    D_CONLY },
   { "_BitInt",         RID_BITINT,    D_CONLY },
   { "_Bool",           RID_BOOL,      D_CONLY },
@@ -4130,6 +4132,46 @@ c_countof_type (location_t loc, tree type)
   return array_type_nelts_top (type);
 }
 
+/* Implement the _Maxof operator:
+   Return the maximum representable value of an integer type.  */
+
+tree
+c_maxof_type (location_t loc, tree type)
+{
+  enum tree_code type_code;
+
+  type_code = TREE_CODE (type);
+  if (type_code != INTEGER_TYPE
+      && type_code != BITINT_TYPE
+      && type_code != ENUMERAL_TYPE)
+    {
+      error_at (loc, "invalid application of %<_Maxof%> to type %qT", type);
+      return error_mark_node;
+    }
+
+  return TYPE_MAX_VALUE (type);
+}
+
+/* Implement the _Minof operator:
+   Return the minimum representable value of an integer type.  */
+
+tree
+c_minof_type (location_t loc, tree type)
+{
+  enum tree_code type_code;
+
+  type_code = TREE_CODE (type);
+  if (type_code != INTEGER_TYPE
+      && type_code != BITINT_TYPE
+      && type_code != ENUMERAL_TYPE)
+    {
+      error_at (loc, "invalid application of %<_Minof%> to type %qT", type);
+      return error_mark_node;
+    }
+
+  return TYPE_MIN_VALUE (type);
+}
+
 /* Handle C and C++ default attributes.  */
 
 enum built_in_attribute
diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
index 0bcc4998afe6..9b1f034579b7 100644
--- a/gcc/c-family/c-common.def
+++ b/gcc/c-family/c-common.def
@@ -53,6 +53,12 @@ DEFTREECODE (USERDEF_LITERAL, "userdef_literal", 
tcc_exceptional, 3)
 /* Represents a 'countof' expression.  */
 DEFTREECODE (COUNTOF_EXPR, "countof_expr", tcc_expression, 1)
 
+/* Represents a 'maxof' expression.  */
+DEFTREECODE (MAXOF_EXPR, "maxof_expr", tcc_expression, 1)
+
+/* Represents a 'minof' expression.  */
+DEFTREECODE (MINOF_EXPR, "minof_expr", tcc_expression, 1)
+
 /* Represents a 'sizeof' expression during C++ template expansion,
    or for the purpose of -Wsizeof-pointer-memaccess warning.  */
 DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1)
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bedbd4a94b0e..5c4edf1527a3 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -105,7 +105,7 @@ enum rid
 
   /* C extensions */
   RID_ASM,       RID_TYPEOF,   RID_TYPEOF_UNQUAL, RID_ALIGNOF,  RID_ATTRIBUTE,
-  RID_COUNTOF,
+  RID_COUNTOF,   RID_MAXOF,    RID_MINOF,
   RID_C23_VA_START, RID_VA_ARG,
   RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL,    RID_CHOOSE_EXPR,
   RID_TYPES_COMPATIBLE_P,      RID_BUILTIN_COMPLEX,       RID_BUILTIN_SHUFFLE,
@@ -893,6 +893,8 @@ extern void c_apply_type_quals_to_decl (int, tree);
 extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int);
 extern tree c_alignof_expr (location_t, tree);
 extern tree c_countof_type (location_t, tree);
+extern tree c_maxof_type (location_t, tree);
+extern tree c_minof_type (location_t, tree);
 /* Print an error message for invalid operands to arith operation CODE.
    NOP_EXPR is used as a special case (see truthvalue_conversion).  */
 extern void binary_op_error (rich_location *, enum tree_code, tree, tree);
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index ea0294f0738e..67ce19469963 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1787,6 +1787,9 @@ static inline struct c_expr c_parser_countof_expression 
(c_parser *);
 static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
                                                            enum rid);
 static struct c_expr c_parser_alignof_expression (c_parser *);
+static inline struct c_expr c_parser_maxof_expression (c_parser *);
+static inline struct c_expr c_parser_minof_expression (c_parser *);
+static struct c_expr c_parser_maxof_or_minof_expression (c_parser *, enum rid);
 static struct c_expr c_parser_postfix_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
                                                                   struct 
c_declspecs *,
@@ -10513,8 +10516,12 @@ c_parser_cast_expression (c_parser *parser, struct 
c_expr *after)
      _Countof ( type-name )
      sizeof unary-expression
      sizeof ( type-name )
+     _Maxof unary-expression
+     _Maxof ( type-name )
+     _Minof unary-expression
+     _Minof ( type-name )
 
-   (_Countof is new in C2y.)
+   (_Countof, _Maxof, and _Minof are new in C2y.)
 
    unary-operator: one of
      & * + - ~ !
@@ -10655,6 +10662,10 @@ c_parser_unary_expression (c_parser *parser)
          return c_parser_sizeof_expression (parser);
        case RID_ALIGNOF:
          return c_parser_alignof_expression (parser);
+       case RID_MAXOF:
+         return c_parser_maxof_expression (parser);
+       case RID_MINOF:
+         return c_parser_minof_expression (parser);
        case RID_BUILTIN_HAS_ATTRIBUTE:
          return c_parser_has_attribute_expression (parser);
        case RID_EXTENSION:
@@ -10905,6 +10916,106 @@ c_parser_alignof_expression (c_parser *parser)
     }
 }
 
+/* Parse a _Maxof expression.  */
+
+static inline struct c_expr
+c_parser_maxof_expression (c_parser *parser)
+{
+  return c_parser_maxof_or_minof_expression (parser, RID_MAXOF);
+}
+
+/* Parse a _Minof expression.  */
+
+static inline struct c_expr
+c_parser_minof_expression (c_parser *parser)
+{
+  return c_parser_maxof_or_minof_expression (parser, RID_MINOF);
+}
+
+/* Parse a _Maxof or _Minof expression.  */
+
+static struct c_expr
+c_parser_maxof_or_minof_expression (c_parser *parser, enum rid rid)
+{
+  const char *op_name = (rid == RID_MAXOF) ? "_Maxof" : "_Minof";
+  struct c_expr expr;
+  struct c_expr result;
+  location_t expr_loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, rid));
+
+  location_t start;
+  location_t finish = UNKNOWN_LOCATION;
+
+  start = c_parser_peek_token (parser)->location;
+
+  pedwarn_c23 (start, OPT_Wpedantic,
+              "ISO C does not support %qs before C2Y", op_name);
+
+  c_parser_consume_token (parser);
+  c_inhibit_evaluation_warnings++;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
+    {
+      /* Either operator ( type-name ) or operator unary-expression
+        starting with a compound literal.  */
+      struct c_declspecs *scspecs;
+      struct c_type_name *type_name;
+      matching_parens parens;
+      parens.consume_open (parser);
+      expr_loc = c_parser_peek_token (parser)->location;
+      scspecs = c_parser_compound_literal_scspecs (parser);
+      type_name = c_parser_type_name (parser, true);
+      parens.skip_until_found_close (parser);
+      finish = parser->tokens_buf[0].location;
+      if (type_name == NULL)
+       {
+         /* Let c_expr_*_expr call pop_maybe_used and fill in c_expr
+            for parsing error; the parsing of the expression could have
+            called record_maybe_used_decl.  */
+         expr.set_error ();
+         error_at (expr_loc, "%qs XXX: How do we arrive here?", op_name);
+         goto Xof_expr;
+       }
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
+                                                              type_name,
+                                                              expr_loc);
+         finish = expr.get_finish ();
+         error_at (expr_loc, "invalid application of %qs to a compound 
literal",
+                   op_name);
+         goto Xof_expr;
+       }
+      /* operator ( type-name ).  */
+      if (scspecs)
+       error_at (expr_loc, "storage class specifier in %qs", op_name);
+      if (type_name->specs->alignas_p)
+       error_at (type_name->specs->locations[cdw_alignas],
+                 "alignment specified for type name in %qs", op_name);
+      c_inhibit_evaluation_warnings--;
+      if (rid == RID_MAXOF)
+       result = c_expr_maxof_type (expr_loc, type_name);
+      else
+       result = c_expr_minof_type (expr_loc, type_name);
+      set_c_expr_source_range (&result, start, finish);
+    }
+  else
+    {
+      expr_loc = c_parser_peek_token (parser)->location;
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+       error_at (expr_loc, "invalid application of %qs to something not a 
type", op_name);
+      else
+       c_parser_error (parser, "expected %<(%>");
+      expr = c_parser_unary_expression (parser);
+    Xof_expr:
+      c_inhibit_evaluation_warnings--;
+      result.set_error ();
+      result.original_code = ERROR_MARK;
+      result.original_type = NULL;
+    }
+  return result;
+}
+
 /* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
    expression.  */
 
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 162add0522ac..6abe98a9f85a 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -855,6 +855,8 @@ extern struct c_expr c_expr_sizeof_type (location_t, struct 
c_type_name *);
 extern struct c_expr c_expr_countof_expr (location_t, struct c_expr);
 extern struct c_expr c_expr_countof_type (location_t loc,
                                          struct c_type_name *);
+extern struct c_expr c_expr_maxof_type (location_t loc, struct c_type_name *);
+extern struct c_expr c_expr_minof_type (location_t loc, struct c_type_name *);
 extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
                                            struct c_expr);
 extern struct c_expr parser_build_binary_op (location_t,
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 371583bd64ed..d8a5819b1e9e 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -4117,6 +4117,60 @@ c_expr_countof_type (location_t loc, struct c_type_name 
*t)
   return ret;
 }
 
+/* Return the result of maxof applied to T, a structure for the type
+   name passed to maxof (rather than the type itself).  LOC is the
+   location of the original expression.  */
+
+struct c_expr
+c_expr_maxof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  tree type_expr = NULL_TREE;
+  bool type_expr_const = true;
+  type = groktypename (t, &type_expr, &type_expr_const);
+  ret.value = c_maxof_type (loc, type);
+  c_last_sizeof_arg = type;
+  c_last_sizeof_loc = loc;
+  ret.original_code = MAXOF_EXPR;
+  ret.original_type = NULL;
+  ret.m_decimal = 0;
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+    }
+  pop_maybe_used (type != error_mark_node);
+  return ret;
+}
+
+/* Return the result of minof applied to T, a structure for the type
+   name passed to minof (rather than the type itself).  LOC is the
+   location of the original expression.  */
+
+struct c_expr
+c_expr_minof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  tree type_expr = NULL_TREE;
+  bool type_expr_const = true;
+  type = groktypename (t, &type_expr, &type_expr_const);
+  ret.value = c_minof_type (loc, type);
+  c_last_sizeof_arg = type;
+  c_last_sizeof_loc = loc;
+  ret.original_code = MAXOF_EXPR;
+  ret.original_type = NULL;
+  ret.m_decimal = 0;
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+    }
+  pop_maybe_used (type != error_mark_node);
+  return ret;
+}
+
 /* Build a function call to function FUNCTION with parameters PARAMS.
    The function call is at LOC.
    PARAMS is a list--a chain of TREE_LIST nodes--in which the
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index d58260e295a5..46ee480daf56 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13271,6 +13271,7 @@ C and/or C++ standards, while others remain specific to 
GNU C.
 * Nested Functions::    Nested functions in GNU C.
 * Typeof::              @code{typeof}: referring to the type of an expression.
 * _Countof::            Determining the Number of Elements of Arrays
+* _Maxof and _Minof::   The maximum and minimum representable values of a type.
 * Offsetof::            Special syntax for @code{offsetof}.
 * Alignment::           Determining the alignment of a function, type or 
variable.
 * Enum Extensions::     Forward declarations and specifying the underlying 
type.
@@ -13937,6 +13938,24 @@ _Countof (int [7][n++]);  // integer constant 
expression
 _Countof (int [n++][7]);  // run-time value; n++ is evaluated
 @end smallexample
 
+@node _Maxof and _Minof
+@subsection The maximum and minimum representable values of a type
+@findex _Maxof
+@findex _Minof
+
+The keywords @code{_Maxof} and @code{_Minof} determine
+the maximum and minimum representable values of an integer type.
+Its syntax is similar to @code{sizeof}.
+The operand must be
+a parenthesized integer type.
+The result of this operator is an integer constant expression.
+For example:
+
+@smallexample
+_Maxof (int);    // returns INT_MAX
+_Minof (short);  // returns SHRT_MIN
+@end smallexample
+
 @node Offsetof
 @subsection Support for @code{offsetof}
 @findex __builtin_offsetof
diff --git a/gcc/testsuite/gcc.dg/maxof-compat.c 
b/gcc/testsuite/gcc.dg/maxof-compat.c
new file mode 100644
index 000000000000..2c023a3eaf7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/maxof-compat.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors -Wc23-c2y-compat" } */
+
+int a[_Maxof(char)];  /* { dg-warning "ISO C does not support" } */
+int b[1 + _Minof(unsigned char)];  /* { dg-warning "ISO C does not support" } 
*/
diff --git a/gcc/testsuite/gcc.dg/maxof-compile.c 
b/gcc/testsuite/gcc.dg/maxof-compile.c
new file mode 100644
index 000000000000..6988452edafa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/maxof-compile.c
@@ -0,0 +1,110 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+#define SCHAR_MAX  __SCHAR_MAX__
+#define SCHAR_MIN  (-SCHAR_MAX - 1)
+#define UCHAR_MAX  (SCHAR_MAX * 2 + 1)
+
+#define SHRT_MAX   __SHRT_MAX__
+#define SHRT_MIN   (-SHRT_MAX - 1)
+#define USHRT_MAX  (SHRT_MAX * 2U + 1)
+
+#define INT_MAX    __INT_MAX__
+#define INT_MIN    (-INT_MAX - 1)
+#define UINT_MAX   (INT_MAX * 2U + 1)
+
+#define LONG_MAX   __LONG_MAX__
+#define LONG_MIN   (-LONG_MAX - 1L)
+#define ULONG_MAX  (LONG_MAX * 2LU + 1)
+
+void
+integer (void)
+{
+  _Static_assert(_Maxof (char) == SCHAR_MAX || _Maxof (char) == UCHAR_MAX);
+  _Static_assert(_Minof (char) == SCHAR_MIN || _Minof (char) == 0);
+
+  _Static_assert(_Maxof (signed char) == SCHAR_MAX);
+  _Static_assert(_Maxof (short) == SHRT_MAX);
+  _Static_assert(_Maxof (int) == INT_MAX);
+  _Static_assert(_Maxof (long) == LONG_MAX);
+  _Static_assert(_Maxof (long long) >= LONG_MAX);
+
+  _Static_assert(_Minof (signed char) == SCHAR_MIN);
+  _Static_assert(_Minof (short) == SHRT_MIN);
+  _Static_assert(_Minof (int) == INT_MIN);
+  _Static_assert(_Minof (long) == LONG_MIN);
+  _Static_assert(_Minof (long long) <= LONG_MIN);
+
+  _Static_assert(_Maxof (unsigned char) == UCHAR_MAX);
+  _Static_assert(_Maxof (unsigned short) == USHRT_MAX);
+  _Static_assert(_Maxof (unsigned int) == UINT_MAX);
+  _Static_assert(_Maxof (unsigned long) == ULONG_MAX);
+  _Static_assert(_Maxof (unsigned long long) >= ULONG_MAX);
+
+  _Static_assert(_Minof (unsigned char) == 0);
+  _Static_assert(_Minof (unsigned short) == 0);
+  _Static_assert(_Minof (unsigned int) == 0);
+  _Static_assert(_Minof (unsigned long) == 0);
+  _Static_assert(_Minof (unsigned long long) == 0);
+}
+
+void
+bitint (void)
+{
+  _Static_assert(_Maxof (_BitInt(5)) == 15);
+  _Static_assert(_Minof (_BitInt(5)) == -16);
+  _Static_assert(_Maxof (unsigned _BitInt(5)) == 31);
+  _Static_assert(_Minof (unsigned _BitInt(5)) == 0);
+}
+
+void
+enums (void)
+{
+  enum e1 { E1 };
+  enum e2 : short { E2 };
+
+  _Maxof (enum e1);
+  _Minof (enum e1);
+  _Static_assert(_Maxof (enum e2) == SHRT_MAX);
+  _Static_assert(_Minof (enum e2) == SHRT_MIN);
+}
+
+void
+expr (void)
+{
+  int x;
+
+  _Maxof (x);  /* { dg-error "to something not a type" } */
+  _Minof (x);  /* { dg-error "to something not a type" } */
+  _Maxof (1);  /* { dg-error "to something not a type" } */
+  _Minof (1);  /* { dg-error "to something not a type" } */
+  _Maxof 1;  /* { dg-error "expected" } */
+  _Minof 1;  /* { dg-error "expected" } */
+  _Maxof (int) {1};  /* { dg-error "to a compound literal" } */
+  _Minof (int) {1};  /* { dg-error "to a compound literal" } */
+}
+
+void
+non_int (void)
+{
+  struct s {int x;};
+  union u {int x;};
+
+  _Maxof (struct s);  /* { dg-error "to type" } */
+  _Minof (struct s);  /* { dg-error "to type" } */
+  _Maxof (union u);  /* { dg-error "to type" } */
+  _Minof (union u);  /* { dg-error "to type" } */
+  _Maxof (bool);  /* { dg-error "to type" } */
+  _Minof (bool);  /* { dg-error "to type" } */
+  _Maxof (int [1]);  /* { dg-error "to type" } */
+  _Minof (int [1]);  /* { dg-error "to type" } */
+}
+
+void
+specs (void)
+{
+  _Maxof (static int);  /* { dg-error "storage class specifier in" } */
+  _Minof (static int);  /* { dg-error "storage class specifier in" } */
+  _Maxof (alignas(8) int);  /* { dg-error "alignment specified" } */
+  _Minof (alignas(8) int);  /* { dg-error "alignment specified" } */
+}
diff --git a/gcc/testsuite/gcc.dg/maxof-no-compat.c 
b/gcc/testsuite/gcc.dg/maxof-no-compat.c
new file mode 100644
index 000000000000..e0d3fb94d85b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/maxof-no-compat.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors -Wno-c23-c2y-compat" } */
+
+int a[_Maxof(char)];
+int b[1 + _Minof(unsigned char)];
diff --git a/gcc/testsuite/gcc.dg/maxof-pedantic-errors.c 
b/gcc/testsuite/gcc.dg/maxof-pedantic-errors.c
new file mode 100644
index 000000000000..dcb64bb06bb5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/maxof-pedantic-errors.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+
+int a[_Maxof(char)];  /* { dg-error "ISO C does not support" } */
+int b[1 + _Minof(unsigned char)];  /* { dg-error "ISO C does not support" } */
diff --git a/gcc/testsuite/gcc.dg/maxof-pedantic.c 
b/gcc/testsuite/gcc.dg/maxof-pedantic.c
new file mode 100644
index 000000000000..fa2582c2baa5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/maxof-pedantic.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic" } */
+
+int a[_Maxof(char)];  /* { dg-warning "ISO C does not support" } */
+int b[1 + _Minof(unsigned char)];  /* { dg-warning "ISO C does not support" } 
*/
-- 
2.51.0

Reply via email to