c: Add -std=c2y, -std=gnu2y, -Wc23-c2y-compat, C2Y _Generic with type operand

The first new C2Y feature, _Generic where the controlling operand is a
type name rather than an expression (as defined in N3260), was voted
into C2Y today.  (In particular, this form of _Generic allows
distinguishing qualified and unqualified versions of a type.)  This
feature also includes allowing the generic associations to specify
incomplete and function types.

Add this feature to GCC, along with the -std=c2y, -std=gnu2y and
-Wc23-c2y-compat options to control when and how it is diagnosed.  As
usual, the feature is allowed by default in older standards modes,
subject to diagnosis with -pedantic, -pedantic-errors or
-Wc23-c2y-compat.

Bootstrapped with no regressions on x86_64-pc-linux-gnu.

gcc/
	* doc/cpp.texi (__STDC_VERSION__): Document C2Y handling.
	* doc/invoke.texi (-Wc23-c2y-compat, -std=c2y, -std=gnu2y):
	Document options.
	(-std=gnu23): Update documentation.
	* doc/standards.texi (C Language): Document C2Y.  Update C23
	description.
	* config/rl78/rl78.cc (rl78_option_override): Handle "GNU C2Y"
	language name.
	* dwarf2out.cc (highest_c_language, gen_compile_unit_die):
	Likewise.

gcc/c-family/
	* c-common.cc (flag_isoc2y): New.
	(flag_isoc99, flag_isoc11, flag_isoc23): Update comments.
	* c-common.h (flag_isoc2y): New.
	(clk_c, flag_isoc23): Update comments.
	* c-opts.cc (set_std_c2y): New.
	(c_common_handle_option): Handle OPT_std_c2y and OPT_std_gnu2y.
	(set_std_c89, set_std_c99, set_std_c11, set_std_c17, set_std_c23):
	Set flag_isoc2y.
	(set_std_c23): Update comment.
	* c.opt (Wc23-c2y-compat, std=c2y, std=gnu2y): New.
	* c.opt.urls: Regenerate.

gcc/c/
	* c-errors.cc (pedwarn_c23): New.
	* c-parser.cc (disable_extension_diagnostics)
	(restore_extension_diagnostics): Save and restore
	warn_c23_c2y_compat.
	(c_parser_generic_selection): Handle type name as controlling
	operand.  Allow incomplete and function types subject to
	pedwarn_c23 calls.
	* c-tree.h (pedwarn_c23): New.

gcc/testsuite/
	* gcc.dg/c23-generic-1.c, gcc.dg/c23-generic-2.c,
	gcc.dg/c23-generic-3.c, gcc.dg/c23-generic-4.c,
	gcc.dg/c2y-generic-1.c, gcc.dg/c2y-generic-2.c,
	gcc.dg/c2y-generic-3.c, gcc.dg/gnu2y-generic-1.c: New tests.
	* gcc.dg/c23-tag-6.c: Use -pedantic-errors.

libcpp/
	* include/cpplib.h (CLK_GNUC2Y, CLK_STDC2Y): New.
	* init.cc (lang_defaults): Add GNUC2Y and STDC2Y entries.
	(cpp_init_builtins): Define __STDC_VERSION__ to 202500L for GNUC2Y
	and STDC2Y.
This commit is contained in:
Joseph Myers 2024-06-11 23:00:04 +00:00
parent 6bc26cceb2
commit 0cf68222d2
24 changed files with 322 additions and 39 deletions

View File

@ -216,18 +216,22 @@ int flag_cond_mismatch;
int flag_isoc94;
/* Nonzero means use the ISO C99 (or C11) dialect of C. */
/* Nonzero means use the ISO C99 (or later) dialect of C. */
int flag_isoc99;
/* Nonzero means use the ISO C11 dialect of C. */
/* Nonzero means use the ISO C11 (or later) dialect of C. */
int flag_isoc11;
/* Nonzero means use the ISO C23 dialect of C. */
/* Nonzero means use the ISO C23 (or later) dialect of C. */
int flag_isoc23;
/* Nonzero means use the ISO C2Y (or later) dialect of C. */
int flag_isoc2y;
/* Nonzero means that we have builtin functions, and main is an int. */
int flag_hosted = 1;

