From patchwork Mon Jun 12 19:51:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 106779 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp98257vqr; Mon, 12 Jun 2023 12:52:16 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5fNJUsE47pChmPY3smA2O3xEgOmgPimrsLeiAUi4VM2dZa+28sMwYsI5mxyPcFz73S2MeZ X-Received: by 2002:a17:907:320c:b0:976:8fdd:9046 with SMTP id xg12-20020a170907320c00b009768fdd9046mr9543509ejb.12.1686599536811; Mon, 12 Jun 2023 12:52:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686599536; cv=none; d=google.com; s=arc-20160816; b=ZOXIXwvj/s3D09gKhA63+DimF4J551yOk5itZ1OpBT7yWT5U8l+mbyVEmctX8M3q0h k2BMCZ9H32+jkU/vzbhQDCg573DCBs+xSNyuwkvGpu5uNVtgmGygrrKdVM3Lr8ybeyEu ZFL5GwxS7UEbUrC6GTLZ1CmxUuplqswI+RXIbnZol7dXptyTgymWDhqTWqfcsxyQzJEl FvsOSjX29QCWyjTC4j9YY8tWxh4hZa7el7OZzW3FvMNaHr0Nzp59ykVL4h8/BSkDuhBz ARaXb1SPTiVZ2CvTB9WSkAtKZ3TdfWvWaR3O2mc+3Gq2dUcDXGvlmGX4ZxGfotQsJgPj NMMA== 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:mime-version:message-id:subject:cc:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=kR2L8rOu64DfobRuScgtkPjRpTZhAsCinPm+BV7/kYA=; b=mKrvZdRqiT/2RxTfO7IphJA3b8LxOE6taQvWEmROh0gEnkcamETEsid/lYHTjQguBp Y38fDZtEZs0vfVia/tzjui+YPFzESXSH/DNPElThv2gy2AmCISvuzNryrDkEoDrDZIUy YRjjhLrpFolehtLhcxrLTFcWg0XZBguUw6SOqtxNe0pQOiOnu0KvGdiPQJPJqrfObUVb wBYgFdi20Fo5ZUdN1rLL5/JzO8D648rgRZh0hLBmqCvNcG8fRMCJ6jIjCeWrHBzxaiW1 psKNfAynkkq+B/mlS5/yYw5e+BJ8E+00Fm+VYjKVGdEdReRrDlZqOv0gIktCu4nL38FM H5PQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=qYjBG2He; 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 sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id kk6-20020a170907766600b00976a813d882si2314930ejc.4.2023.06.12.12.52.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Jun 2023 12:52:16 -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=qYjBG2He; 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 8C4443858C52 for ; Mon, 12 Jun 2023 19:52:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8C4443858C52 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1686599535; bh=kR2L8rOu64DfobRuScgtkPjRpTZhAsCinPm+BV7/kYA=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=qYjBG2HeBboMxCAxqR0Xvocc2AKI8BYtq7LKLg9fKA9UFkV6/W8ETpVGOd5FJ6sD6 Um9KqATh5wB22TkHHtkrXmc9IL62OqGb/4gqWyhxaebBAfyoAQyryNRE9CUgl1GD5n kxEbvf0bAr/LfVlazngahbBxVM6fmO6nBpdeO5sc= 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 39DC13858D20 for ; Mon, 12 Jun 2023 19:51:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 39DC13858D20 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-673-lcdzl_wgMAqD9aNE7KhTtA-1; Mon, 12 Jun 2023 15:51:27 -0400 X-MC-Unique: lcdzl_wgMAqD9aNE7KhTtA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E51111C03DBA; Mon, 12 Jun 2023 19:51:26 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.30]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8369E40D1B60; Mon, 12 Jun 2023 19:51:26 +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 35CJpNrG2489487 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 12 Jun 2023 21:51:24 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 35CJpMho2489486; Mon, 12 Jun 2023 21:51:22 +0200 Date: Mon, 12 Jun 2023 21:51:22 +0200 To: "Joseph S. Myers" , Marek Polacek Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c: Add __typeof_unqual__ and __typeof_unqual support Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1768527795963529741?= X-GMAIL-MSGID: =?utf-8?q?1768527795963529741?= Hi! 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. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2023-06-12 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-06-06 20:02:35.643211062 +0200 +++ gcc/doc/extend.texi 2023-06-10 19:58:26.197478291 +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}. + 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 only one variable, whose declarator must just be an identifier, the --- 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; +}