From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mailrelay.tugraz.at (mailrelay.tugraz.at [129.27.2.202]) by sourceware.org (Postfix) with ESMTPS id B57B23858D35 for ; Sat, 5 Aug 2023 16:33:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B57B23858D35 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=tugraz.at Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tugraz.at Received: from vra-169-214.tugraz.at (vra-169-214.tugraz.at [129.27.169.214]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4RJ7Rh4RGpz3wgY; Sat, 5 Aug 2023 18:33:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1691253185; bh=SYPxjI+izmghRzFaoeoljMUI6LRurmfpWceWu7XUAiY=; h=Subject:From:To:Cc:Date; b=p/B2S1tQ4yaEjPTk9WcNvRP3YI0HUiLRgUenu6bMC3aliMWV8YwlJKuDeZUQInsYE OEooS+hMKazlIbeG8ADiCxfDGQnAii43nKAZhV4whI6l5eN/iiBzn6sg9y1Hh4Nith lvTV70he9121RvQoPWaM0RoI7II/s3Bb3H35vlEY= Message-ID: Subject: [C PATCH] Support typename as selector in _Generic From: Martin Uecker To: gcc-patches@gcc.gnu.org Cc: Joseph Myers Date: Sat, 05 Aug 2023 18:33:04 +0200 Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.38.3-1+deb11u2 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-TUG-Backscatter-control: G/VXY7/6zeyuAY/PU2/0qw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.116 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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" } */ + +