c: C2x typeof
authorJoseph Myers <joseph@codesourcery.com>
Thu, 6 Oct 2022 14:26:21 +0000 (14:26 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 6 Oct 2022 14:26:21 +0000 (14:26 +0000)
commitfa258f6894801aef6785f0327594dc803da63fbd
treec11370ab02d3e2babc54547c0778057ce4a36e76
parent09df0d8b14dda66c5159a1b2cf85b73f26282152
c: C2x typeof

C2x adds typeof as a standard feature.  In general this follows
existing GNU C semantics very closely, but there are various ways in
which the implementation involves more than simply enabling the
keyword for C2x:

* As well as typeof, there is a typeof_unqual variant, which removes
  all qualifiers and _Atomic from the resulting type (whereas typeof
  preserves qualifiers and _Atomic on qualified or atomic (lvalue or
  type name) operands).

* The typeof keyword is disabled by -fno-asm, so enabling it for C2x
  needs to be implemented in a way that preserves the disabling by
  -fno-asm for older standard versions (which having -fno-asm having
  no effect on it in C2x mode).  This is done via adding a new D_EXT11
  mask (which is also where the C++ front-end change comes from, to
  handle D_EXT11 appropriately there for -fno-asm and
  -fno-gnu-keywords).

* GNU typeof treats the noreturn property of a function (as specified
  in standard C with _Noreturn or [[noreturn]]) as being part of the
  type of a pointer to function, but it is not part of the type in
  standard terms.  Thus a special case is needed in the typeof
  implementation, just like in the _Generic implementation, to avoid
  treating it as a type for standard typeof.  It seems plausible this
  is being used when copying the type of one object to another using
  typeof, so the existing semantics are preserved for __typeof__, and
  for typeof in pre-C2x modes, while typeof for C2x or later has the
  standard semantics.

* It turns out that, even after Martin Uecker's changes in this area,
  there were still cases where rvalues could wrongly have a qualified
  or atomic type in GCC.  This applied to ++ and -- increment and
  decrement expressions, and also to calls to functions returning an
  atomic type.  (For the latter, the working draft doesn't actually
  explicitly exclude the function call expression having an atomic
  type, but given all the changes that have gone into C17 and C2x to
  avoid rvalues ever having qualified types, and given that
  lvalue-to-rvalue conversion removes both qualifiers and _Atomic, it
  seems unlikely that this (or casts, where GCC already removes
  _Atomic) is actually intended as a route to allow an
  _Atomic-qualified rvalue; I've noted this to raise as an NB comment
  on the CD ballot.)

Bootstrapped with no regressions for x86_64-pc-linux-gnu.  OK to
commit (C+

gcc/
* doc/invoke.texi (-fno-asm): Update description of effects on
typeof keyword.

gcc/c-family/
* c-common.cc (c_common_reswords): Mark typeof as D_EXT11.  Add
typeof_unqual.
* c-common.h (enum rid): Add RID_TYPEOF_UNQUAL.
(D_EXT11): New macro.  Values of subsequent macros updated.

gcc/c/
* c-parser.cc (c_parse_init): Add D_EXT11 to mask if flag_no_asm
and not C2x.
(c_keyword_starts_typename, c_token_starts_declspecs)
(c_parser_declspecs, c_parser_objc_selector): Handle
RID_TYPEOF_UNQUAL.
(c_parser_typeof_specifier): Handle RID_TYPEOF_UNQUAL.
Distinguish typeof for C2x from __typeof__ for all standard
versions and typeof before C2x.
* c-typeck.cc (build_function_call_vec): Use unqualified version
of non-void return type.
(build_unary_op): Use unqualified type for increment and
decrement.

gcc/cp/
* lex.cc (init_reswords): Handle D_EXT11.

gcc/testsuite/
* gcc.dg/c11-typeof-1.c, gcc.dg/c2x-typeof-1.c,
gcc.dg/c2x-typeof-2.c, gcc.dg/c2x-typeof-3.c,
gcc.dg/gnu11-typeof-1.c, gcc.dg/gnu11-typeof-2.c,
gcc.dg/gnu2x-typeof-1.c: New tests.
13 files changed:
gcc/c-family/c-common.cc
gcc/c-family/c-common.h
gcc/c/c-parser.cc
gcc/c/c-typeck.cc
gcc/cp/lex.cc
gcc/doc/invoke.texi
gcc/testsuite/gcc.dg/c11-typeof-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-typeof-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-typeof-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-typeof-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gnu11-typeof-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gnu11-typeof-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gnu2x-typeof-1.c [new file with mode: 0644]