On 10/8/25 6:56 PM, Jakub Jelinek wrote:
On Wed, Oct 08, 2025 at 03:13:31PM +0100, Jason Merrill wrote:
--- gcc/ginclude/stdarg.h.jj    2025-10-04 09:42:23.775001859 +0200
+++ gcc/ginclude/stdarg.h       2025-10-06 16:05:22.066861182 +0200
@@ -44,7 +44,8 @@ typedef __builtin_va_list __gnuc_va_list
      if this invocation was from the user program.  */
   #ifdef _STDARG_H
-#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#if (defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L) \
+    || __cplusplus + 0 >= 202400L

Why __cplusplus + 0?  I don't see that pattern anywhere else.

It was the first time I saw it as well, I thought there is some hidden
reason for it, but -Wundef warns about both #if foo >= 202400
and #if foo + 0 >= 202400 equally, so I've dropped it.
Most likely the header is just too old.

It is there in
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \
     || __cplusplus + 0 >= 201103L
#define va_copy(d,s)    __builtin_va_copy(d,s)
#endif

--- gcc/cp/parser.cc.jj 2025-10-04 09:50:00.063564536 +0200
+++ gcc/cp/parser.cc    2025-10-06 17:05:27.170484820 +0200
@@ -6407,6 +6407,118 @@ cp_parser_primary_expression (cp_parser
            return build_x_va_arg (combined_loc, expression, type);
          }
+       case RID_C23_VA_START:

Please factor this out into a separate function, with a grammar summary in
the comment.

Done.

Why not use cp_parser_skip_to_closing_parenthesis instead of this loop?
Needs a comment if there's a reason.

Added comment.  With the current wording which matches the C23 wording, e.g.
   va_start (ap, ()()()[[[}}});
