[flang-commits] [flang] [flang] Fix POSIX.1/XPG checks in intrinsics-library.cpp (PR #201072)
Rainer Orth via flang-commits
flang-commits at lists.llvm.org
Wed Jul 29 01:25:55 PDT 2026
rorth wrote:
You're right about the `<unistd.h>` part. However, let's take two steps back: I think I now seen what's wrong. Assume for the moment that the guards above are meant to check if POSIX.1 >= 2001.1 or XPG >= 6 are available. Just take the guards and the instances of `HostRuntimeLibrary` within, indented to see the structure:
```
#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
#if !defined(_AIX) && !defined(__APPLE__)
template <> struct HostRuntimeLibrary<float, LibraryVersion::LibmExtensions> {
#endif
#if HAS_QUADMATHLIB
template <> struct HostRuntimeLibrary<__float128, LibraryVersion::Libm> {
template <> struct HostRuntimeLibrary<__complex128, LibraryVersion::Libm> {
#endif
template <> struct HostRuntimeLibrary<double, LibraryVersion::LibmExtensions> {
#if defined(__GLIBC__) && (HAS_FLOAT80 || HAS_LDBL128)
struct HostRuntimeLibrary<long double, LibraryVersion::LibmExtensions> {
#endif // HAS_FLOAT80 || HAS_LDBL128
#endif //_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
#ifdef _WIN32
template <> struct HostRuntimeLibrary<double, LibraryVersion::LibmExtensions> {
#endif
```
There's a mixture of `HostRuntimeLibrary<..., LibraryVersion::LibmExtensions>` and `HostRuntimeLibrary<..., LibraryVersion::Libm>` inside the POSIX.1/XPG guard. However, the `LibraryVersion::Libm` ones are completely unrelated to POSIX.1/XPG, but always present if `HAS_QUADMATHLIB`.
If you change the structure to
```
#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
#if !defined(_AIX) && !defined(__APPLE__)
template <> struct HostRuntimeLibrary<float, LibraryVersion::LibmExtensions> {
#endif
template <> struct HostRuntimeLibrary<double, LibraryVersion::LibmExtensions> {
#if defined(__GLIBC__) && (HAS_FLOAT80 || HAS_LDBL128)
struct HostRuntimeLibrary<long double, LibraryVersion::LibmExtensions> {
#endif // HAS_FLOAT80 || HAS_LDBL128
#endif //_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
#ifdef _WIN32
template <> struct HostRuntimeLibrary<double, LibraryVersion::LibmExtensions> {
#endif
#if HAS_QUADMATHLIB
template <> struct HostRuntimeLibrary<__float128, LibraryVersion::Libm> {
template <> struct HostRuntimeLibrary<__complex128, LibraryVersion::Libm> {
#endif
```
the compile failures observed when POSIX.1-2001/XPG6 is (incorrectly) assumed to be missing are gone.
Let's get to the actual POSIX.1/XPG guards now. Consider a (modified) version of the `ftm.c` example from Linux `feature_test_macros(7)`, stripped down to only include POSIX.1/XPG macros, but including `_POSIX_VERSION` and `_XOPEN_VERSION`:
```
/* ftm.c */
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
#ifdef _POSIX_SOURCE
printf("_POSIX_SOURCE defined\n");
#endif
#ifdef _POSIX_C_SOURCE
printf("_POSIX_C_SOURCE defined: %jdL\n",
(intmax_t) _POSIX_C_SOURCE);
#endif
#ifdef _POSIX_VERSION
printf("_POSIX_VERSION defined: %jdL\n",
(intmax_t) _POSIX_VERSION);
#endif
#ifdef _XOPEN_SOURCE
printf("_XOPEN_SOURCE defined: %d\n", _XOPEN_SOURCE);
#endif
#ifdef _XOPEN_VERSION
printf("_XOPEN_VERSION defined: %d\n", _XOPEN_VERSION);
#endif
exit(EXIT_SUCCESS);
}
```
If you build this with `gcc -o ftm ftm.c` on various targets, you get:
- Linux (Ubuntu 24.04):
```
_POSIX_SOURCE defined
_POSIX_C_SOURCE defined: 200809L
_POSIX_VERSION defined: 200809L
_XOPEN_VERSION defined: 700
```
- Solaris 11.4:
```
_POSIX_VERSION defined: 200809L
_XOPEN_VERSION defined: 700
```
- FreeBSD 15.1:
```
_POSIX_VERSION defined: 200809L
```
- NetBSD 10.1:
```
_POSIX_VERSION defined: 200112L
```
- macOS 26:
```
_POSIX_VERSION defined: 200112L
_XOPEN_VERSION defined: 600
```
- AIX 7.3:
```
_POSIX_SOURCE defined
_POSIX_C_SOURCE defined: 200809L
_POSIX_VERSION defined: 200809L
_XOPEN_SOURCE defined: 700
_XOPEN_VERSION defined: 700
```
As you can see, the system headers predefining the feature test macros themselves rather than their `_*_VERSION` counterparts is primarily a glibc (and AIX) extension. I suspect this doesn't violate POSIX.1/XPG, but certainly isn't the intended use. Therefore including `<unistd.h>` **and** switching the guard to `_POSIX_VERSION >= 200112L || _XOPEN_VERSION >= 600` should work as intended everywhere.
I've got a patch doing just this, so far only lightly tested on Solaris and Linux. If we can agree this is the direction to take, I'll test it some more on both Darwin and AIX, unless someone else who has development environments on those readily available beats me to it.
I could go on about properly guarding the various versions of the bessel functions, some of them in XPG6, others mere extensions on all sorts of platforms, but for the moment I'm primarily concerned about fixing the Solaris compile failure.
https://github.com/llvm/llvm-project/pull/201072
More information about the flang-commits
mailing list