View File

@ -531,7 +531,7 @@ extern GTY(()) tree c_global_trees[CTI_MAX];
enum c_language_kind
{
clk_c = 0, /* C90, C94, C99, C11 or C23 */
clk_c = 0, /* C without ObjC features. */
clk_objc = 1, /* clk_c with ObjC features. */
clk_cxx = 2, /* ANSI/ISO C++ */
clk_objcxx = 3 /* clk_cxx with ObjC features. */
@ -676,10 +676,14 @@ extern int flag_isoc99;
extern int flag_isoc11;
/* Nonzero means use the ISO C23 dialect of C. */
/* Nonzero means use the ISO C23 (or later) dialect of C. */
extern int flag_isoc23;
/* Nonzero means use the ISO C2Y (or later) dialect of C. */
extern int flag_isoc2y;
/* Nonzero means that we have builtin functions, and main is an int. */
extern int flag_hosted;

View File

@ -121,6 +121,7 @@ static void set_std_c99 (int);
static void set_std_c11 (int);
static void set_std_c17 (int);
static void set_std_c23 (int);
static void set_std_c2y (int);
static void check_deps_environment_vars (void);
static void handle_deferred_opts (void);
static void sanitize_cpp_opts (void);
@ -743,6 +744,16 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
set_std_c23 (false /* ISO */);
break;
case OPT_std_c2y:
if (!preprocessing_asm_p)
set_std_c2y (true /* ISO */);
break;
case OPT_std_gnu2y:
if (!preprocessing_asm_p)
set_std_c2y (false /* ISO */);
break;
case OPT_trigraphs:
cpp_opts->trigraphs = 1;
break;
@ -1782,6 +1793,7 @@ set_std_c89 (int c94, int iso)
flag_isoc99 = 0;
flag_isoc11 = 0;
flag_isoc23 = 0;
flag_isoc2y = 0;
lang_hooks.name = "GNU C89";
}
@ -1793,6 +1805,7 @@ set_std_c99 (int iso)
flag_no_asm = iso;
flag_no_nonansi_builtin = iso;
flag_iso = iso;
flag_isoc2y = 0;
flag_isoc23 = 0;
flag_isoc11 = 0;
flag_isoc99 = 1;
@ -1808,6 +1821,7 @@ set_std_c11 (int iso)
flag_no_asm = iso;
flag_no_nonansi_builtin = iso;
flag_iso = iso;
flag_isoc2y = 0;
flag_isoc23 = 0;
flag_isoc11 = 1;
flag_isoc99 = 1;
@ -1823,6 +1837,7 @@ set_std_c17 (int iso)
flag_no_asm = iso;
flag_no_nonansi_builtin = iso;
flag_iso = iso;
flag_isoc2y = 0;
flag_isoc23 = 0;
flag_isoc11 = 1;
flag_isoc99 = 1;
@ -1830,7 +1845,7 @@ set_std_c17 (int iso)
lang_hooks.name = "GNU C17";
}
/* Set the C 2X standard (without GNU extensions if ISO). */
/* Set the C 23 standard (without GNU extensions if ISO). */
static void
set_std_c23 (int iso)
{
@ -1838,6 +1853,7 @@ set_std_c23 (int iso)
flag_no_asm = iso;
flag_no_nonansi_builtin = iso;
flag_iso = iso;
flag_isoc2y = 0;
flag_isoc23 = 1;
flag_isoc11 = 1;
flag_isoc99 = 1;
@ -1845,6 +1861,22 @@ set_std_c23 (int iso)
lang_hooks.name = "GNU C23";
}
/* Set the C 2Y standard (without GNU extensions if ISO). */
static void
set_std_c2y (int iso)
{
cpp_set_lang (parse_in, iso ? CLK_STDC23: CLK_GNUC23);
flag_no_asm = iso;
flag_no_nonansi_builtin = iso;
flag_iso = iso;
flag_isoc2y = 1;
flag_isoc23 = 1;
flag_isoc11 = 1;
flag_isoc99 = 1;
flag_isoc94 = 1;
lang_hooks.name = "GNU C2Y";
}
/* Set the C++ 98 standard (without GNU extensions if ISO). */
static void

View File

