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 constants.
(c_maxof_type, c_minof_type): New prototypes.
gcc/c/ChangeLog:
* c-parser.cc (c_parser_maxof_or_minof_expression): New func.
(c_parser_unary_expression): Add RID_MAXOF & RID_MINOF cases.
* c-tree.h (c_expr_maxof_type): New prototype.
(c_expr_minof_type): New prototype.
* c-typeck.cc (c_expr_maxof_type): New function.
(c_expr_minof_type): New function.
gcc/testsuite/ChangeLog:
* gcc.dg/maxof-compat.c: New test.
* gcc.dg/maxof-compile.c: New test.
* gcc.dg/maxof-no-compat.c: New test.
* gcc.dg/maxof-pedantic-errors.c: New test.
* gcc.dg/maxof-pedantic.c: New test.
Signed-off-by: Alejandro Colomar <[email protected]>
---
gcc/c-family/c-common.cc | 32 ++++
gcc/c-family/c-common.def | 6 +
gcc/c-family/c-common.h | 4 +-
gcc/c/c-parser.cc | 65 ++++++-
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 | 169 +++++++++++++++++++
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, 369 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 9b97a0fe6224..f4410f55193a 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 },
@@ -4138,6 +4140,36 @@ c_countof_type (location_t loc, tree type)
return value;
}
+/* Implement the _Maxof operator:
+ Return the maximum representable value of an integer type. */
+
+tree
+c_maxof_type (location_t loc, tree type)
+{
+ if (!INTEGRAL_TYPE_P (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)
+{
+ if (!INTEGRAL_TYPE_P (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 8b7f4ae44717..6a92bd6ef762 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 360df52967b5..ef0a89a3e94e 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1803,6 +1803,7 @@ static struct c_expr c_parser_unary_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 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 *,
@@ -10528,9 +10529,12 @@ c_parser_cast_expression (c_parser *parser, struct
c_expr *after)
_Countof ( type-name )
sizeof unary-expression
sizeof ( type-name )
+ _Maxof ( type-name )
+ _Minof ( type-name )
static-assert-declaration-no-semi
- (_Countof and the use of static assertions in expressions are new in C2y.)
+ (_Countof, _Maxof, _Minof, and the use of static assertions in
+ expressions are new in C2y.)
unary-operator: one of
& * + - ~ !
@@ -10672,6 +10676,9 @@ c_parser_unary_expression (c_parser *parser)
return c_parser_sizeof_or_countof_expression (parser, rid);
case RID_ALIGNOF:
return c_parser_alignof_expression (parser);
+ case RID_MAXOF:
+ case RID_MINOF:
+ return c_parser_maxof_or_minof_expression (parser, rid);
case RID_BUILTIN_HAS_ATTRIBUTE:
return c_parser_has_attribute_expression (parser);
case RID_EXTENSION:
@@ -10915,6 +10922,62 @@ c_parser_alignof_expression (c_parser *parser)
}
}
+/* 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 result;
+ location_t expr_loc;
+ struct c_type_name *type_name;
+ matching_parens parens;
+ 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_parser_error (parser, "expected %<(%>");
+ goto fail;
+ }
+ parens.consume_open (parser);
+ expr_loc = c_parser_peek_token (parser)->location;
+ if (!c_token_starts_typename (c_parser_peek_token (parser)))
+ {
+ error_at (expr_loc, "invalid application of %qs to something not a
type", op_name);
+ goto fail;
+ }
+ type_name = c_parser_type_name (parser, true);
+ // Can return NULL? Why?
+ parens.skip_until_found_close (parser);
+ finish = parser->tokens_buf[0].location;
+ 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);
+ return result;
+fail:
+ 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 ff63d69e85d5..80b147154032 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -856,6 +856,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 e1d2d1173dc7..2fc82408cf85 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -4120,6 +4120,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 cd2d3475df31..613e414a0b48 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13537,6 +13537,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.
@@ -14203,6 +14204,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..04d417cb29b1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/maxof-compile.c
@@ -0,0 +1,169 @@
+/* { 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);
+
+ _Static_assert (_Maxof (bool) == true);
+ _Static_assert (_Minof (bool) == false);
+}
+
+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" } */
+ /* { dg-error "expected ';'" "syntax error" { target *-*-* } .-1 } */
+ /* { dg-error "expected statement" "syntax error 2" { target *-*-* } .-2 } */
+ _Minof (x); /* { dg-error "to something not a type" } */
+ /* { dg-error "expected ';'" "syntax error" { target *-*-* } .-1 } */
+ /* { dg-error "expected statement" "syntax error 2" { target *-*-* } .-2 } */
+ _Maxof (1); /* { dg-error "to something not a type" } */
+ /* { dg-error "expected ';'" "syntax error" { target *-*-* } .-1 } */
+ /* { dg-error "expected statement" "syntax error 2" { target *-*-* } .-2 } */
+ _Minof (1); /* { dg-error "to something not a type" } */
+ /* { dg-error "expected ';'" "syntax error" { target *-*-* } .-1 } */
+ /* { dg-error "expected statement" "syntax error 2" { target *-*-* } .-2 } */
+ _Maxof 1; /* { dg-error "expected '\\('" } */
+ _Minof 1; /* { dg-error "expected '\\('" } */
+ _Maxof (int) {1}; /* { dg-error "expected ';'" } */
+ _Minof (int) {1}; /* { dg-error "expected ';'" } */
+}
+
+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 (int [1]); /* { dg-error "to type" } */
+ _Minof (int [1]); /* { dg-error "to type" } */
+}
+
+void
+specs (void)
+{
+ _Maxof (static int); /* { dg-error "to something not a type" } */
+ /* { dg-error "expected ';'" "syntax error" { target *-*-* } .-1 } */
+ /* { dg-error "expected statement" "syntax error 2" { target *-*-* } .-2 } */
+ _Minof (static int); /* { dg-error "to something not a type" } */
+ /* { dg-error "expected ';'" "syntax error" { target *-*-* } .-1 } */
+ /* { dg-error "expected statement" "syntax error 2" { target *-*-* } .-2 } */
+ _Maxof (alignas(8) int); /* { dg-error "alignment specified" } */
+ _Minof (alignas(8) int); /* { dg-error "alignment specified" } */
+}
+
+void
+bogus (void)
+{
+ _Maxof (int x); /* { dg-error "expected '\\)'" } */
+ _Minof (int x); /* { dg-error "expected '\\)'" } */
+}
+
+void
+type (void)
+{
+ _Generic (_Maxof (char), char: 0);
+ _Generic (_Minof (char), char: 0);
+
+ _Generic (_Maxof (signed char), signed char: 0);
+ _Generic (_Maxof (short), short: 0);
+ _Generic (_Maxof (int), int: 0);
+ _Generic (_Maxof (long), long: 0);
+ _Generic (_Maxof (long long), long long: 0);
+
+ _Generic (_Minof (signed char), signed char: 0);
+ _Generic (_Minof (short), short: 0);
+ _Generic (_Minof (int), int: 0);
+ _Generic (_Minof (long), long: 0);
+ _Generic (_Minof (long long), long long: 0);
+
+ _Generic (_Maxof (unsigned char), unsigned char: 0);
+ _Generic (_Maxof (unsigned short), unsigned short: 0);
+ _Generic (_Maxof (unsigned int), unsigned int: 0);
+ _Generic (_Maxof (unsigned long), unsigned long: 0);
+ _Generic (_Maxof (unsigned long long), unsigned long long: 0);
+
+ _Generic (_Minof (unsigned char), unsigned char: 0);
+ _Generic (_Minof (unsigned short), unsigned short: 0);
+ _Generic (_Minof (unsigned int), unsigned int: 0);
+ _Generic (_Minof (unsigned long), unsigned long: 0);
+ _Generic (_Minof (unsigned long long), unsigned long long: 0);
+
+ _Generic (_Maxof (bool), bool: 0);
+ _Generic (_Minof (bool), bool: 0);
+
+ _Generic (_Maxof (_BitInt (5)), _BitInt (5): 0);
+ _Generic (_Minof (_BitInt (5)), _BitInt (5): 0);
+ _Generic (_Maxof (unsigned _BitInt (5)), unsigned _BitInt (5): 0);
+ _Generic (_Minof (unsigned _BitInt (5)), unsigned _BitInt (5): 0);
+}
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