Hi,

Here's a second attempt at implementing these two operators.
They're implemented as proposed in n3628, but differ slightly in that
they reject _Bool (the first commit message details a bit more about
this).

I tested the feature while developing it, and those tests all passed.
However, when I've tried to do it formally, I'm now getting some issues
that don't make any sense.  I think something in the build system is not
working properly, or I have broken something in a way that I don't
understand.  I'll paste here what I see:

        alx@devuan:~/src/gnu/gcc/maxof$ git log --oneline gnu/master^..maxof2
        4b6f1d46fb2d (HEAD -> maxof, tag: maxof2) c: Reduce excess errors of 
_Maxof and _Minof
        29ee24eabe18 c: Add _Maxof and _Minof operators
        1161fc635450 (gnu/trunk, gnu/master, gnu/HEAD) Handle shift-pairs in 
ext-dce for targets without zero/sign extension insns
        alx@devuan:~/src/gnu/gcc/maxof$ git reset gnu/master --h
        HEAD is now at 1161fc635450 Handle shift-pairs in ext-dce for targets 
without zero/sign extension insns
        alx@devuan:~/src/gnu/gcc/maxof$ mkdir ../maxof2
        alx@devuan:~/src/gnu/gcc/maxof$ cd ../maxof2/
        alx@devuan:~/src/gnu/gcc/maxof2$ set -o pipefail
        alx@devuan:~/src/gnu/gcc/maxof2$ ../maxof/configure --disable-multilib 
--prefix=/opt/local/gnu/gcc/maxof2 |& ts -s | tail -n1; echo $?;
        00:00:02 config.status: creating Makefile
        0
        alx@devuan:~/src/gnu/gcc/maxof2$ make -j24 bootstrap |& ts -s | tail 
-n1; echo $?;
        00:22:11 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/maxof2'
        0
        alx@devuan:~/src/gnu/gcc/maxof2$ make -j24 check |& ts -s | tail -n1; 
echo $?;
        00:34:55 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/maxof2'
        0
        alx@devuan:~/src/gnu/gcc/maxof2$ cd ../maxof
        alx@devuan:~/src/gnu/gcc/maxof$ git merge --ff-only maxof2 
        Updating 1161fc635450..4b6f1d46fb2d
        Fast-forward
         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                            |  66 +++++++-
         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         | 159 +++++++++++++++++++
         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, 360 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
        alx@devuan:~/src/gnu/gcc/maxof$ cd ../
        alx@devuan:~/src/gnu/gcc$ mv maxof2
        maxof2/
        alx@devuan:~/src/gnu/gcc$ mv maxof2/ maxof2_b4
        alx@devuan:~/src/gnu/gcc$ mkdir maxof2
        alx@devuan:~/src/gnu/gcc$ cd maxof2
        alx@devuan:~/src/gnu/gcc/maxof2$ ../maxof/configure --disable-multilib 
--prefix=/opt/local/gnu/gcc/maxof2 |& ts -s | tail -n1; echo $?;
        00:00:01 config.status: creating Makefile
        0
        alx@devuan:~/src/gnu/gcc/maxof2$ make -j24 bootstrap |& ts -s | tail 
-n1; echo $?;
        00:22:20 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/maxof2'
        0
        alx@devuan:~/src/gnu/gcc/maxof2$ make -j24 check |& ts -s | tail -n1; 
echo $?;
        00:34:40 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/maxof2'
        0
        alx@devuan:~/src/gnu/gcc/maxof2$ find -type f | grep '\.sum$' | while 
read f; do diff -u "../maxof2_b4/$f" "$f"; done
        --- ../maxof2_b4/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      
2025-11-14 02:04:25.583049614 +0100
        +++ ./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum   2025-11-14 
15:44:37.179161371 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:34 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === libitm tests ===
        --- 
../maxof2_b4/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum2025-11-14 
02:04:24.552495874 +0100
        +++ ./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum     
2025-11-14 15:44:36.094622398 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:34 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === libatomic tests ===
        --- ../maxof2_b4/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    
2025-11-14 02:06:46.440704161 +0100
        +++ ./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum 2025-11-14 
15:46:46.943307275 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:34 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === libgomp tests ===
        --- 
../maxof2_b4/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     
2025-11-14 02:39:17.560769098 +0100
        +++ ./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum  
2025-11-14 16:19:13.738775165 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:24 2025
        +Test run by alx on Fri Nov 14 15:44:35 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === libstdc++ tests ===
        --- ../maxof2_b4/./gcc/testsuite/objc/objc.sum  2025-11-14 
02:05:29.243579430 +0100
        +++ ./gcc/testsuite/objc/objc.sum       2025-11-14 15:45:23.840405398 
+0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:35 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === objc tests ===
        --- ../maxof2_b4/./gcc/testsuite/g++/g++.sum    2025-11-14 