@ -441,6 +441,10 @@ Wc11-c2x-compat
C ObjC Alias(Wc11-c23-compat)
Deprecated in favor of -Wc11-c23-compat.
Wc23-c2y-compat
C ObjC Var(warn_c23_c2y_compat) Init(-1) Warning
Warn about features not present in ISO C23, but present in ISO C2Y.
Wc90-c99-compat
C ObjC CPP(cpp_warn_c90_c99_compat) CppReason(CPP_W_C90_C99_COMPAT) Var(warn_c90_c99_compat) Init(-1) Warning
Warn about features not present in ISO C90, but present in ISO C99.
@ -2515,6 +2519,10 @@ std=c2x
C ObjC Alias(std=c23)
Deprecated in favor of -std=c23.
std=c2y
C ObjC
Conform to the ISO 202Y C standard draft (experimental and incomplete support).
std=c89
C ObjC Alias(std=c90)
Conform to the ISO 1990 C standard.
@ -2613,6 +2621,10 @@ std=gnu2x
C ObjC Alias(std=gnu23)
Deprecated in favor of -std=gnu23.
std=gnu2y
C ObjC
Conform to the ISO 202Y C standard draft with GNU extensions (experimental and incomplete support).
std=gnu89
C ObjC Alias(std=gnu90)
Conform to the ISO 1990 C standard with GNU extensions.

View File