and
   va_start (ap, ]]]]]]{{{{{{);
are valid (though we warn about those), all it requires that ()s are
balanced and all preprocessing tokens actually convertible to tokens.

+           location_t combined_loc
+             = make_location (arg_loc, start_loc, finish_loc);
+           parens.require_close (parser);

require_close returns the token, so it seems unnecessary to peek it first.

require_close returns the token or NULL, so I'd need to deal with what to
do if it returns NULL.

@@ -15324,7 +15326,9 @@ grokdeclarator (const cp_declarator *dec
                is_xobj_member_function = false;
              }
-           type = build_function_type (type, arg_types);
+           type = build_function_type (type, arg_types,
+                                       cxx_dialect >= cxx26
+                                       && arg_types == NULL_TREE);

How about adding cp_build_function_type to encapsulate this pattern?

Done.

OK, thanks.

2025-10-08  Jakub Jelinek  <[email protected]>

gcc/
        * ginclude/stdarg.h (va_start): Use __builtin_c23_va_start
        also for C++26.
        (__STDC_VERSION_STDARG_H__): Also define for C++26.
gcc/c-family/
        * c-common.h (D_CXX26): Define.
        * c-common.cc (c_common_resword): Add D_CXX26 to
        __builtin_c23_va_start flags, mention D_CXX26 in comment.
gcc/cp/
        * cp-tree.h (cp_build_function_type): Declare.
        * lex.cc: Implement va_start changes from P3348R4 - C++26 should
        refer to C23 not C17 paper.
        (init_reswords): Set D_CXX26 in mask for C++23 and older.
        * parser.cc (cp_parser_primary_expression): Handle RID_C23_VA_START.
        (cp_parser_builtin_c23_va_start): New function.
        * cp-objcp-common.cc (names_builtin_p): Likewise.
        * decl.cc (grokfndecl, check_function_type): Pass
        TYPE_NO_NAMED_ARGS_STDARG_P as last arg to build_function_type.
        (grokdeclarator, static_fn_type): Use cp_build_function_type instead
        of build_function_type.
        * typeck.cc (merge_types): Likewise.
        (structural_comptypes): Return false for TYPE_NO_NAMED_ARGS_STDARG_P
        differences.
        * lambda.cc (maybe_add_lambda_conv_op): Use cp_build_function_type
        instead of build_function_type.
        * tree.cc (cp_build_function_type): New function.
        (strip_typedefs): Pass TYPE_NO_NAMED_ARGS_STDARG_P as last arg to
        build_function_type.
        * name-lookup.cc (push_local_extern_decl_alias): Likewise.
        * module.cc (trees_in::tree_node): Use cp_build_function_type instead
        of build_function_type.
        * pt.cc (copy_default_args_to_explicit_spec,
        rebuild_function_or_method_type, build_deduction_guide): Likewise.
        (alias_ctad_tweaks): Pass TYPE_NO_NAMED_ARGS_STDARG_P as last arg to
        build_function_type.
        * decl2.cc (change_return_type, cp_reconstruct_complex_type):
        Likewise.
gcc/testsuite/
        * c-c++-common/cpp/has-builtin-4.c: Expect
        __has_builtin (__builtin_c23_va_start) == 1 also for C++26.
        * c-c++-common/Wvarargs.c (foo3): Don't expect undefined behavior
        warning for C++26.
        * g++.dg/cpp26/stdarg1.C: New test.
        * g++.dg/cpp26/stdarg2.C: New test.
        * g++.dg/cpp26/stdarg3.C: New test.
        * g++.dg/cpp26/stdarg4.C: New test.
        * g++.dg/cpp26/stdarg5.C: New test.
        * g++.dg/cpp26/stdarg6.C: New test.
        * g++.dg/cpp26/stdarg7.C: New test.
        * g++.dg/cpp26/stdarg8.C: New test.
        * g++.dg/cpp26/stdarg9.C: New test.
        * g++.dg/opt/pr60849.C (foo): Add explicit cast.

--- gcc/ginclude/stdarg.h.jj    2025-10-08 09:23:48.812694862 +0200
+++ gcc/ginclude/stdarg.h       2025-10-08 18:44:28.803856008 +0200
@@ -44,7 +44,8 @@ typedef __builtin_va_list __gnuc_va_list
     if this invocation was from the user program.  */
  #ifdef _STDARG_H
-#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#if (defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L) \
+    || __cplusplus >= 202400L
  #define va_start(...) __builtin_c23_va_start(__VA_ARGS__)
  #else
  #define va_start(v,l) __builtin_va_start(v,l)
@@ -125,7 +126,8 @@ typedef __gnuc_va_list va_list;
#endif /* not __svr4__ */ -#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#if (defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L) \
+    || __cplusplus >= 202400L
  #define __STDC_VERSION_STDARG_H__     202311L
  #endif
--- gcc/c-family/c-common.h.jj 2025-10-08 09:23:47.940706893 +0200
+++ gcc/c-family/c-common.h     2025-10-08 18:43:37.988553400 +0200
@@ -448,6 +448,7 @@ extern machine_mode c_default_pointer_mo
  #define D_CXX20               0x8000  /* In C++, C++20 only.  */
  #define D_CXX_COROUTINES 0x10000  /* In C++, only with coroutines.  */
  #define D_CXX_MODULES 0x20000  /* In C++, only with modules.  */
+#define D_CXX26         0x40000        /* In C++, C++26 only.  */
#define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS
  #define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T
--- gcc/c-family/c-common.cc.jj 2025-10-08 09:23:47.891707569 +0200
+++ gcc/c-family/c-common.cc    2025-10-08 18:43:37.990553372 +0200
@@ -376,9 +376,10 @@ static bool nonnull_check_p (tree, unsig
     C --std=c17: D_C23 | D_CXXONLY | D_OBJC
     C --std=c23: D_CXXONLY | D_OBJC
     ObjC is like C except that D_OBJC and D_CXX_OBJC are not set
-   C++ --std=c++98: D_CONLY | D_CXX11 | D_CXX20 | D_OBJC
-   C++ --std=c++11: D_CONLY | D_CXX20 | D_OBJC
-   C++ --std=c++20: D_CONLY | D_OBJC
+   C++ --std=c++98: D_CONLY | D_CXX11 | D_CXX20 | D_CXX26 | D_OBJC
+   C++ --std=c++11: D_CONLY | D_CXX20 | D_CXX26 | D_OBJC
+   C++ --std=c++20: D_CONLY | D_CXX26 | D_OBJC
+   C++ --std=c++26: D_CONLY | D_OBJC
     ObjC++ is like C++ except that D_OBJC is not set
If -fno-asm is used, D_ASM is added to the mask. If
@@ -462,7 +463,7 @@ const struct c_common_resword c_common_r
    { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY },
    { "__builtin_offsetof", RID_OFFSETOF, 0 },
    { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
-  { "__builtin_c23_va_start", RID_C23_VA_START,      D_C23 },
+  { "__builtin_c23_va_start", RID_C23_VA_START,      D_C23 | D_CXX26 },
    { "__builtin_va_arg",     RID_VA_ARG,     0 },
    { "__complex",    RID_COMPLEX,    0 },
    { "__complex__",  RID_COMPLEX,    0 },
--- gcc/cp/cp-tree.h.jj 2025-10-08 17:46:23.319698090 +0200
+++ gcc/cp/cp-tree.h    2025-10-08 19:36:19.714162019 +0200
@@ -8491,6 +8491,7 @@ extern tree cp_build_reference_type               (tr
  extern tree move                              (tree);
  extern tree cp_build_qualified_type           (tree, int,
                                                 tsubst_flags_t = 
tf_warning_or_error);
+extern tree cp_build_function_type             (tree, tree);
  extern bool cv_qualified_p                    (const_tree);
  extern tree cv_unqualified                    (tree);
  extern special_function_kind special_function_p (const_tree);
--- gcc/cp/lex.cc.jj    2025-10-08 09:23:48.434700078 +0200
+++ gcc/cp/lex.cc       2025-10-08 18:43:37.990553372 +0200
@@ -243,6 +243,8 @@ init_reswords (void)
      mask |= D_CXX11;
    if (cxx_dialect < cxx20)
      mask |= D_CXX20;
+  if (cxx_dialect < cxx26)
+    mask |= D_CXX26;
    if (!flag_concepts)
      mask |= D_CXX_CONCEPTS;
    if (!flag_coroutines)
--- gcc/cp/parser.cc.jj 2025-10-08 09:23:48.654697042 +0200
+++ gcc/cp/parser.cc    2025-10-08 19:28:36.930512900 +0200
@@ -2575,6 +2575,7 @@ static cp_expr cp_parser_expression
    (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = 
false);
  static cp_expr cp_parser_constant_expression
    (cp_parser *, int = 0, bool * = NULL, bool = false);
+static cp_expr cp_parser_builtin_c23_va_start (cp_parser *);
  static cp_expr cp_parser_builtin_offsetof
    (cp_parser *);
  static cp_expr cp_parser_lambda_expression
@@ -6407,6 +6408,9 @@ cp_parser_primary_expression (cp_parser
            return build_x_va_arg (combined_loc, expression, type);
          }
+ case RID_C23_VA_START:
+         return cp_parser_builtin_c23_va_start (parser);
+
        case RID_OFFSETOF:
          return cp_parser_builtin_offsetof (parser);
@@ -11497,6 +11501,133 @@ cp_parser_constant_expression (cp_parser
    return expression;
  }
+/* Parse __builtin_c23_va_start.
+
+   c23-va-start-expression:
+     __builtin_c23_va_start ( assignment-expression )
+     __builtin_c23_va_start ( assignment-expression , identifier )
+     __builtin_c23_va_start ( assignment-expression , tokens[opt] )
+
+   The first form is the expected new C++26 form, the second if
+   identifier is the name of the last parameter before ... is meant
+   for backwards compatibility with C++23 and older.
+   The third form where LWG4388 requires all the preprocessing tokens
+   to be convertible to tokens and it can't contain unbalanced
+   parentheses is parsed with a warning and the tokens are just skipped.
+   This is because C++26 like C23 defines va_start macro as
+   va_start (ap, ...) and says second and later arguments to the macro
+   are discarded, yet we want to diagnose when people use something
+   which wasn't valid before C++26 and is not the single argument
+   va_start either.  */
+
+static cp_expr
+cp_parser_builtin_c23_va_start (cp_parser *parser)
+{
+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
+  cp_lexer_consume_token (parser->lexer);
+  /* Look for the opening `('.  */
+  matching_parens parens;
+  parens.require_open (parser);
+  location_t arg_loc = cp_lexer_peek_token (parser->lexer)->location;
+  /* Now, parse the assignment-expression.  */
+  tree expression = cp_parser_assignment_expression (parser);
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+    {
+      location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
+      if (!cp_parser_require (parser, CPP_COMMA, RT_COMMA))
+       {
+         cp_parser_skip_to_closing_parenthesis (parser, false, false,
+                                                /*consume_paren=*/ true);
+         return error_mark_node;
+       }
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+         && cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN))
+       {
+         tree name = cp_lexer_peek_token (parser->lexer)->u.value;
+         location_t nloc = cp_lexer_peek_token (parser->lexer)->location;
+         tree decl = lookup_name (name);
+         tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
+         if (!last_parm || decl != last_parm)
+           warning_at (nloc, OPT_Wvarargs, "optional second parameter of "
+                       "%<va_start%> not last named argument");
+         else
+           {
+             /* __builtin_va_start parsing does mark the argument as used and
+                read, for -Wunused* purposes mark it the same.  */
+             TREE_USED (last_parm) = 1;
+             mark_exp_read (last_parm);
+           }
+         cp_lexer_consume_token (parser->lexer);
+       }
+      else
+       {
+         unsigned nesting_depth = 0;
+         location_t sloc = cp_lexer_peek_token (parser->lexer)->location;
+         location_t eloc = sloc;
+
+         /* For va_start (ap,) the ) comes from stdarg.h.
+            Use location of , in that case, otherwise without -Wsystem-headers
+            nothing is reported.  After all, the problematic token is the
+            comma in that case.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+           sloc = eloc = cloc;
+         /* Not using cp_parser_skip_to_closing_parenthesis here, because
+            the tokens in second and further arguments don't have to be
+            fully balanced, only can't contain unbalanced parentheses.
+            So, va_start (ap, [[[[[[[[[{{{{{{{{{}]);
+            is valid C++ for which we want to warn,
+            #define X id); something (
+            va_start (ap, X);
+            is IFNDR (not detectable unless the preprocessor special cases
+            va_start macro).  */
+         while (true)
+           {
+             cp_token *token = cp_lexer_peek_token (parser->lexer);
+             if (token->type == CPP_CLOSE_PAREN && !nesting_depth)
+               break;
+
+             if (token->type == CPP_EOF)
+               break;
+             if (token->type == CPP_OPEN_PAREN)
+               ++nesting_depth;
+             else if (token->type == CPP_CLOSE_PAREN)
+               --nesting_depth;
+             else if (token->type == CPP_PRAGMA)
+               {
+                 cp_parser_skip_to_pragma_eol (parser, token);
+                 continue;
+               }
+             eloc = token->location;
+             cp_lexer_consume_token (parser->lexer);
+           }
+         if (sloc != eloc)
+           sloc = make_location (sloc, sloc, eloc);
+         warning_at (sloc, OPT_Wvarargs,
+                     "%<va_start%> macro used with additional "
+                     "arguments other than identifier of the "
+                     "last named argument");
+       }
+    }
+  /* Look for the closing `)'.  */
+  location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
+  /* Construct a location of the form:
+     __builtin_c23_va_start (ap, arg)
+     ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
+     with the caret at the first argument, ranging from the start
+     of the "__builtin_c23_va_start" token to the close paren.  */
+  location_t combined_loc = make_location (arg_loc, start_loc, finish_loc);
+  parens.require_close (parser);
+  tree fndecl = builtin_decl_explicit (BUILT_IN_VA_START);
+  releasing_vec args;
+  vec_safe_push (args, expression);
+  vec_safe_push (args, integer_zero_node);
+  tree ret = finish_call_expr (fndecl, &args, false, true,
+                              tf_warning_or_error);
+  if (TREE_CODE (ret) == CALL_EXPR)
+    SET_EXPR_LOCATION (ret, combined_loc);
+  return cp_expr (ret, combined_loc);
+}      
+
  /* Parse __builtin_offsetof.
offsetof-expression:
--- gcc/cp/cp-objcp-common.cc.jj        2025-10-08 09:23:48.066705154 +0200
+++ gcc/cp/cp-objcp-common.cc   2025-10-08 18:43:37.997553276 +0200
@@ -588,6 +588,7 @@ names_builtin_p (const char *name)
      case RID_BUILTIN_BIT_CAST:
      case RID_OFFSETOF:
      case RID_VA_ARG:
+    case RID_C23_VA_START:
        return 1;
      case RID_BUILTIN_OPERATOR_NEW:
      case RID_BUILTIN_OPERATOR_DELETE:
--- gcc/cp/decl.cc.jj   2025-10-08 09:23:48.125704341 +0200
+++ gcc/cp/decl.cc      2025-10-08 19:33:17.164667187 +0200
@@ -12413,11 +12413,13 @@ grokfndecl (tree ctype,
        if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
                        integer_type_node))
        {
-         tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
+         tree dtype = TREE_TYPE (decl);
+         tree oldtypeargs = TYPE_ARG_TYPES (dtype);
          tree newtype;
          error_at (declspecs->locations[ds_type_spec],
                    "%<::main%> must return %<int%>");
-         newtype = build_function_type (integer_type_node, oldtypeargs);
+         newtype = build_function_type (integer_type_node, oldtypeargs,
+                                        TYPE_NO_NAMED_ARGS_STDARG_P (dtype));
          TREE_TYPE (decl) = newtype;
        }
        if (warn_main)
@@ -15324,7 +15326,7 @@ grokdeclarator (const cp_declarator *dec
                is_xobj_member_function = false;
              }
- type = build_function_type (type, arg_types);
+           type = cp_build_function_type (type, arg_types);
tree attrs = declarator->std_attributes;
            if (tx_qual)
@@ -19312,7 +19314,8 @@ check_function_type (tree decl, tree cur
                                             void_type_node,
                                             TREE_CHAIN (args));
        else
-       fntype = build_function_type (void_type_node, args);
+       fntype = build_function_type (void_type_node, args,
+                                     TYPE_NO_NAMED_ARGS_STDARG_P (fntype));
        fntype = (cp_build_type_attribute_variant
                (fntype, TYPE_ATTRIBUTES (TREE_TYPE (decl))));
        fntype = cxx_copy_lang_qualifiers (fntype, TREE_TYPE (decl));
@@ -20809,7 +20812,7 @@ static_fn_type (tree memfntype)
      return memfntype;
    gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
    args = TYPE_ARG_TYPES (memfntype);
-  fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
+  fntype = cp_build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
    fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype));
    fntype = (cp_build_type_attribute_variant
            (fntype, TYPE_ATTRIBUTES (memfntype)));
--- gcc/cp/typeck.cc.jj 2025-10-08 09:23:48.739695870 +0200
+++ gcc/cp/typeck.cc    2025-10-08 19:35:25.593904723 +0200
@@ -1035,7 +1035,7 @@ merge_types (tree t1, tree t2)
        gcc_assert (quals == type_memfn_quals (t2));
        gcc_assert (rqual == type_memfn_rqual (t2));
- tree rval = build_function_type (valtype, parms);
+       tree rval = cp_build_function_type (valtype, parms);
        rval = apply_memfn_quals (rval, quals);
        tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
                                                  TYPE_RAISES_EXCEPTIONS (t2));
@@ -1058,10 +1058,10 @@ merge_types (tree t1, tree t2)
        /* If this was a member function type, get back to the
           original type of type member function (i.e., without
           the class instance variable up front.  */
-       t1 = build_function_type (TREE_TYPE (t1),
-                                 TREE_CHAIN (TYPE_ARG_TYPES (t1)));
-       t2 = build_function_type (TREE_TYPE (t2),
-                                 TREE_CHAIN (TYPE_ARG_TYPES (t2)));
+       t1 = cp_build_function_type (TREE_TYPE (t1),
+                                    TREE_CHAIN (TYPE_ARG_TYPES (t1)));
+       t2 = cp_build_function_type (TREE_TYPE (t2),
+                                    TREE_CHAIN (TYPE_ARG_TYPES (t2)));
        t3 = merge_types (t1, t2);
        t3 = build_method_type_directly (basetype, TREE_TYPE (t3),
                                         TYPE_ARG_TYPES (t3));
@@ -1550,8 +1550,11 @@ structural_comptypes (tree t1, tree t2,
        return false;
        break;
- case METHOD_TYPE:
      case FUNCTION_TYPE:
+      if (TYPE_NO_NAMED_ARGS_STDARG_P (t1) != TYPE_NO_NAMED_ARGS_STDARG_P (t2))
+       return false;
+      /* FALLTHRU */
+    case METHOD_TYPE:
        /* Exception specs and memfn_rquals were checked above.  */
        if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
        return false;
--- gcc/cp/lambda.cc.jj 2025-10-08 09:23:48.364701044 +0200
+++ gcc/cp/lambda.cc    2025-10-08 19:33:52.778178456 +0200
@@ -1329,9 +1329,10 @@ maybe_add_lambda_conv_op (tree type)
      }
tree stattype
-    = build_function_type (fn_result, FUNCTION_FIRST_USER_PARMTYPE (callop));
-  stattype = (cp_build_type_attribute_variant
-             (stattype, TYPE_ATTRIBUTES (optype)));
+    = cp_build_function_type (fn_result,
+                             FUNCTION_FIRST_USER_PARMTYPE (callop));
+  stattype = cp_build_type_attribute_variant (stattype,
+                                             TYPE_ATTRIBUTES (optype));
    if (flag_noexcept_type
        && TYPE_NOTHROW_P (TREE_TYPE (callop)))
      stattype = build_exception_variant (stattype, noexcept_true_spec);
--- gcc/cp/tree.cc.jj   2025-10-08 09:23:48.733695953 +0200
+++ gcc/cp/tree.cc      2025-10-08 19:31:49.907864636 +0200
@@ -1537,6 +1537,19 @@ cp_build_qualified_type (tree type, int
    return result;
  }
+/* Return a FUNCTION_TYPE for a function returning VALUE_TYPE
+   with ARG_TYPES arguments.  Wrapper around build_function_type
+   which ensures TYPE_NO_NAMED_ARGS_STDARG_P is set if ARG_TYPES
+   is NULL for C++26.  */
+
+tree
+cp_build_function_type (tree value_type, tree arg_types)
+{
+  return build_function_type (value_type, arg_types,
+                             cxx_dialect >= cxx26
+                             && arg_types == NULL_TREE);
+}
+
  /* Return TYPE with const and volatile removed.  */
tree
@@ -1782,7 +1795,8 @@ strip_typedefs (tree t, bool *remove_att
          }
        else
          {
-           result = build_function_type (type, arg_types);
+           result = build_function_type (type, arg_types,
+                                         TYPE_NO_NAMED_ARGS_STDARG_P (t));
            result = apply_memfn_quals (result, type_memfn_quals (t));
          }
--- gcc/cp/name-lookup.cc.jj 2025-10-08 09:23:48.588697953 +0200
+++ gcc/cp/name-lookup.cc       2025-10-08 18:43:38.003553194 +0200
@@ -3726,7 +3726,11 @@ push_local_extern_decl_alias (tree decl)
                          chain = &TREE_CHAIN (*chain);
                        }
- tree fn_type = build_function_type (TREE_TYPE (type), nargs);
+                   bool no_named_args_stdarg
+                     = TYPE_NO_NAMED_ARGS_STDARG_P (type);
+                   tree fn_type
+                     = build_function_type (TREE_TYPE (type), nargs,
+                                            no_named_args_stdarg);
fn_type = apply_memfn_quals
                      (fn_type, type_memfn_quals (type));
--- gcc/cp/module.cc.jj 2025-10-08 09:24:14.666338175 +0200
+++ gcc/cp/module.cc    2025-10-08 19:34:04.217021479 +0200
@@ -10414,7 +10414,7 @@ trees_in::tree_node (bool is_use)
                  if (klass)
                    res = build_method_type_directly (klass, res, args);
                  else
-                   res = build_function_type (res, args);
+                   res = cp_build_function_type (res, args);
                }
            }
            break;
--- gcc/cp/pt.cc.jj     2025-10-08 17:46:17.919772189 +0200
+++ gcc/cp/pt.cc        2025-10-08 19:34:34.908600297 +0200
@@ -2654,8 +2654,7 @@ copy_default_args_to_explicit_spec (tree
                                             new_spec_types);
      }
    else
-    new_type = build_function_type (TREE_TYPE (old_type),
-                                   new_spec_types);
+    new_type = cp_build_function_type (TREE_TYPE (old_type), new_spec_types);
    new_type = cp_build_type_attribute_variant (new_type,
                                              TYPE_ATTRIBUTES (old_type));
    new_type = cxx_copy_lang_qualifiers (new_type, old_type);
@@ -14779,7 +14778,7 @@ rebuild_function_or_method_type (tree t,
    tree new_type;
    if (TREE_CODE (t) == FUNCTION_TYPE)
      {
-      new_type = build_function_type (return_type, arg_types);
+      new_type = cp_build_function_type (return_type, arg_types);
        new_type = apply_memfn_quals (new_type, type_memfn_quals (t));
      }
    else
@@ -31100,7 +31099,7 @@ build_deduction_guide (tree type, tree c
        = copy_node (INNERMOST_TEMPLATE_PARMS (tparms));
      }
- tree fntype = build_function_type (type, fparms);
+  tree fntype = cp_build_function_type (type, fparms);
    tree ded_fn = build_lang_decl_loc (loc,
                                     FUNCTION_DECL,
                                     dguide_name (type), fntype);
@@ -31532,7 +31531,8 @@ alias_ctad_tweaks (tree tmpl, tree uguid
          tree fntype = TREE_TYPE (fprime);
          ret = lookup_template_class (TPARMS_PRIMARY_TEMPLATE (atparms), targs,
                                       in_decl, NULL_TREE, complain);
-         fntype = build_function_type (ret, TYPE_ARG_TYPES (fntype));
+         fntype = build_function_type (ret, TYPE_ARG_TYPES (fntype),
+                                       TYPE_NO_NAMED_ARGS_STDARG_P (fntype));
          TREE_TYPE (fprime) = fntype;
          if (TREE_CODE (fprime) == TEMPLATE_DECL)
            TREE_TYPE (DECL_TEMPLATE_RESULT (fprime)) = fntype;
--- gcc/cp/decl2.cc.jj  2025-10-08 09:23:48.248702644 +0200
+++ gcc/cp/decl2.cc     2025-10-08 18:43:38.009553111 +0200
@@ -233,7 +233,8 @@ change_return_type (tree new_ret, tree f
if (TREE_CODE (fntype) == FUNCTION_TYPE)
      {
-      newtype = build_function_type (new_ret, args);
+      newtype = build_function_type (new_ret, args,
+                                    TYPE_NO_NAMED_ARGS_STDARG_P (fntype));
        newtype = apply_memfn_quals (newtype,
                                   type_memfn_quals (fntype));
      }
@@ -1698,7 +1699,8 @@ cp_reconstruct_complex_type (tree type,
    else if (TREE_CODE (type) == FUNCTION_TYPE)
      {
        inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
-      outer = build_function_type (inner, TYPE_ARG_TYPES (type));
+      outer = build_function_type (inner, TYPE_ARG_TYPES (type),
+                                  TYPE_NO_NAMED_ARGS_STDARG_P (type));
        outer = apply_memfn_quals (outer, type_memfn_quals (type));
      }
    else if (TREE_CODE (type) == METHOD_TYPE)
--- gcc/testsuite/c-c++-common/cpp/has-builtin-4.c.jj   2025-10-08 
09:23:48.937693138 +0200
+++ gcc/testsuite/c-c++-common/cpp/has-builtin-4.c      2025-10-08 
18:43:38.025552892 +0200
@@ -9,7 +9,7 @@
  #if __has_builtin (__builtin_va_arg) != 1
  #error "no __builtin_va_arg"
  #endif
-#if __STDC_VERSION__ >= 202311L
+#if (__STDC_VERSION__ >= 202311L || __cplusplus >= 202400L)
  #if __has_builtin (__builtin_c23_va_start) != 1
  #error "no __builtin_c23_va_start"
  #endif
--- gcc/testsuite/c-c++-common/Wvarargs.c.jj    2025-10-08 09:23:48.906693566 
+0200
+++ gcc/testsuite/c-c++-common/Wvarargs.c       2025-10-08 18:43:38.037552727 
+0200
@@ -50,6 +50,6 @@ foo3 (int a, register int b, ...)     // { d
  {
      va_list vp;
      /* 'b' is declared with register storage, so warn.  */
-    va_start (vp, b); /* { dg-warning "undefined behavior" } */
+    va_start (vp, b); /* { dg-warning "undefined behavior" "" { target { c || 
c++23_down } } } */
      va_end (vp);
  }
--- gcc/testsuite/g++.dg/cpp26/stdarg1.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg1.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,158 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do run { target c++26 } }
+
+#include <stdarg.h>
+
+double
+f (...)
+{
+  va_list ap;
+  va_start (ap);
+  double ret = va_arg (ap, int);
+  ret += va_arg (ap, double);
+  ret += va_arg (ap, int);
+  ret += va_arg (ap, double);
+  va_end (ap);
+  return ret;
+}
+
+void
+g (...)
+{
+  va_list ap;
+  va_start (ap, random ! ignored, ignored ** text);    // { dg-warning "'va_start' 
macro used with additional arguments other than identifier of the last named 
argument" }
+  for (int i = 0; i < 10; i++)
+    if (va_arg (ap, double) != i)
+      __builtin_abort ();
+  va_end (ap);
+}
+
+void
+h1 (int x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+void
+h2 (int x(), ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+void
+h3 (int x[10], ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+void
+h4 (char x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+void
+h5 (float x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+void
+h6 (long x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+struct s { char c[1000]; };
+
+void
+h7 (struct s x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+}
+
+int
+main ()
+{
+  if (f (1, 2.0, 3, 4.0) != 10.0)
+    __builtin_abort ();
+  g (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
+  g (0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f);
+  h1 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  h2 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  h3 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  h4 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  h5 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  h6 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  h7 (s {}, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+}
--- gcc/testsuite/g++.dg/cpp26/stdarg2.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg2.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,212 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do run { target c++26 } }
+
+#include <stdarg.h>
+
+struct s { char c[1000]; };
+
+struct s
+f (...)
+{
+  va_list ap;
+  va_start (ap);
+  double r = va_arg (ap, int);
+  r += va_arg (ap, double);
+  r += va_arg (ap, int);
+  r += va_arg (ap, double);
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = r;
+  ret.c[999] = 42;
+  return ret;
+}
+
+struct s
+g (...)
+{
+  va_list ap;
+  va_start (ap, random ! ignored, ignored ** text);    // { dg-warning "'va_start' 
macro used with additional arguments other than identifier of the last named 
argument" }
+  for (int i = 0; i < 10; i++)
+    if (va_arg (ap, double) != i)
+      __builtin_abort ();
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 17;
+  ret.c[999] = 58;
+  return ret;
+}
+
+struct s
+h1 (int x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 32;
+  ret.c[999] = 95;
+  return ret;
+}
+
+struct s
+h2 (int x(), ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 5;
+  ret.c[999] = 125;
+  return ret;
+}
+
+struct s
+h3 (int x[10], ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 8;
+  ret.c[999] = 12;
+  return ret;
+}
+
+struct s
+h4 (char x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 18;
+  ret.c[999] = 28;
+  return ret;
+}
+
+struct s
+h5 (float x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 38;
+  ret.c[999] = 48;
+  return ret;
+}
+
+struct s
+h6 (long x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 58;
+  ret.c[999] = 68;
+  return ret;
+}
+
+struct s
+h7 (struct s x, ...)
+{
+  va_list ap;
+  va_start (ap);
+  for (int i = 0; i < 10; i++)
+    {
+      if (va_arg (ap, double) != i)
+       __builtin_abort ();
+      i++;
+      if (va_arg (ap, int) != i)
+       __builtin_abort ();
+    }
+  va_end (ap);
+  struct s ret = {};
+  ret.c[0] = 78;
+  ret.c[999] = 88;
+  return ret;
+}
+
+int
+main ()
+{
+  struct s x = f (1, 2.0, 3, 4.0);
+  if (x.c[0] != 10 || x.c[999] != 42)
+    __builtin_abort ();
+  x = g (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
+  if (x.c[0] != 17 || x.c[999] != 58)
+    __builtin_abort ();
+  x = g (0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f);
+  if (x.c[0] != 17 || x.c[999] != 58)
+    __builtin_abort ();
+  x = h1 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 32 || x.c[999] != 95)
+    __builtin_abort ();
+  x = h2 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 5 || x.c[999] != 125)
+    __builtin_abort ();
+  x = h3 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 8 || x.c[999] != 12)
+    __builtin_abort ();
+  x = h4 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 18 || x.c[999] != 28)
+    __builtin_abort ();
+  x = h5 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 38 || x.c[999] != 48)
+    __builtin_abort ();
+  x = h6 (0, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 58 || x.c[999] != 68)
+    __builtin_abort ();
+  x = h7 (s {}, 0.0, 1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9);
+  if (x.c[0] != 78 || x.c[999] != 88)
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp26/stdarg3.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg3.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,7 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-O2" }
+
+#include "stdarg1.C"
+
+// { dg-warning "'va_start' macro used with additional arguments other than identifier of the 
last named argument" "" { target *-*-* } 0 }
--- gcc/testsuite/g++.dg/cpp26/stdarg4.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg4.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,7 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-O2" }
+
+#include "stdarg2.C"
+
+// { dg-warning "'va_start' macro used with additional arguments other than identifier of the 
last named argument" "" { target *-*-* } 0 }
--- gcc/testsuite/g++.dg/cpp26/stdarg5.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg5.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,5 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-O2" }
+
+#include "../../gcc.dg/c23-stdarg-9.c"
--- gcc/testsuite/g++.dg/cpp26/stdarg6.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg6.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,112 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-O2" }
+
+#include <stdarg.h>
+
+int i;
+
+void
+f0 (...)
+{
+  va_list ap;
+  va_start (ap);
+  va_end (ap);
+}
+
+void
+f1 (...)
+{
+  va_list ap;
+  va_start (ap, i);                            // { dg-warning "optional second 
parameter of 'va_start' not last named argument" }
+  va_end (ap);
+}
+
+void
+f2 (...)
+{
+  int j = 0;
+  va_list ap;
+  va_start (ap, j);                            // { dg-warning "optional second 
parameter of 'va_start' not last named argument" }
+  va_end (ap);
+}
+
+void
+f3 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, k);                            // { dg-warning "optional second 
parameter of 'va_start' not last named argument" }
+  va_end (ap);
+}
+
+void
+f4 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, l);
+  va_end (ap);
+}
+
+void
+f5 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, (int) l);                      // { dg-warning "'va_start' macro 
used with additional arguments other than identifier of the last named argument" }
+  va_end (ap);
+}
+
+void
+f6 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, l + 0);                                // { dg-warning "'va_start' 
macro used with additional arguments other than identifier of the last named 
argument" }
+  va_end (ap);
+}
+
+void
+f7 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, ()()(), [][][], {}{}{}, *+-/1({[_*_]})%&&!?!?);        // { dg-warning 
"'va_start' macro used with additional arguments other than identifier of the last named 
argument" }
+  va_end (ap);
+}
+
+void
+f8 (...)
+{
+  va_list ap;
+  va_start (ap,);                              // { dg-warning "'va_start' macro 
used with additional arguments other than identifier of the last named argument" }
+  va_end (ap);
+}
+
+void
+f9 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, k+l+****2);                    // { dg-warning "'va_start' macro 
used with additional arguments other than identifier of the last named argument" }
+  va_end (ap);
+}
+
+void
+f10 (int m, ...)
+{
+  va_list ap;
+  va_start (ap, m);
+  va_end (ap);
+}
+
+void
+f11 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, ()()()[[[}}});                 // { dg-warning "'va_start' macro 
used with additional arguments other than identifier of the last named argument" }
+  va_end (ap);
+}
+
+void
+f12 (int k, int l, ...)
+{
+  va_list ap;
+  va_start (ap, ]]]]]]{{{{{{);                 // { dg-warning "'va_start' macro 
used with additional arguments other than identifier of the last named argument" }
+  va_end (ap);
+}
--- gcc/testsuite/g++.dg/cpp26/stdarg7.C.jj     2025-10-08 18:43:38.037552727 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg7.C        2025-10-08 18:43:38.037552727 
+0200
@@ -0,0 +1,11 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-O2" }
+
+#include <stdarg.h>
+
+void
+f (...)
+{
+  va_start (); // { dg-error "expected primary-expression before '\\\)' token" 
}
+}
--- gcc/testsuite/g++.dg/cpp26/stdarg8.C.jj     2025-10-08 18:43:38.038552713 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg8.C        2025-10-08 18:43:38.038552713 
+0200
@@ -0,0 +1,26 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do run { target c++26 } }
+
+#include <stdarg.h>
+
+int
+main ()
+{
+  int v = 0;
+  auto a = [&] (...) {
+    va_list ap;
+    va_start (ap);
+    int b = 42;
+    if (v)
+      b = va_arg (ap, int);
+    va_end (ap);
+    return b;
+  };
+  if (a () != 42)
+    __builtin_abort ();
+  v = 1;
+  if (a (1, 2) != 1)
+    __builtin_abort ();
+  if (a (13, 2.0f, 2ULL) != 13)
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp26/stdarg9.C.jj     2025-10-08 18:43:38.038552713 
+0200
+++ gcc/testsuite/g++.dg/cpp26/stdarg9.C        2025-10-08 18:43:38.038552713 
+0200
@@ -0,0 +1,16 @@
+// P3348R4 - C++26 should refer to C23 not C17
+// { dg-do compile }
+
+#include <stdarg.h>
+
+#if __cplusplus >= 202400L
+#ifndef __STDC_VERSION_STDARG_H__
+#error __STDC_VERSION_STDARG_H__ not defined for C++26
+#elif __STDC_VERSION_STDARG_H__ != 202311L
+#error Unexpected __STDC_VERSION_STDARG_H__ value
+#endif
+#else
+#ifdef __STDC_VERSION_STDARG_H__
+#error __STDC_VERSION_STDARG_H__ defined for C++ < 26
+#endif
+#endif
--- gcc/testsuite/g++.dg/opt/pr60849.C.jj       2025-10-08 09:23:48.978692572 
+0200
+++ gcc/testsuite/g++.dg/opt/pr60849.C  2025-10-08 18:43:38.047552590 +0200
@@ -7,7 +7,7 @@ extern "C" int isnan ();
void foo(float a) {
    int (*xx)(...);
-  xx = isnan;
+  xx = (int (*)(...)) isnan;
    if (xx(a))
      g++;
  }


        Jakub


Reply via email to