c: Implement C23 nullptr (N3042)
commit60d84e82639e25b025a926b19ec5a92fba4447ce
authorMarek Polacek <polacek@redhat.com>
Wed, 10 Aug 2022 19:00:49 +0000 (10 15:00 -0400)
committerMarek Polacek <polacek@redhat.com>
Thu, 25 Aug 2022 21:54:13 +0000 (25 17:54 -0400)
tree7bbbeeb4ff4c16132b02c74f95a936d80cd09779
parent14cfa01755a66afbae2539f8b5796c960ddcecc6
c: Implement C23 nullptr (N3042)

This patch implements the C23 nullptr literal:
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3042.htm> (with
wording fixes from N3047), which is intended to replace the problematic
definition of NULL which might be either of integer type or void*.

Since C++ has had nullptr for over a decade now, it was relatively easy
to just move the built-in node definitions from the C++ FE to the C/C++
common code.  Also, our DWARF emitter already handles NULLPTR_TYPE by
emitting DW_TAG_unspecified_type.  However, I had to handle a lot of
contexts such as ?:, comparison, conversion, etc.

There are some minor differences, e.g. in C you can do

  bool b = nullptr;

but in C++ you have to use direct-initialization:

  bool b{nullptr};

And I think that

  nullptr_t n = 0;

is only valid in C++.

Of course, C doesn't have to handle mangling, RTTI, substitution,
overloading, ...

This patch also defines nullptr_t in <stddef.h>.  However, it does not
define __STDC_VERSION_STDDEF_H__ yet, because we don't know yet what value
it should be defined to.

gcc/c-family/ChangeLog:

* c-common.cc (c_common_reswords): Enable nullptr in C2X.
(c_common_nodes_and_builtins): Create the built-in node for nullptr.
* c-common.h (enum c_tree_index): Add CTI_NULLPTR, CTI_NULLPTR_TYPE.
(struct c_common_resword): Resize the disable member.
(D_C2X): Add.
(nullptr_node): Define.
(nullptr_type_node): Define.
(NULLPTR_TYPE_P): Define.
* c-pretty-print.cc (c_pretty_printer::simple_type_specifier): Handle
NULLPTR_TYPE.
(c_pretty_printer::direct_abstract_declarator): Likewise.
(c_pretty_printer::constant): Likewise.

gcc/c/ChangeLog:

* c-convert.cc (c_convert) <case POINTER_TYPE>: Handle NULLPTR_TYPE.
Give a better diagnostic when converting to nullptr_t.
* c-decl.cc (c_init_decl_processing): Perform C-specific nullptr
initialization.
* c-parser.cc (c_parse_init): Maybe OR D_C2X into mask.
(c_parser_postfix_expression): Handle RID_NULLPTR.
* c-typeck.cc (null_pointer_constant_p): Return true when expr is
nullptr_node.
(build_unary_op) <case TRUTH_NOT_EXPR>: Handle NULLPTR_TYPE.
(build_conditional_expr): Handle the case when the second/third operand
is NULLPTR_TYPE and third/second operand is POINTER_TYPE.
(convert_for_assignment): Handle converting an expression of type
nullptr_t to pointer/bool.
(build_binary_op) <case TRUTH_XOR_EXPR>: Handle NULLPTR_TYPE.
<case EQ_EXPR>: Handle comparing operands of type nullptr_t.

gcc/cp/ChangeLog:

* cp-tree.h (enum cp_tree_index): Remove CTI_NULLPTR, CTI_NULLPTR_TYPE.
Move it to c_tree_index.
(nullptr_node): No longer define here.
(nullptr_type_node): Likewise.
(NULLPTR_TYPE_P): Likewise.
* decl.cc (cxx_init_decl_processing): Only keep C++-specific nullptr
initialization; move the shared code to c_common_nodes_and_builtins.

gcc/ChangeLog:

* ginclude/stddef.h: Define nullptr_t.

gcc/testsuite/ChangeLog:

* gcc.dg/c11-nullptr-1.c: New test.
* gcc.dg/c17-nullptr-1.c: New test.
* gcc.dg/c17-nullptr-2.c: New test.
* gcc.dg/c2x-nullptr-1.c: New test.
* gcc.dg/c2x-nullptr-2.c: New test.
* gcc.dg/c2x-nullptr-3.c: New test.
* gcc.dg/c2x-nullptr-4.c: New test.
* gcc.dg/c2x-nullptr-5.c: New test.
18 files changed:
gcc/c-family/c-common.cc
gcc/c-family/c-common.h
gcc/c-family/c-pretty-print.cc
gcc/c/c-convert.cc
gcc/c/c-decl.cc
gcc/c/c-parser.cc
gcc/c/c-typeck.cc
gcc/cp/cp-tree.h
gcc/cp/decl.cc
gcc/ginclude/stddef.h
gcc/testsuite/gcc.dg/c11-nullptr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c17-nullptr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c17-nullptr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-nullptr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-nullptr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-nullptr-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-nullptr-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-nullptr-5.c [new file with mode: 0644]