@ -160,6 +160,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Wbuiltin-macro-redefined)
Wc11-c23-compat
UrlSuffix(gcc/Warning-Options.html#index-Wc11-c23-compat)
Wc23-c2y-compat
UrlSuffix(gcc/Warning-Options.html#index-Wc23-c2y-compat)
Wc90-c99-compat
UrlSuffix(gcc/Warning-Options.html#index-Wc90-c99-compat)

View File

@ -25,6 +25,45 @@ along with GCC; see the file COPYING3. If not see
#include "c-tree.h"
#include "opts.h"
/* Issue an ISO C23 pedantic warning MSGID if -pedantic outside C2Y mode,
otherwise issue warning MSGID if -Wc23-c2y-compat is specified.
This function is supposed to be used for matters that are allowed in
ISO C2Y but not supported in ISO C23, thus we explicitly don't pedwarn
when C2Y is specified. */
bool
pedwarn_c23 (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
bool warned = false;
rich_location richloc (line_table, location);
va_start (ap, gmsgid);
/* If desired, issue the C23/C2Y compat warning, which is more specific
than -pedantic. */
if (warn_c23_c2y_compat > 0)
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc2y)
? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = OPT_Wc23_c2y_compat;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
/* -Wno-c23-c2y-compat suppresses even the pedwarns. */
else if (warn_c23_c2y_compat == 0)
;
/* For -pedantic outside C2Y, issue a pedwarn. */
else if (pedantic && !flag_isoc2y)
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
diagnostic.option_index = opt;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
va_end (ap);
return warned;
}
/* Issue an ISO C11 pedantic warning MSGID if -pedantic outside C23 mode,
otherwise issue warning MSGID if -Wc11-c23-compat is specified.
This function is supposed to be used for matters that are allowed in

View File

@ -1534,6 +1534,9 @@ disable_extension_diagnostics (void)
/* Similarly for warn_c11_c23_compat. */
| ((warn_c11_c23_compat == 1) << 11)
| ((warn_c11_c23_compat == -1) << 12)
/* Similarly for warn_c23_c2y_compat. */
| ((warn_c23_c2y_compat == 1) << 13)
| ((warn_c23_c2y_compat == -1) << 14)
);
cpp_opts->cpp_pedantic = pedantic = 0;
warn_pointer_arith = 0;
@ -1545,6 +1548,7 @@ disable_extension_diagnostics (void)
warn_c90_c99_compat = 0;
warn_c99_c11_compat = 0;
warn_c11_c23_compat = 0;
warn_c23_c2y_compat = 0;
return ret;
}
@ -1565,6 +1569,7 @@ restore_extension_diagnostics (int flags)
warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
warn_c23_c2y_compat = (flags >> 13) & 1 ? 1 : ((flags >> 14) & 1 ? -1 : 0);
}
/* Helper data structure for parsing #pragma acc routine. */
@ -10273,8 +10278,14 @@ struct c_generic_association
/* Parse a generic-selection. (C11 6.5.1.1).
generic-selection:
_Generic ( assignment-expression , generic-assoc-list )
_Generic ( generic-controlling-operand , generic-assoc-list )
generic-controlling-operand:
assignment-expression
type-name
(The use of a type-name is new in C2Y.)
generic-assoc-list:
generic-association
generic-assoc-list , generic-association
@ -10314,30 +10325,43 @@ c_parser_generic_selection (c_parser *parser)
if (!parens.require_open (parser))
return error_expr;
c_inhibit_evaluation_warnings++;
selector_loc = c_parser_peek_token (parser)->location;
selector = c_parser_expr_no_commas (parser, NULL);
selector = default_function_array_conversion (selector_loc, selector);
c_inhibit_evaluation_warnings--;
if (selector.value == error_mark_node)
if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return selector;
c_inhibit_evaluation_warnings++;
pedwarn_c23 (selector_loc, OPT_Wpedantic,
"ISO C does not support use of type name as %<_Generic%> "
"controlling operand before C2Y");
struct c_type_name *type = c_parser_type_name (parser);
selector_type = groktypename (type, NULL, NULL);
c_inhibit_evaluation_warnings--;
}
else
{
c_inhibit_evaluation_warnings++;
selector = c_parser_expr_no_commas (parser, NULL);
selector = default_function_array_conversion (selector_loc, selector);
c_inhibit_evaluation_warnings--;
if (selector.value == error_mark_node)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return selector;
}
mark_exp_read (selector.value);
selector_type = TREE_TYPE (selector.value);
/* In ISO C terms, rvalues (including the controlling expression
of _Generic) do not have qualified types. */
if (TREE_CODE (selector_type) != ARRAY_TYPE)
selector_type = TYPE_MAIN_VARIANT (selector_type);
/* In ISO C terms, _Noreturn is not part of the type of expressions
such as &abort, but in GCC it is represented internally as a type
qualifier. */
if (FUNCTION_POINTER_TYPE_P (selector_type)
&& TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
selector_type
= build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
}
mark_exp_read (selector.value);
selector_type = TREE_TYPE (selector.value);
/* In ISO C terms, rvalues (including the controlling expression of
_Generic) do not have qualified types. */
if (TREE_CODE (selector_type) != ARRAY_TYPE)
selector_type = TYPE_MAIN_VARIANT (selector_type);
/* In ISO C terms, _Noreturn is not part of the type of expressions
such as &abort, but in GCC it is represented internally as a type
qualifier. */
if (FUNCTION_POINTER_TYPE_P (selector_type)
&& TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
selector_type
= build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
@ -10376,11 +10400,13 @@ c_parser_generic_selection (c_parser *parser)
}
if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
error_at (assoc.type_location,
"%<_Generic%> association has function type");
pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
"ISO C does not support %<_Generic%> association with "
"function type before C2Y");
else if (!COMPLETE_TYPE_P (assoc.type))
error_at (assoc.type_location,
"%<_Generic%> association has incomplete type");
pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
"ISO C does not support %<_Generic%> association with "
"incomplete type before C2Y");
if (c_type_variably_modified_p (assoc.type))
error_at (assoc.type_location,

View File

@ -905,6 +905,8 @@ extern bool pedwarn_c99 (location_t, int opt, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern bool pedwarn_c11 (location_t, int opt, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern bool pedwarn_c23 (location_t, int opt, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern void
set_c_expr_source_range (c_expr *expr,

View File

@ -367,6 +367,7 @@ rl78_option_override (void)
&& strcmp (lang_hooks.name, "GNU C11")
&& strcmp (lang_hooks.name, "GNU C17")
&& strcmp (lang_hooks.name, "GNU C23")
&& strcmp (lang_hooks.name, "GNU C2Y")
&& strcmp (lang_hooks.name, "GNU C89")
&& strcmp (lang_hooks.name, "GNU C99")
/* Compiling with -flto results in a language of GNU GIMPLE being used... */

View File

@ -1887,7 +1887,9 @@ signifies the 2011 revision of the C standard; the value
@code{201710L} signifies the 2017 revision of the C standard (which is
otherwise identical to the 2011 version apart from correction of
defects). The value @code{202311L} is used for the experimental
@option{-std=c23} and @option{-std=gnu23} modes.
@option{-std=c23} and @option{-std=gnu23} modes. An unspecified value
larger than @code{202311L} is used for the experimental
@option{-std=c2y} and @option{-std=gnu2y} modes.
This macro is not defined if the @option{-traditional-cpp} option is
used, nor when compiling C++ or Objective-C@.

View File

@ -340,7 +340,7 @@ Objective-C and Objective-C++ Dialects}.
-Wbool-compare -Wbool-operation
-Wno-builtin-declaration-mismatch
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat
-Wc11-c23-compat
-Wc11-c23-compat -Wc23-c2y-compat
-Wc++-compat -Wc++11-compat -Wc++14-compat -Wc++17-compat
-Wc++20-compat
-Wno-c++11-extensions -Wno-c++14-extensions -Wno-c++17-extensions
@ -2472,6 +2472,10 @@ ISO C23, the 2023 revision of the ISO C standard (expected to be
published in 2024). The support for this version is experimental and
incomplete. The name @samp{c2x} is deprecated.
@item c2y
The next version of the ISO C standard, still under development. The
support for this version is experimental and incomplete.
@item gnu90
@itemx gnu89
GNU dialect of ISO C90 (including some C99 features).
@ -2491,6 +2495,10 @@ GNU dialect of ISO C17. This is the default for C code.
@item gnu23
@itemx gnu2x
GNU dialect of ISO C23. The support for this version is experimental
and incomplete. The name @samp{gnu2x} is deprecated.
@item gnu2y
The next version of the ISO C standard, still under development, plus
GNU extensions. The support for this version is experimental and
incomplete. The name @samp{gnu2x} is deprecated.
@ -9326,6 +9334,19 @@ deprecated.
When not compiling in C23 mode, these warnings are upgraded to errors
by @option{-pedantic-errors}.
@opindex Wc23-c2y-compat
@opindex Wno-c23-c2y-compat
@item -Wc23-c2y-compat @r{(C and Objective-C only)}
@itemx -Wc23-c2y-compat @r{(C and Objective-C only)}
Warn about features not present in ISO C23, but present in ISO C2Y.
For instance, warn about @code{_Generic} selecting with a type name
instead of an expression. This option is independent of the standards
mode. Warnings are disabled in the expression that follows
@code{__extension__}.
When not compiling in C2Y mode, these warnings are upgraded to errors
by @option{-pedantic-errors}.
@opindex Wc++-compat
@opindex Wno-c++-compat
@item -Wc++-compat @r{(C and Objective-C only)}

View File

@ -42,6 +42,8 @@ with some exceptions, and possibly with some extensions.
@cindex C23
@cindex ISO C2X
@cindex C2X
@cindex ISO C2Y
@cindex C2Y
@cindex Technical Corrigenda
@cindex TC1
@cindex Technical Corrigendum 1
@ -113,12 +115,16 @@ known as @dfn{C17} and is supported with @option{-std=c17} or
@option{-std=c11}, and the only difference between the options is the
value of @code{__STDC_VERSION__}.
A further version of the C standard, known as @dfn{C23}, is under
A fifth version of the C standard, known as @dfn{C23}, is under
development and expected to be published in 2024 as ISO/IEC 9899:2024.
(While in development, drafts of this standard version were referred
to as @dfn{C2X}.) Experimental and incomplete support for this is
enabled with @option{-std=c23} or @option{-std=iso9899:2024}.
A further version of the C standard, known as @dfn{C2Y}, is under
development; experimental and incomplete support for this is enabled
with @option{-std=c2y}.
By default, GCC provides some extensions to the C language that, on
rare occasions conflict with the C standard. @xref{C
Extensions,,Extensions to the C Language Family}.

View File

@ -25281,6 +25281,8 @@ highest_c_language (const char *lang1, const char *lang2)
if (strcmp ("GNU C++98", lang1) == 0 || strcmp ("GNU C++98", lang2) == 0)
return "GNU C++98";
if (strcmp ("GNU C2Y", lang1) == 0 || strcmp ("GNU C2Y", lang2) == 0)
return "GNU C2Y";
if (strcmp ("GNU C23", lang1) == 0 || strcmp ("GNU C23", lang2) == 0)
return "GNU C23";
if (strcmp ("GNU C17", lang1) == 0 || strcmp ("GNU C17", lang2) == 0)
@ -25363,7 +25365,8 @@ gen_compile_unit_die (const char *filename)
if (dwarf_version >= 5 /* || !dwarf_strict */)
if (strcmp (language_string, "GNU C11") == 0
|| strcmp (language_string, "GNU C17") == 0
|| strcmp (language_string, "GNU C23") == 0)
|| strcmp (language_string, "GNU C23") == 0
|| strcmp (language_string, "GNU C2Y") == 0)
language = DW_LANG_C11;
}
}

View File

@ -0,0 +1,17 @@
/* Test C2Y _Generic features: error with -std=c23 -pedantic-errors. */
/* { dg-do compile } */
/* { dg-options "-std=c23 -pedantic-errors" } */
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2); /* { dg-error "use of type name" } */
_Static_assert (_Generic (void, int : 1, void : 2) == 2); /* { dg-error "use of type name" } */
/* { dg-error "incomplete type" "incomplete type" { target *-*-* } .-1 } */
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2); /* { dg-error "use of type name" } */
/* { dg-error "function type" "function type" { target *-*-* } .-1 } */
const int ci;
_Static_assert (_Generic (typeof (ci), const int : 1, int : 2) == 1); /* { dg-error "use of type name" } */
_Static_assert (_Generic (ci, const int : 1, int : 2) == 2);