02:16:21.259781844 +0100
        +++ ./gcc/testsuite/g++/g++.sum 2025-11-14 15:58:33.707331276 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:35 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === g++ tests ===
        --- ../maxof2_b4/./gcc/testsuite/gcc/gcc.sum    2025-11-14 
02:22:42.112260276 +0100
        +++ ./gcc/testsuite/gcc/gcc.sum 2025-11-14 16:02:01.933356817 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:35 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === gcc tests ===
        @@ -71738,6 +71738,7 @@
         PASS: c-c++-common/zero-scratch-regs-leafy-1.c  -Wc++-compat  (test 
for excess errors)
         PASS: c-c++-common/zero-scratch-regs-leafy-1.c  -Wc++-compat  
execution test
         PASS: c-c++-common/zero-scratch-regs-leafy-2.c  -Wc++-compat  (test 
for excess errors)
        +ERROR: couldn't compile regular expression pattern: parentheses () not 
balanced
         UNSUPPORTED: fatal-error-html.py pytest python3 is missing
         UNSUPPORTED: fatal-error-sarif.py pytest python3 is missing
         PASS: gcc.dg/20000108-1.c (test for excess errors)
        @@ -94161,18 +94162,10 @@
[...]
        @@ -221107,11 +206857,11 @@
         
                        === gcc Summary ===
         
        -# of expected passes           215035
        +# of expected passes           201711
         # of unexpected failures       529
        -# of unexpected successes      6
        -# of expected failures         1485
        -# of unresolved testcases      1
        -# of unsupported tests         3859
        +# of unexpected successes      7
        +# of expected failures         1448
        +# of unresolved testcases      2
        +# of unsupported tests         2965
         /srv/alx/src/gnu/gcc/maxof2/gcc/xgcc  version 16.0.0 20251113 
(experimental) (GCC) 
         
        --- ../maxof2_b4/./gcc/testsuite/gfortran/gfortran.sum  2025-11-14 
02:15:47.295817457 +0100
        +++ ./gcc/testsuite/gfortran/gfortran.sum       2025-11-14 
15:57:02.256911162 +0100
        @@ -1,4 +1,4 @@
        -Test run by alx on Fri Nov 14 02:04:23 2025
        +Test run by alx on Fri Nov 14 15:44:35 2025
         Native configuration is x86_64-pc-linux-gnu
         
                        === gfortran tests ===
        alx@devuan:~/src/gnu/gcc/maxof2$ find -type f | grep '\.sum$' | while 
read f; do diff -u "../maxof2_b4/$f" "$f"; done | grep 'gcc.dg/maxof'
        +PASS: gcc.dg/maxof-compat.c  (test for warnings, line 4)
        +PASS: gcc.dg/maxof-compat.c  (test for warnings, line 5)
        +PASS: gcc.dg/maxof-compat.c (test for excess errors)
        +PASS: gcc.dg/maxof-compile.c  (test for errors, line 77)

