* [C PATCH] Support typename as selector in _Generic
@ 2023-08-05 16:33 Martin Uecker
0 siblings, 0 replies; only message in thread
From: Martin Uecker @ 2023-08-05 16:33 UTC (permalink / raw)
To: gcc-patches; +Cc: Joseph Myers
Clang now has an extension which accepts a typename for
_Generic. This is simple to implement and is useful.
Do we want this?
Clang calls it a "Clang extension" in the pedantic
warning. I changed it to "an extension" I am not
sure what the policy is.
Do we need an extra warning option? Clang has one.
No documentation so far.
Bootstrapped and regression tested on x86_64-pc-linux-gnu.
Martin
c: Support typename as selector in _Generic
Support typenames as first argument to _Generic which is an
extension supported by Clang. It makes it easier to test
for types with qualifiers in combination with typeof.
gcc/c/:
* c-parser.cc (c_parser_generic_selection): Support typename
in _Generic selector.
gcc/testsuite/:
* gnu2x-generic.c: New test.
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 57a01dc2fa3..9aea2425294 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -9312,30 +9312,51 @@ 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_token_starts_typename (c_parser_peek_token (parser)))
{
- 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)));
+ /* Language extension introduced by Clang. */
+ pedwarn (selector_loc, OPT_Wpedantic, "passing a type argument as "
+ "first argument to %<_Generic%> is an extension");
+ struct c_type_name *type_name;
+ c_inhibit_evaluation_warnings++;
+ type_name = c_parser_type_name (parser);
+ c_inhibit_evaluation_warnings--;
+ if (NULL == type_name)
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return error_expr;
+ }
+ /* Qualifiers are preserved. */
+ selector_type = groktypename (type_name, NULL, NULL);
+ }
+ 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)));
+ }
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
@@ -9401,7 +9422,7 @@ c_parser_generic_selection (c_parser *parser)
assoc.expression = c_parser_expr_no_commas (parser, NULL);
if (!match)
- c_inhibit_evaluation_warnings--;
+ c_inhibit_evaluation_warnings--;
if (assoc.expression.value == error_mark_node)
{
diff --git a/gcc/testsuite/gcc.dg/gnu2x-generic.c b/gcc/testsuite/gcc.dg/gnu2x-generic.c
new file mode 100644
index 00000000000..82b09578072
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-generic.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+_Static_assert(_Generic(const int, const int: 1, int: 0), "");
+_Static_assert(_Generic( int, const int: 0, int: 1), "");
+_Static_assert(_Generic(int[4], int[4]: 1), "");
+_Static_assert(_Generic(typeof(int[4]), int[4]: 1), "");
+
+void foo(int n)
+{
+ _Static_assert(_Generic(int[n++], int[4]: 1), "");
+}
+
+#pragma GCC diagnostic warning "-Wpedantic"
+_Static_assert(_Generic(int[4], int[4]: 1), ""); /* { dg-warning "extension" } */
+
+
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-08-05 16:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-05 16:33 [C PATCH] Support typename as selector in _Generic Martin Uecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).