@@ -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)
{
new file mode 100644
@@ -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" } */
+
+