public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c: Add __typeof_unqual__ and __typeof_unqual support
@ 2023-06-12 19:51 Jakub Jelinek
  2023-08-10 15:33 ` [PATCH] c, v2: " Jakub Jelinek
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2023-06-12 19:51 UTC (permalink / raw)
  To: Joseph S. Myers, Marek Polacek; +Cc: gcc-patches

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  <jakub@redhat.com>

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.

--- 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;
+}

	Jakub


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] c, v2: Add __typeof_unqual__ and __typeof_unqual support
  2023-06-12 19:51 [PATCH] c: Add __typeof_unqual__ and __typeof_unqual support Jakub Jelinek
@ 2023-08-10 15:33 ` Jakub Jelinek
  2023-08-10 22:24   ` Joseph Myers
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2023-08-10 15:33 UTC (permalink / raw)
  To: Joseph S. Myers, Marek Polacek, gcc-patches

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  <jakub@redhat.com>

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.

--- 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;
+}


	Jakub


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] c, v2: Add __typeof_unqual__ and __typeof_unqual support
  2023-08-10 15:33 ` [PATCH] c, v2: " Jakub Jelinek
@ 2023-08-10 22:24   ` Joseph Myers
  0 siblings, 0 replies; 3+ messages in thread
From: Joseph Myers @ 2023-08-10 22:24 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Marek Polacek, gcc-patches

On Thu, 10 Aug 2023, Jakub Jelinek via Gcc-patches wrote:

> 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?

OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-08-10 22:24 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-12 19:51 [PATCH] c: Add __typeof_unqual__ and __typeof_unqual support Jakub Jelinek
2023-08-10 15:33 ` [PATCH] c, v2: " Jakub Jelinek
2023-08-10 22:24   ` Joseph Myers

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).