View File

@ -0,0 +1,17 @@
/* Test C2Y _Generic features: warning with -std=c23 -pedantic. */
/* { dg-do compile } */
/* { dg-options "-std=c23 -pedantic" } */
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2); /* { dg-warning "use of type name" } */
_Static_assert (_Generic (void, int : 1, void : 2) == 2); /* { dg-warning "use of type name" } */
/* { dg-warning "incomplete type" "incomplete type" { target *-*-* } .-1 } */
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2); /* { dg-warning "use of type name" } */
/* { dg-warning "function type" "function type" { target *-*-* } .-1 } */
const int ci;
_Static_assert (_Generic (typeof (ci), const int : 1, int : 2) == 1); /* { dg-warning "use of type name" } */
_Static_assert (_Generic (ci, const int : 1, int : 2) == 2);

View File

@ -0,0 +1,16 @@
/* Test C2Y _Generic features: no warning or error with -std=c23
-pedantic-errors -Wno-c23-c2y-compat. */
/* { dg-do compile } */
/* { dg-options "-std=c23 -pedantic-errors -Wno-c23-c2y-compat" } */
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2);
_Static_assert (_Generic (void, int : 1, void : 2) == 2);
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2);
const int ci;
_Static_assert (_Generic (typeof (ci), const int : 1, int : 2) == 1);
_Static_assert (_Generic (ci, const int : 1, int : 2) == 2);

