From: Martin Uecker <uecker@tugraz.at>
To: gcc-patches@gcc.gnu.org
Cc: Joseph Myers <joseph@codesourcery.com>
Subject: [C PATCH] Support typename as selector in _Generic
Date: Sat, 05 Aug 2023 18:33:04 +0200 [thread overview]
Message-ID: <ffd3c7b1b0c71e13f40471aeef643b9c9e3c0353.camel@tugraz.at> (raw)
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" } */
+
+
reply other threads:[~2023-08-05 16:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ffd3c7b1b0c71e13f40471aeef643b9c9e3c0353.camel@tugraz.at \
--to=uecker@tugraz.at \
--cc=gcc-patches@gcc.gnu.org \
--cc=joseph@codesourcery.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).