It doesn't make any sense, as there should be many more test results
matching 'gcc.dg/maxof' (and I've seen them in previous testing).

BTW, I suppose you'll prefer the two commits squashed.  I kept them
separate just to show the difference in errors during review, but I can
squash them if you want me to.


Have a lovely night!
Alex


Alejandro Colomar (2):
  c: Add _Maxof and _Minof operators
  c: Reduce excess errors of _Maxof and _Minof

 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                            |  66 +++++++-
 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         | 159 +++++++++++++++++++
 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, 360 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

Range-diff against v1:
2:  11d4b9b554d5 ! 1:  29ee24eabe18 c: Add _Maxof and _Minof operators
    @@ Commit message
     
         Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3628.txt>
     
    +    This implementation differs from n3628 in that _Bool is not accepted by
    +    these operators in this implementation.  It was an oversight to allow
    +    _Bool in n3628, and I will publish a revision of that paper with that
    +    amended, prior to the next meeting of the C Committee.
    +
    +    These operators generalize the existing XXX_MAX and XXX_MIN macros.
    +    Those macros don't exist for _Bool, as it wouldn't be useful.
    +    Similarly, these new operators wouldn't be useful for use with _Bool,
    +    even if mathematically it could make sense to accept them as input.
    +
    +    To be cautious, let's constrain that, with the option to revisit that 
in
    +    the future, if a reason for accepting _Bool were discovered.
    +
         gcc/ChangeLog:
     
                 * doc/extend.texi (Syntax Extensions): Document _Maxof & 
_Minof.
    @@ Commit message
                 * 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-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_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-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 (in_maxof, in_minof): New global variables.
    +            * 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: const struct c_common_resword 
c_common_reswords[] =
        { "_BitInt",            RID_BITINT,    D_CONLY },
        { "_Bool",              RID_BOOL,      D_CONLY },
     @@ gcc/c-family/c-common.cc: c_countof_type (location_t loc, tree type)
    -   return array_type_nelts_top (type);
    +   return value;
      }
      
     +/* Implement the _Maxof operator:
    @@ gcc/c-family/c-common.cc: c_countof_type (location_t loc, tree 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)
    ++  if (!INTEGRAL_TYPE_P (type) || TREE_CODE (type) == BOOLEAN_TYPE)
     +    {
     +      error_at (loc, "invalid application of %<_Maxof%> to type %qT", 
type);
     +      return error_mark_node;
    @@ gcc/c-family/c-common.cc: c_countof_type (location_t loc, tree 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)
    ++  if (!INTEGRAL_TYPE_P (type) || TREE_CODE (type) == BOOLEAN_TYPE)
     +    {
     +      error_at (loc, "invalid application of %<_Minof%> to type %qT", 
type);
     +      return error_mark_node;
    @@ gcc/c-family/c-common.h: extern void c_apply_type_quals_to_decl (int, 
tree);
      extern void binary_op_error (rich_location *, enum tree_code, tree, tree);
     
      ## gcc/c/c-parser.cc ##
    -@@ gcc/c/c-parser.cc: static inline struct c_expr 
c_parser_countof_expression (c_parser *);
    +@@ gcc/c/c-parser.cc: 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 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 *,
    @@ gcc/c/c-parser.cc: c_parser_cast_expression (c_parser *parser, struct 
c_expr *af
           _Countof ( type-name )
           sizeof unary-expression
           sizeof ( type-name )
    -+     _Maxof unary-expression
     +     _Maxof ( type-name )
    -+     _Minof unary-expression
     +     _Minof ( type-name )
    +      static-assert-declaration-no-semi
      
    --   (_Countof is new in C2y.)
    -+   (_Countof, _Maxof, and _Minof are new in C2y.)
    +-   (_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
           & * + - ~ !
     @@ gcc/c/c-parser.cc: 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:
    +       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:
     @@ gcc/c/c-parser.cc: 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;
    ++  struct c_type_name *type_name;
    ++  matching_parens parens;
     +  gcc_assert (c_parser_next_token_is_keyword (parser, rid));
     +
     +  location_t start;
    @@ gcc/c/c-parser.cc: c_parser_alignof_expression (c_parser *parser)
     +
     +  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)))
    ++  if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     +    {
    -+      /* 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);
    ++      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
    -+    {
    -+      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;
    -+    }
    ++    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;
     +}
     +
    @@ gcc/doc/extend.texi
     @@ gcc/doc/extend.texi: 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
    + * _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.
    @@ gcc/testsuite/gcc.dg/maxof-compile.c (new)
     +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 (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 (_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 (_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 (_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 (_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);
    ++  _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
    @@ gcc/testsuite/gcc.dg/maxof-compile.c (new)
     +
     +  _Maxof (enum e1);
     +  _Minof (enum e1);
    -+  _Static_assert(_Maxof (enum e2) == SHRT_MAX);
    -+  _Static_assert(_Minof (enum e2) == SHRT_MIN);
    ++  _Static_assert (_Maxof (enum e2) == SHRT_MAX);
    ++  _Static_assert (_Minof (enum e2) == SHRT_MIN);
     +}
     +
     +void
    @@ gcc/testsuite/gcc.dg/maxof-compile.c (new)
     +  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" } */
    -+  _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" } */
    ++  /* { 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
    @@ gcc/testsuite/gcc.dg/maxof-compile.c (new)
     +void
     +specs (void)
     +{
    -+  _Maxof (static int);  /* { dg-error "storage class specifier in" } */
    -+  _Minof (static int);  /* { dg-error "storage class specifier in" } */
    ++  _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 (_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);
     +}
     
      ## gcc/testsuite/gcc.dg/maxof-no-compat.c (new) ##
1:  a54651f69765 ! 2:  4b6f1d46fb2d doc: Move _Countof under 'Other Extensions 
to C Syntax'
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    doc: Move _Countof under 'Other Extensions to C Syntax'
    +    c: Reduce excess errors of _Maxof and _Minof
     
    -    gcc/ChangeLog:
    +    gcc/c/ChangeLog:
     
    -            * doc/extend.texi: Move _Countof under 'Syntax Extensions'.
    +            * c-parser.cc (c_parser_maxof_or_minof_expression): After '('
    +            has been parsed, if there's a syntax error, skip until ')', to
    +            minimize excess errors.
    +
    +    gcc/testsuite/ChangeLog:
    +
    +            * gcc.dg/maxof-compile.c (expr, specs): Update test.
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    - ## gcc/doc/extend.texi ##
    -@@ gcc/doc/extend.texi: extensions, accepted by GCC in C90 mode and in C++.
    - * Thread-Local::        Per-thread variables.
    - * OpenMP::              Multiprocessing extensions.
    - * OpenACC::             Extensions for offloading code to accelerator 
