GCC's <stddef.h> supports selective type requests such as
__need_size_t. System headers, including the macOS SDK, use the same
protocol to request rsize_t with __need_rsize_t. Clang handles this
request, but GCC's <stddef.h> returned without defining rsize_t.
This patch handles only an explicit __need_rsize_t request. It defines
rsize_t as __SIZE_TYPE__, uses _RSIZE_T to match Clang and the SDK's
non-modular path, and undefines __need_rsize_t after processing it. As
with other partial requests, it does not mark <stddef.h> as fully
included.
A normal inclusion still does not define rsize_t, including when
__STDC_WANT_LIB_EXT1__ is set. Defining it in that case would expose an
Annex K name on targets whose C libraries do not implement Annex K.
RSIZE_MAX and the bounds-checking functions remain the C library's
responsibility.
PR target/126782 was first observed on Darwin with -fmodules. GCC 16
reported __has_feature(modules), which made the SDK request
__need_rsize_t. GCC trunk no longer reports that feature, so the
original testcase now compiles without this patch. The patch adds
support for the underlying header protocol without restoring the old
trigger.
Bootstrapped all default languages on aarch64-unknown-linux-gnu.
Stages 2 and 3 compared equal. A full make -k check completed with:
PASS=997628 FAIL=57 XFAIL=5623 XPASS=0 UNSUPPORTED=11149 UNRESOLVED=7
ERROR=0. All five new tests passed. No local pre-patch full-suite
baseline was run. The 57 failures do not mention stddef.h or rsize_t.
Is this OK for trunk?
gcc/ChangeLog:
PR target/126782
* ginclude/stddef.h (__need_rsize_t): New selective-inclusion
request. Define rsize_t as __SIZE_TYPE__.
gcc/testsuite/ChangeLog:
PR target/126782
* gcc.dg/stddef-need-rsize-1.c: New test.
* gcc.dg/stddef-need-rsize-2.c: New test.
* gcc.dg/stddef-need-rsize-3.c: New test.
* gcc.dg/stddef-need-rsize-4.c: New test.
* g++.dg/stddef-need-rsize-1.C: New test.
Signed-off-by: Bjorn Pagen <[email protected]>
---
gcc/ginclude/stddef.h | 19 ++++++++++--
gcc/testsuite/g++.dg/stddef-need-rsize-1.C | 15 ++++++++++
gcc/testsuite/gcc.dg/stddef-need-rsize-1.c | 35 ++++++++++++++++++++++
gcc/testsuite/gcc.dg/stddef-need-rsize-2.c | 22 ++++++++++++++
gcc/testsuite/gcc.dg/stddef-need-rsize-3.c | 7 +++++
gcc/testsuite/gcc.dg/stddef-need-rsize-4.c | 9 ++++++
6 files changed, 105 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/stddef-need-rsize-1.C
create mode 100644 gcc/testsuite/gcc.dg/stddef-need-rsize-1.c
create mode 100644 gcc/testsuite/gcc.dg/stddef-need-rsize-2.c
create mode 100644 gcc/testsuite/gcc.dg/stddef-need-rsize-3.c
create mode 100644 gcc/testsuite/gcc.dg/stddef-need-rsize-4.c
diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
index 454e5e9fc..185c6ea18 100644
--- a/gcc/ginclude/stddef.h
+++ b/gcc/ginclude/stddef.h
@@ -28,14 +28,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively.
If not, see
&& !defined(__STDDEF_H__)) \
|| defined(__need_wchar_t) || defined(__need_size_t) \
|| defined(__need_ptrdiff_t) || defined(__need_NULL) \
- || defined(__need_wint_t)
+ || defined(__need_wint_t) || defined(__need_rsize_t)
/* Any one of these symbols __need_* means that GNU libc
wants us just to define one data type. So don't define
the symbols that indicate this file's entire job has been done. */
#if (!defined(__need_wchar_t) && !defined(__need_size_t) \
&& !defined(__need_ptrdiff_t) && !defined(__need_NULL) \
- && !defined(__need_wint_t))
+ && !defined(__need_wint_t) && !defined(__need_rsize_t))
#define _STDDEF_H
#define _STDDEF_H_
/* [email protected] says the NeXT needs this. */
@@ -252,6 +252,21 @@ typedef long ssize_t;
#undef __need_size_t
#endif /* _STDDEF_H or __need_size_t. */
+/* Restricted-size type from ISO C11 Annex K. Define it only when a
+ system header explicitly requests it via __need_rsize_t. A normal
+ inclusion of this header does not provide the type; many C libraries
+ do not implement Annex K. RSIZE_MAX and the bounds-checked
+ functions remain the C library's responsibility. */
+#if defined (__need_rsize_t)
+#ifndef _RSIZE_T /* in case the OS headers have defined it. */
+#define _RSIZE_T
+#ifndef __SIZE_TYPE__
+#define __SIZE_TYPE__ long unsigned int
+#endif
+typedef __SIZE_TYPE__ rsize_t;
+#endif /* _RSIZE_T */
+#undef __need_rsize_t
+#endif /* __need_rsize_t. */
/* Wide character type.
Locale-writers should change this as necessary to
diff --git a/gcc/testsuite/g++.dg/stddef-need-rsize-1.C
b/gcc/testsuite/g++.dg/stddef-need-rsize-1.C
new file mode 100644
index 000000000..ffdcc87f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/stddef-need-rsize-1.C
@@ -0,0 +1,15 @@
+/* PR target/126782 */
+/* Explicit __need_rsize_t must define rsize_t in C++ as well. */
+/* { dg-do compile } */
+
+#define __need_rsize_t
+#include <stddef.h>
+
+#ifdef __need_rsize_t
+#error "__need_rsize_t was not consumed"
+#endif
+
+rsize_t value;
+
+extern rsize_t *p;
+extern __SIZE_TYPE__ *p;
diff --git a/gcc/testsuite/gcc.dg/stddef-need-rsize-1.c
b/gcc/testsuite/gcc.dg/stddef-need-rsize-1.c
new file mode 100644
index 000000000..ed51379f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/stddef-need-rsize-1.c
@@ -0,0 +1,35 @@
+/* PR target/126782 */
+/* Explicit __need_rsize_t must define rsize_t without completing
+ a normal <stddef.h> inclusion. */
+/* { dg-do compile } */
+
+#define __need_rsize_t
+#include <stddef.h>
+
+#ifdef __need_rsize_t
+#error "__need_rsize_t was not consumed"
+#endif
+
+#ifdef _STDDEF_H
+#error "partial request must not define _STDDEF_H"
+#endif
+
+#ifdef _STDDEF_H_
+#error "partial request must not define _STDDEF_H_"
+#endif
+
+#ifndef _RSIZE_T
+#error "_RSIZE_T was not defined"
+#endif
+
+rsize_t value;
+
+extern rsize_t *p;
+extern __SIZE_TYPE__ *p;
+
+#define __need_rsize_t
+#include <stddef.h>
+
+rsize_t again;
+
+size_t missing; /* { dg-error "unknown type name 'size_t'" } */
diff --git a/gcc/testsuite/gcc.dg/stddef-need-rsize-2.c
b/gcc/testsuite/gcc.dg/stddef-need-rsize-2.c
new file mode 100644
index 000000000..0bfe5a872
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/stddef-need-rsize-2.c
@@ -0,0 +1,22 @@
+/* PR target/126782 */
+/* A later __need_rsize_t request must still define rsize_t after a
+ complete <stddef.h> inclusion. */
+/* { dg-do compile } */
+
+#include <stddef.h>
+
+#ifndef _STDDEF_H
+#error "full inclusion must define _STDDEF_H"
+#endif
+
+#define __need_rsize_t
+#include <stddef.h>
+
+#ifdef __need_rsize_t
+#error "__need_rsize_t was not consumed"
+#endif
+
+rsize_t value;
+
+extern rsize_t *p;
+extern __SIZE_TYPE__ *p;
diff --git a/gcc/testsuite/gcc.dg/stddef-need-rsize-3.c
b/gcc/testsuite/gcc.dg/stddef-need-rsize-3.c
new file mode 100644
index 000000000..67f51639d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/stddef-need-rsize-3.c
@@ -0,0 +1,7 @@
+/* PR target/126782 */
+/* A normal <stddef.h> inclusion must not expose rsize_t. */
+/* { dg-do compile } */
+
+#include <stddef.h>
+
+rsize_t value; /* { dg-error "unknown type name 'rsize_t'" } */
diff --git a/gcc/testsuite/gcc.dg/stddef-need-rsize-4.c
b/gcc/testsuite/gcc.dg/stddef-need-rsize-4.c
new file mode 100644
index 000000000..8638ee67f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/stddef-need-rsize-4.c
@@ -0,0 +1,9 @@
+/* PR target/126782 */
+/* Requesting Annex K interfaces must not, by itself, make this header
+ declare rsize_t. */
+/* { dg-do compile } */
+
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <stddef.h>
+
+rsize_t value; /* { dg-error "unknown type name 'rsize_t'" } */
--
2.50.1 (Apple Git-155)