From patchwork Thu Aug 10 15:33:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 134045 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp502657vqi; Thu, 10 Aug 2023 08:33:58 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFjIy2nfwfX0Ld4VA0U6+nk/CrslcGq19gr39ZOYQOSDHKS1HEQLiHyu6m+yTb35/ABNdop X-Received: by 2002:a17:906:3196:b0:988:b61e:4219 with SMTP id 22-20020a170906319600b00988b61e4219mr3147125ejy.29.1691681638270; Thu, 10 Aug 2023 08:33:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691681638; cv=none; d=google.com; s=arc-20160816; b=j4BQRMQUoWZkDHw4dGtfmfv8NsfHrzbqKdFtp86UI95LAA80vo8hWSx9oqvZz7xCb4 lBL+qsJf+tTi4RRYWw7A/Ggs/0cQrdntF9DxkD9iTzRfabQnZmfmB35loefRJ9xYXOYj No4+7ygC4L4AoOlQW7b9hQg2Bz+OL5jImlc0B7xatxTBRYep/7t7RzFOMNNdAjcK0n1N d6v2yYvH0xj8pASGji0OfpLOMY0/xyobYcDI/iIUY+dCwXgMecikQrWJsDgig3EXVc87 XK67vK+j0L/bOPkBnp/fHUzk+npYmTB0KMzA/Td9Mf7GI68iTxJSIAQmX77Hxn1cuZZl Tzyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-disposition:in-reply-to:mime-version:references:message-id :subject:to:date:dmarc-filter:delivered-to:dkim-signature :dkim-filter; bh=VlY5rM8lGcjnQTMZjDFx7Jtgoy6aoO96FsPMMIwNVgg=; fh=IfQ2nj8y/DGV3NUguOJYlCLFFY4/pLxWyTI4ZLjBcII=; b=qbzx0L0zR/y87dB08tcN1xpBkcskNBL74g+3/27+Nlpo7QuMKRaqSIhiTP+Jd2FBTP qiYp3dcUhxnNsVFGF3a8wYyBW4a4dothUvBm/NGpISa8LL0MOoci47oruIglB4PhEkkz hcK2WVv1wFDYSxYi2ihnbQ3NRCPQrqPZ7ku/zUZ6owFRJjatfZmaUrqkpqxsHKV6ns33 hWlJ9JE79GcxZWP1aj2TdVSS3N7LuACEVd6EpHsBbzDMVrFCroHAAFLwzZKgPKizvW0z l+n6KK4+puxBU7rnRONuRaVsWVohZEMdG/ZwzcL0WWL0yjf5Sjrp623Y6NZCbw678MIn ZeAQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=aalVxIVw; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id dt17-20020a170906b79100b00997c9f1bdf7si1889885ejb.407.2023.08.10.08.33.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Aug 2023 08:33:58 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=aalVxIVw; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 23D2D3858288 for ; Thu, 10 Aug 2023 15:33:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 23D2D3858288 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1691681637; bh=VlY5rM8lGcjnQTMZjDFx7Jtgoy6aoO96FsPMMIwNVgg=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=aalVxIVwEq5IR633YG+V29giMzqRSUfkx46aXb+V5zBwq2s3B985IirQOZ8oxK8VA 5yHP7OILeq+hyQDBrlW3LUWEuIXJn9gK67mEGNzTQGb1iGnXUQsQyHiGdqHXhnuAry oPcf+FfjYtBaSzsHt5rBmvdUwddg5yTzE+pv3MgA= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id B063A3858288 for ; Thu, 10 Aug 2023 15:33:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B063A3858288 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-462-r3ajs9nMP0C5DaVyDsKYWA-1; Thu, 10 Aug 2023 11:33:10 -0400 X-MC-Unique: r3ajs9nMP0C5DaVyDsKYWA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 910B8858EED; Thu, 10 Aug 2023 15:33:10 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.225.169]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 301A2140E91B; Thu, 10 Aug 2023 15:33:10 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 37AFX7I52356851 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 10 Aug 2023 17:33:07 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 37AFX6nP2356850; Thu, 10 Aug 2023 17:33:06 +0200 Date: Thu, 10 Aug 2023 17:33:06 +0200 To: "Joseph S. Myers" , Marek Polacek , gcc-patches@gcc.gnu.org Subject: [PATCH] c, v2: Add __typeof_unqual__ and __typeof_unqual support Message-ID: References: MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773856765506649762 X-GMAIL-MSGID: 1773856765506649762 Hi! I'd like to ping this patch. Reposting it as the extend.texi hunk didn't apply cleanly anymore. Bootstrapped/regtested again on x86_64-linux and i686-linux, ok for trunk? On Mon, Jun 12, 2023 at 09:51:22PM +0200, Jakub Jelinek via Gcc-patches wrote: > As I mentioned in my stdckdint.h mail, I think having __ prefixed > keywords for the typeof_unqual keyword which can be used in earlier > language modes can be useful, not all code can be switched to C23 > right away. > > The following patch implements that. It keeps the non-C23 behavior > for it for the _Noreturn functions to stay compatible with how > __typeof__ behaves. > > I think we don't need it for C++, in C++ we have standard > traits to remove qualifiers etc. 2023-08-10 Jakub Jelinek gcc/ * doc/extend.texi (Typeof): Document typeof_unqual and __typeof_unqual__. gcc/c-family/ * c-common.cc (c_common_reswords): Add __typeof_unqual and __typeof_unqual__ spellings of typeof_unqual. gcc/c/ * c-parser.cc (c_parser_typeof_specifier): Handle __typeof_unqual and __typeof_unqual__ as !is_std. gcc/testsuite/ * gcc.dg/c11-typeof-2.c: New test. * gcc.dg/c11-typeof-3.c: New test. * gcc.dg/gnu11-typeof-3.c: New test. * gcc.dg/gnu11-typeof-4.c: New test. Jakub --- gcc/c-family/c-common.cc.jj 2023-05-20 15:31:09.070663296 +0200 +++ gcc/c-family/c-common.cc 2023-06-10 19:20:11.106910976 +0200 @@ -420,6 +420,8 @@ const struct c_common_resword c_common_r { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 }, { "__typeof", RID_TYPEOF, 0 }, { "__typeof__", RID_TYPEOF, 0 }, + { "__typeof_unqual", RID_TYPEOF_UNQUAL, D_CONLY }, + { "__typeof_unqual__", RID_TYPEOF_UNQUAL, D_CONLY }, { "__volatile", RID_VOLATILE, 0 }, { "__volatile__", RID_VOLATILE, 0 }, { "__GIMPLE", RID_GIMPLE, D_CONLY }, --- gcc/c/c-parser.cc.jj 2023-06-06 20:02:35.587211846 +0200 +++ gcc/c/c-parser.cc 2023-06-10 19:22:15.577205685 +0200 @@ -4126,7 +4126,8 @@ c_parser_typeof_specifier (c_parser *par { gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL)); is_unqual = true; - is_std = true; + tree spelling = c_parser_peek_token (parser)->value; + is_std = strcmp (IDENTIFIER_POINTER (spelling), "typeof_unqual") == 0; } c_parser_consume_token (parser); c_inhibit_evaluation_warnings++; --- gcc/doc/extend.texi.jj 2023-08-10 12:59:04.588094460 +0200 +++ gcc/doc/extend.texi 2023-08-10 13:00:09.301167471 +0200 @@ -843,6 +843,13 @@ Thus, @code{array (pointer (char), 4)} i pointers to @code{char}. @end itemize +The ISO C2X operator @code{typeof_unqual} is available in ISO C2X mode +and its result is the non-atomic unqualified version of what @code{typeof} +operator returns. Alternate spelling @code{__typeof_unqual__} is +available in all C modes and provides non-atomic unqualified version of +what @code{__typeof__} operator returns. +@xref{Alternate Keywords}. + @cindex @code{__auto_type} in GNU C In GNU C, but not GNU C++, you may also declare the type of a variable as @code{__auto_type}. In that case, the declaration must declare --- gcc/testsuite/gcc.dg/c11-typeof-2.c.jj 2023-06-10 19:27:38.675779747 +0200 +++ gcc/testsuite/gcc.dg/c11-typeof-2.c 2023-06-10 19:42:27.450606301 +0200 @@ -0,0 +1,177 @@ +/* Test GNU extensions __typeof__ and __typeof_unqual__. Valid code. */ +/* { dg-do run } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int i; +extern __typeof__ (i) i; +extern __typeof (int) i; +extern __typeof_unqual__ (i) i; +extern __typeof_unqual (int) i; + +volatile int vi; +extern __typeof__ (volatile int) vi; +extern __typeof (vi) vi; + +extern __typeof_unqual__ (volatile int) i; +extern __typeof_unqual__ (vi) i; +extern __typeof__ ((const int) vi) i; +extern __typeof ((volatile int) vi) i; + +const int ci; +extern __typeof (const int) ci; +extern __typeof (ci) ci; + +extern __typeof_unqual (const int) i; +extern __typeof_unqual (ci) i; +extern __typeof__ ((const int) ci) i; +extern __typeof__ (+ci) i; +extern __typeof (0, ci) i; +extern __typeof__ (1 ? ci : ci) i; +extern __typeof (0) i; + +const int fci (void); +extern __typeof__ (fci ()) i; + +_Atomic int ai; +extern __typeof (_Atomic int) ai; +extern __typeof__ (_Atomic (int)) ai; +extern __typeof (ai) ai; + +extern __typeof_unqual__ (_Atomic int) i; +extern __typeof_unqual (_Atomic (int)) i; +extern __typeof_unqual__ (ai) i; +extern __typeof (+ai) i; +extern __typeof__ ((_Atomic int) ai) i; +extern __typeof__ (0, ai) i; +extern __typeof (1 ? ai : ai) i; + +_Atomic int fai (void); +extern __typeof__ (fai ()) i; + +_Atomic const volatile int acvi; +extern __typeof (int volatile const _Atomic) acvi; +extern __typeof (acvi) acvi; +extern const _Atomic volatile __typeof (acvi) acvi; +extern _Atomic volatile __typeof__ (ci) acvi; +extern _Atomic const __typeof (vi) acvi; +extern const __typeof__ (ai) volatile acvi; + +extern __typeof_unqual (acvi) i; +extern __typeof_unqual__ (__typeof (acvi)) i; +extern __typeof_unqual (_Atomic __typeof_unqual__ (acvi)) i; + +extern _Atomic __typeof_unqual (acvi) ai; + +char c; +volatile char vc; +volatile char *pvc; +volatile char *const cpvc; +const char *pcc; +const char *volatile vpcc; +__typeof (*vpcc) cc; + +extern __typeof__ (*cpvc) vc; +extern __typeof_unqual (*cpvc) c; +extern __typeof_unqual__ (cpvc) pvc; +extern __typeof_unqual__ (vpcc) pcc; +extern const char cc; + +extern __typeof (++vi) i; +extern __typeof (++ai) i; +extern __typeof__ (--vi) i; +extern __typeof (--ai) i; +extern __typeof__ (vi++) i; +extern __typeof__ (ai++) i; +extern __typeof (vi--) i; +extern __typeof__ (ai--) i; + +_Bool b; +volatile _Bool vb; +_Atomic _Bool ab; +extern __typeof__ (++vb) b; +extern __typeof__ (++ab) b; +extern __typeof (--vb) b; +extern __typeof__ (--ab) b; +extern __typeof (vb++) b; +extern __typeof (ab++) b; +extern __typeof__ (vb--) b; +extern __typeof (ab--) b; + +extern __typeof__ (vc = 1) c; +extern __typeof__ (vpcc = 0) pcc; +extern __typeof (ai *= 2) i; + +int s = sizeof (__typeof__ (int (*)[++i])); + +void *vp; + +extern void abort (void); +extern void exit (int); + +extern int only_used_in_typeof; + +static int not_defined (void); + +__typeof (i) +main (__typeof (*vp)) +{ + volatile __typeof__ (only_used_in_typeof) ii = 2; + if (ii != 2) + abort (); + const __typeof__ (not_defined ()) jj = 3; + if (jj != 3) + abort (); + unsigned int u = 1; + __typeof__ (u) u2 = 0; + __typeof (int (*)[++u2]) p = 0; + if (u2 != 1) + abort (); + if (sizeof (*p) != sizeof (int)) + abort (); + __typeof_unqual (int (*)[++u2]) q = 0; + if (u2 != 2) + abort (); + if (sizeof (*q) != 2 * sizeof (int)) + abort (); + if (sizeof (*p) != sizeof (int)) + abort (); + __typeof (++u2) u3 = 1; + if (u2 != u + u3) + abort (); + __typeof_unqual__ (++u2) u4 = 2; + if (u2 != u4) + abort (); + u = sizeof (__typeof__ (int (*)[++u2])); + if (u2 != 2) + abort (); + u = sizeof (__typeof_unqual (int (*)[++u2])); + if (u2 != 2) + abort (); + __typeof ((int (*)[++u2]) 0) q2; + if (u2 != 3) + abort (); + __typeof ((void) 0, (int (*)[++u2]) 0) q3; + if (u2 != 4) + abort (); + __typeof__ ((int (*)[++u2]) 0, 0) q4; + if (u2 != 4) + abort (); + __typeof_unqual ((int (*)[++u2]) 0) q5; + if (u2 != 5) + abort (); + __typeof_unqual__ ((void) 0, (int (*)[++u2]) 0) q6; + if (u2 != 6) + abort (); + __typeof_unqual__ ((int (*)[++u2]) 0, 0) q7; + if (u2 != 6) + abort (); + int a1[6], a2[6]; + int (*pa)[u2] = &a1; + __typeof (pa = &a2) pp; + if (pa != &a2) + abort (); + __typeof_unqual (pa = &a1) pp2; + if (pa != &a1) + abort (); + exit (0); +} --- gcc/testsuite/gcc.dg/c11-typeof-3.c.jj 2023-06-10 19:27:42.003734166 +0200 +++ gcc/testsuite/gcc.dg/c11-typeof-3.c 2023-06-10 19:46:38.041174992 +0200 @@ -0,0 +1,58 @@ +/* Test GNU extensions __typeof__ and __typeof_unqual__. Invalid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +struct s { int i : 2; } x; +union u { unsigned int j : 1; } y; + +__typeof__ (x.i) j; /* { dg-error "applied to a bit-field" } */ +__typeof_unqual__ (x.i) j2; /* { dg-error "applied to a bit-field" } */ +__typeof (y.j) j3; /* { dg-error "applied to a bit-field" } */ +__typeof_unqual (y.j) j4; /* { dg-error "applied to a bit-field" } */ + +static int ok (void); +static int also_ok (void); +static int not_defined (void); /* { dg-error "used but never defined" } */ +static int also_not_defined (void); /* { dg-error "used but never defined" } */ + +_Noreturn void nf1 (void); +__attribute__((noreturn)) void nf2 (void); +void fg (void) {} +__typeof__ (&nf1) pnf1 = fg; /* { dg-error "qualified function pointer from unqualified" } */ +__typeof (&nf2) pnf2 = fg; /* { dg-error "qualified function pointer from unqualified" } */ +extern void (*pnf1) (void); /* { dg-error "conflicting types for" } */ +extern void (*pnf2) (void); /* { dg-error "conflicting types for" } */ +extern __typeof (nf1) *pnf1; /* { dg-error "conflicting types for" } */ +extern __typeof (nf1) *pnf2; /* { dg-error "conflicting types for" } */ +extern __typeof__ (nf2) *pnf1; /* { dg-error "conflicting types for" } */ +extern __typeof__ (nf2) *pnf2; /* { dg-error "conflicting types for" } */ +__typeof (*&nf1) fg2, fg2a, fg2b; /* { dg-error "ISO C forbids qualified function types" } */ +__typeof__ (*&nf2) fg3, fg3a, fg3b; /* { dg-error "ISO C forbids qualified function types" } */ +__typeof (nf1) fg4, fg4a, fg4b; +__typeof__ (nf2) fg5, fg5a, fg5b; + +extern void abort (void); + +void fg2 (void) {} /* { dg-error "conflicting type qualifiers for" } */ +_Noreturn void fg2a (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +__attribute__((noreturn)) void fg2b (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +void fg3 (void) {} /* { dg-error "conflicting type qualifiers for" } */ +_Noreturn void fg3a (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +__attribute__((noreturn)) void fg3b (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +void fg4 (void) {} +_Noreturn void fg4a (void) { abort (); } +__attribute__((noreturn)) void fg4b (void) { abort (); } +void fg5 (void) {} +_Noreturn void fg5a (void) { abort (); } +__attribute__((noreturn)) void fg5b (void) { abort (); } + +void +f (void) +{ + __typeof__ (ok ()) x = 2; + __typeof_unqual (also_ok ()) y = 2; + int a[2]; + int (*p)[x] = &a; + __typeof (p + not_defined ()) q; + __typeof_unqual__ (p + also_not_defined ()) q2; +} --- gcc/testsuite/gcc.dg/gnu11-typeof-3.c.jj 2023-06-10 19:39:59.936626612 +0200 +++ gcc/testsuite/gcc.dg/gnu11-typeof-3.c 2023-06-10 19:47:32.861424347 +0200 @@ -0,0 +1,177 @@ +/* Test GNU extensions __typeof__ and __typeof_unqual__. Valid code. */ +/* { dg-do run } */ +/* { dg-options "-std=gnu11" } */ + +int i; +extern __typeof__ (i) i; +extern __typeof (int) i; +extern __typeof_unqual__ (i) i; +extern __typeof_unqual (int) i; + +volatile int vi; +extern __typeof__ (volatile int) vi; +extern __typeof (vi) vi; + +extern __typeof_unqual__ (volatile int) i; +extern __typeof_unqual__ (vi) i; +extern __typeof__ ((const int) vi) i; +extern __typeof ((volatile int) vi) i; + +const int ci; +extern __typeof (const int) ci; +extern __typeof (ci) ci; + +extern __typeof_unqual (const int) i; +extern __typeof_unqual (ci) i; +extern __typeof__ ((const int) ci) i; +extern __typeof__ (+ci) i; +extern __typeof (0, ci) i; +extern __typeof__ (1 ? ci : ci) i; +extern __typeof (0) i; + +const int fci (void); +extern __typeof__ (fci ()) i; + +_Atomic int ai; +extern __typeof (_Atomic int) ai; +extern __typeof__ (_Atomic (int)) ai; +extern __typeof (ai) ai; + +extern __typeof_unqual__ (_Atomic int) i; +extern __typeof_unqual (_Atomic (int)) i; +extern __typeof_unqual__ (ai) i; +extern __typeof (+ai) i; +extern __typeof__ ((_Atomic int) ai) i; +extern __typeof__ (0, ai) i; +extern __typeof (1 ? ai : ai) i; + +_Atomic int fai (void); +extern __typeof__ (fai ()) i; + +_Atomic const volatile int acvi; +extern __typeof (int volatile const _Atomic) acvi; +extern __typeof (acvi) acvi; +extern const _Atomic volatile __typeof (acvi) acvi; +extern _Atomic volatile __typeof__ (ci) acvi; +extern _Atomic const __typeof (vi) acvi; +extern const __typeof__ (ai) volatile acvi; + +extern __typeof_unqual (acvi) i; +extern __typeof_unqual__ (__typeof (acvi)) i; +extern __typeof_unqual (_Atomic __typeof_unqual__ (acvi)) i; + +extern _Atomic __typeof_unqual (acvi) ai; + +char c; +volatile char vc; +volatile char *pvc; +volatile char *const cpvc; +const char *pcc; +const char *volatile vpcc; +__typeof (*vpcc) cc; + +extern __typeof__ (*cpvc) vc; +extern __typeof_unqual (*cpvc) c; +extern __typeof_unqual__ (cpvc) pvc; +extern __typeof_unqual__ (vpcc) pcc; +extern const char cc; + +extern __typeof (++vi) i; +extern __typeof (++ai) i; +extern __typeof__ (--vi) i; +extern __typeof (--ai) i; +extern __typeof__ (vi++) i; +extern __typeof__ (ai++) i; +extern __typeof (vi--) i; +extern __typeof__ (ai--) i; + +_Bool b; +volatile _Bool vb; +_Atomic _Bool ab; +extern __typeof__ (++vb) b; +extern __typeof__ (++ab) b; +extern __typeof (--vb) b; +extern __typeof__ (--ab) b; +extern __typeof (vb++) b; +extern __typeof (ab++) b; +extern __typeof__ (vb--) b; +extern __typeof (ab--) b; + +extern __typeof__ (vc = 1) c; +extern __typeof__ (vpcc = 0) pcc; +extern __typeof (ai *= 2) i; + +int s = sizeof (__typeof__ (int (*)[++i])); + +void *vp; + +extern void abort (void); +extern void exit (int); + +extern int only_used_in_typeof; + +static int not_defined (void); + +__typeof (i) +main (__typeof (*vp)) +{ + volatile __typeof__ (only_used_in_typeof) ii = 2; + if (ii != 2) + abort (); + const __typeof__ (not_defined ()) jj = 3; + if (jj != 3) + abort (); + unsigned int u = 1; + __typeof__ (u) u2 = 0; + __typeof (int (*)[++u2]) p = 0; + if (u2 != 1) + abort (); + if (sizeof (*p) != sizeof (int)) + abort (); + __typeof_unqual (int (*)[++u2]) q = 0; + if (u2 != 2) + abort (); + if (sizeof (*q) != 2 * sizeof (int)) + abort (); + if (sizeof (*p) != sizeof (int)) + abort (); + __typeof (++u2) u3 = 1; + if (u2 != u + u3) + abort (); + __typeof_unqual__ (++u2) u4 = 2; + if (u2 != u4) + abort (); + u = sizeof (__typeof__ (int (*)[++u2])); + if (u2 != 2) + abort (); + u = sizeof (__typeof_unqual (int (*)[++u2])); + if (u2 != 2) + abort (); + __typeof ((int (*)[++u2]) 0) q2; + if (u2 != 3) + abort (); + __typeof ((void) 0, (int (*)[++u2]) 0) q3; + if (u2 != 4) + abort (); + __typeof__ ((int (*)[++u2]) 0, 0) q4; + if (u2 != 4) + abort (); + __typeof_unqual ((int (*)[++u2]) 0) q5; + if (u2 != 5) + abort (); + __typeof_unqual__ ((void) 0, (int (*)[++u2]) 0) q6; + if (u2 != 6) + abort (); + __typeof_unqual__ ((int (*)[++u2]) 0, 0) q7; + if (u2 != 6) + abort (); + int a1[6], a2[6]; + int (*pa)[u2] = &a1; + __typeof (pa = &a2) pp; + if (pa != &a2) + abort (); + __typeof_unqual (pa = &a1) pp2; + if (pa != &a1) + abort (); + exit (0); +} --- gcc/testsuite/gcc.dg/gnu11-typeof-4.c.jj 2023-06-10 19:40:04.211568056 +0200 +++ gcc/testsuite/gcc.dg/gnu11-typeof-4.c 2023-06-10 19:50:07.819302529 +0200 @@ -0,0 +1,58 @@ +/* Test GNU extensions __typeof__ and __typeof_unqual__. Invalid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu11" } */ + +struct s { int i : 2; } x; +union u { unsigned int j : 1; } y; + +__typeof__ (x.i) j; /* { dg-error "applied to a bit-field" } */ +__typeof_unqual__ (x.i) j2; /* { dg-error "applied to a bit-field" } */ +__typeof (y.j) j3; /* { dg-error "applied to a bit-field" } */ +__typeof_unqual (y.j) j4; /* { dg-error "applied to a bit-field" } */ + +static int ok (void); +static int also_ok (void); +static int not_defined (void); /* { dg-warning "used but never defined" } */ +static int also_not_defined (void); /* { dg-warning "used but never defined" } */ + +_Noreturn void nf1 (void); +__attribute__((noreturn)) void nf2 (void); +void fg (void) {} +__typeof__ (&nf1) pnf1 = fg; /* { dg-warning "qualified function pointer from unqualified" } */ +__typeof (&nf2) pnf2 = fg; /* { dg-warning "qualified function pointer from unqualified" } */ +extern void (*pnf1) (void); /* { dg-error "conflicting types for" } */ +extern void (*pnf2) (void); /* { dg-error "conflicting types for" } */ +extern __typeof (nf1) *pnf1; /* { dg-error "conflicting types for" } */ +extern __typeof (nf1) *pnf2; /* { dg-error "conflicting types for" } */ +extern __typeof__ (nf2) *pnf1; /* { dg-error "conflicting types for" } */ +extern __typeof__ (nf2) *pnf2; /* { dg-error "conflicting types for" } */ +__typeof (*&nf1) fg2, fg2a, fg2b; +__typeof__ (*&nf2) fg3, fg3a, fg3b; +__typeof (nf1) fg4, fg4a, fg4b; +__typeof__ (nf2) fg5, fg5a, fg5b; + +extern void abort (void); + +void fg2 (void) {} /* { dg-error "conflicting type qualifiers for" } */ +_Noreturn void fg2a (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +__attribute__((noreturn)) void fg2b (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +void fg3 (void) {} /* { dg-error "conflicting type qualifiers for" } */ +_Noreturn void fg3a (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +__attribute__((noreturn)) void fg3b (void) { abort (); } /* { dg-error "conflicting type qualifiers for" } */ +void fg4 (void) {} +_Noreturn void fg4a (void) { abort (); } +__attribute__((noreturn)) void fg4b (void) { abort (); } +void fg5 (void) {} +_Noreturn void fg5a (void) { abort (); } +__attribute__((noreturn)) void fg5b (void) { abort (); } + +void +f (void) +{ + __typeof__ (ok ()) x = 2; + __typeof_unqual (also_ok ()) y = 2; + int a[2]; + int (*p)[x] = &a; + __typeof (p + not_defined ()) q; + __typeof_unqual__ (p + also_not_defined ()) q2; +}