devices.
    --* _Countof::            The number of elements of arrays.
    - * Inline::              Defining inline functions (as fast as macros).
    - * Volatiles::           What constitutes an access to a volatile object.
    - * Using Assembly Language with C:: Instructions and extensions for 
interfacing C with assembler.
    -@@ gcc/doc/extend.texi: library.
    - @xref{OpenMP and OpenACC Options}, for additional options useful with
    - @option{-fopenacc}.
    + ## gcc/c/c-parser.cc ##
    +@@ gcc/c/c-parser.cc: c_parser_maxof_or_minof_expression (c_parser 
*parser, enum rid rid)
    +   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);
    ++      parens.skip_until_found_close (parser);
    +       goto fail;
    +     }
    +   type_name = c_parser_type_name (parser, true);
    +
    + ## gcc/testsuite/gcc.dg/maxof-compile.c ##
    +@@ gcc/testsuite/gcc.dg/maxof-compile.c: expr (void)
    +   int x;
      
    --@node _Countof
    --@section Determining the Number of Elements of Arrays
    --@cindex _Countof
    --@cindex number of elements
    --
    --The keyword @code{_Countof} determines
    --the number of elements of an array operand.
    --Its syntax is similar to @code{sizeof}.
    --The operand must be
    --a parenthesized complete array type name
    --or an expression of such a type.
    --For example:
    --
    --@smallexample
    --int a[n];
    --_Countof (a);  // returns n
    --_Countof (int [7][3]);  // returns 7
    --@end smallexample
    --
    --The result of this operator is an integer constant expression,
    --unless the array has a variable number of elements.
    --The operand is only evaluated
    --if the array has a variable number of elements.
    --For example:
    --
    --@smallexample
    --_Countof (int [7][n++]);  // integer constant expression
    --_Countof (int [n++][7]);  // run-time value; n++ is evaluated
    --@end smallexample
    --
    - @node Inline
    - @section An Inline Function is As Fast As a Macro
    - @cindex inline functions
    -@@ gcc/doc/extend.texi: C and/or C++ standards, while others remain 
specific to GNU C.
    - * Labels as Values::    Getting pointers to labels, and computed gotos.
    - * 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
    - * 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.
    -@@ gcc/doc/extend.texi: evaluated only once when using @code{__auto_type}, 
but twice if
    - @code{typeof} is used.
    - @end itemize
    - 
    -+@node _Countof
    -+@subsection Determining the Number of Elements of Arrays
    -+@findex _Countof
    -+@findex number of elements
    -+
    -+The keyword @code{_Countof} determines
    -+the number of elements of an array operand.
    -+Its syntax is similar to @code{sizeof}.
    -+The operand must be
    -+a parenthesized complete array type name
    -+or an expression of such a type.
    -+For example:
    -+
    -+@smallexample
    -+int a[n];
    -+_Countof (a);  // returns n
    -+_Countof (int [7][3]);  // returns 7
    -+@end smallexample
    -+
    -+The result of this operator is an integer constant expression,
    -+unless the array has a variable number of elements.
    -+The operand is only evaluated
    -+if the array has a variable number of elements.
    -+For example:
    -+
    -+@smallexample
    -+_Countof (int [7][n++]);  // integer constant expression
    -+_Countof (int [n++][7]);  // run-time value; n++ is evaluated
    -+@end smallexample
    -+
    - @node Offsetof
    - @subsection Support for @code{offsetof}
    - @findex __builtin_offsetof
    +   _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 } */
    ++  /* { dg-error "expected ')'" "syntax error" { target *-*-* } .-1 } */
    +   _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 } */
    ++  /* { dg-error "expected ')'" "syntax error" { target *-*-* } .-1 } */
    +   _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 } */
    ++  /* { dg-error "expected ')'" "syntax error" { target *-*-* } .-1 } */
    +   _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 } */
    ++  /* { dg-error "expected ')'" "syntax error" { target *-*-* } .-1 } */
    +   _Maxof 1;  /* { dg-error "expected '('" } */
    +   _Minof 1;  /* { dg-error "expected '('" } */
    +   _Maxof (int) {1};  /* { dg-error "expected ';'" } */
    +@@ gcc/testsuite/gcc.dg/maxof-compile.c: 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 } */
    ++  /* { dg-error "expected ')'" "syntax error" { target *-*-* } .-1 } */
    +   _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 } */
    ++  /* { dg-error "expected ')'" "syntax error" { target *-*-* } .-1 } */
    +   _Maxof (alignas(8) int);  /* { dg-error "alignment specified" } */
    +   _Minof (alignas(8) int);  /* { dg-error "alignment specified" } */
    + }
-- 
2.51.0


Reply via email to