View File

@ -0,0 +1,16 @@
/* Test C2Y _Generic features: no warning or error with -std=c23 by
default. */
/* { dg-do compile } */
/* { dg-options "-std=c23" } */
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2);
_Static_assert (_Generic (void, int : 1, void : 2) == 2);
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2);
const int ci;
_Static_assert (_Generic (typeof (ci), const int : 1, int : 2) == 1);
_Static_assert (_Generic (ci, const int : 1, int : 2) == 2);

View File

@ -1,6 +1,6 @@
/*
* { dg-do compile }
* { dg-options "-std=c23" }
* { dg-options "-std=c23 -pedantic-errors" }
*/
// (in-)completeness

View File

@ -0,0 +1,15 @@
/* Test C2Y _Generic features. */
/* { dg-do compile } */
/* { dg-options "-std=c2y -pedantic-errors" } */
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2);
_Static_assert (_Generic (void, int : 1, void : 2) == 2);
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2);
const int ci;
_Static_assert (_Generic (typeof (ci), const int : 1, int : 2) == 1);
_Static_assert (_Generic (ci, const int : 1, int : 2) == 2);

View File

@ -0,0 +1,17 @@
/* Test C2Y _Generic features: warning with -Wc23-c2y-compat. */
/* { dg-do compile } */
/* { dg-options "-std=c2y -pedantic-errors -Wc23-c2y-compat" } */
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2); /* { dg-warning "use of type name" } */
_Static_assert (_Generic (void, int : 1, void : 2) == 2); /* { dg-warning "use of type name" } */
/* { dg-warning "incomplete type" "incomplete type" { target *-*-* } .-1 } */
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2); /* { dg-warning "use of type name" } */
/* { dg-warning "function type" "function type" { target *-*-* } .-1 } */
const int ci;
_Static_assert (_Generic (typeof (ci), const int : 1, int : 2) == 1); /* { dg-warning "use of type name" } */
_Static_assert (_Generic (ci, const int : 1, int : 2) == 2);

View File

@ -0,0 +1,9 @@
/* Test C2Y _Generic features: VM types still not allowed. */
/* { dg-do compile } */
/* { dg-options "-std=c2y -pedantic-errors" } */
void
f (int i)
{
(void) _Generic (i, int : 1, int (*)[i] : 2); /* { dg-error "variable length" } */
}

View File

@ -0,0 +1,15 @@
/* Test C2Y _Generic features: __extension__ suppresses -Wc23-c2y-compat
warnings (and the state is restored after __extension__). */
/* { dg-do compile } */
/* { dg-options "-std=gnu2y -pedantic-errors -Wc23-c2y-compat" } */
_Static_assert (__extension__ _Generic (const int, int : 1, const int : 2) == 2);
_Static_assert (_Generic (const int, int : 1, const int : 2) == 2); /* { dg-warning "use of type name" } */
_Static_assert (__extension__ _Generic (void, int : 1, void : 2) == 2);
_Static_assert (_Generic (void, int : 1, void : 2) == 2); /* { dg-warning "use of type name" } */
/* { dg-warning "incomplete type" "incomplete type" { target *-*-* } .-1 } */
_Static_assert (__extension__ _Generic (int (), int (*) () : 1, int () : 2) == 2);
_Static_assert (_Generic (int (), int (*) () : 1, int () : 2) == 2); /* { dg-warning "use of type name" } */
/* { dg-warning "function type" "function type" { target *-*-* } .-1 } */

View File

@ -172,8 +172,9 @@ enum cpp_ttype
/* C language kind, used when calling cpp_create_reader. */
enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_GNUC11, CLK_GNUC17, CLK_GNUC23,
CLK_GNUC2Y,
CLK_STDC89, CLK_STDC94, CLK_STDC99, CLK_STDC11, CLK_STDC17,
CLK_STDC23,
CLK_STDC23, CLK_STDC2Y,
CLK_GNUCXX, CLK_CXX98, CLK_GNUCXX11, CLK_CXX11,
CLK_GNUCXX14, CLK_CXX14, CLK_GNUCXX17, CLK_CXX17,
CLK_GNUCXX20, CLK_CXX20, CLK_GNUCXX23, CLK_CXX23,

View File

@ -109,12 +109,14 @@ static const struct lang_flags lang_defaults[] =
/* GNUC11 */ { 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
/* GNUC17 */ { 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
/* GNUC23 */ { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1 },
/* GNUC2Y */ { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1 },
/* STDC89 */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC94 */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC17 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* STDC23 */ { 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1 },
/* STDC2Y */ { 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1 },
/* GNUCXX */ { 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
/* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1 },
/* GNUCXX11 */ { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
@ -595,6 +597,9 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
else if (CPP_OPTION (pfile, lang) == CLK_STDC23
|| CPP_OPTION (pfile, lang) == CLK_GNUC23)
_cpp_define_builtin (pfile, "__STDC_VERSION__ 202311L");
else if (CPP_OPTION (pfile, lang) == CLK_STDC2Y
|| CPP_OPTION (pfile, lang) == CLK_GNUC2Y)
_cpp_define_builtin (pfile, "__STDC_VERSION__ 202500L");
else if (CPP_OPTION (pfile, lang) == CLK_STDC17
|| CPP_OPTION (pfile, lang) == CLK_GNUC17)
_cpp_define_builtin (pfile, "__STDC_VERSION__ 201710L");