Bug 257827

Summary: Providing _POSIX_C_SOURCE causes some C++ headers to fail
Product: Base System Reporter: Chris Spiegel <cspiegel>
Component: standardsAssignee: freebsd-standards (Nobody) <standards>
Status: New ---    
Severity: Affects Only Me CC: imp
Priority: ---    
Version: 13.0-RELEASE   
Hardware: amd64   
OS: Any   

Description Chris Spiegel 2021-08-14 00:40:11 UTC
Consider the following C++ program:

```
#include <iostream>

int main(void)
{
    return 0;
}
```

Build:

```
$ c++ -std=c++98 -D_POSIX_C_SOURCE=200112L t.cpp

In file included from /home/chris/t.cpp:1:
In file included from /usr/include/c++/v1/iostream:37:
In file included from /usr/include/c++/v1/ios:215:
/usr/include/c++/v1/__locale:631:16: error: use of undeclared identifier 'isascii'
        return isascii(__c) ? (__tab_[static_cast<int>(__c)] & __m) !=0 : false;
               ^
/usr/include/c++/v1/__locale:638:22: error: use of undeclared identifier 'isascii'
            *__vec = isascii(*__low) ? __tab_[static_cast<int>(*__low)] : 0;
                     ^
/usr/include/c++/v1/__locale:646:17: error: use of undeclared identifier 'isascii'
            if (isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m))
                ^
/usr/include/c++/v1/__locale:655:19: error: use of undeclared identifier 'isascii'
            if (!(isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m)))
                  ^
4 errors generated.
```

The problem (as far as I can tell) is that isascii() is an XSI extension, so will not be exposed unless _XOPEN_SOURCE is set.  But then __locale directly calls isascii(), inadvertently requiring the user to set things up so that it's exposed. I think the proper solution would be for __locale to use an internal version of isascii(), e.g. __isascii(), which can be exposed no matter what (since it's a reserved identifier).
Comment 1 Warner Losh freebsd_committer freebsd_triage 2021-08-14 01:04:30 UTC
_POSIX_C_SOURCE=200112 is only valid for 'C' code, not 'C++'.
It specifically requires a C99 compiler as well, and only makes c99
defined functions visible (and a few others that aren't relevant here).
isascii is marked as XSI in the POSIX standard and ctypes.h says that it must define the proper feature test macros (in this case _XOPEN_SOURCE must be defined to 700) before it is visible.

So I'm thinking this isn't a bug in two different ways: it's not C and even if it were, the proper _XOPEN_SOURCE macro isn't defined when you've asked for strict POSIX compliance.
Comment 2 Chris Spiegel 2021-08-14 01:25:09 UTC
If _POSIX_C_SOURCE is invalid for C++, then agreed, this whole bug is invalid. Moreover, given that _XOPEN_SOURCE includes _POSIX_C_SOURCE (i.e. if you define _XOPEN_SOURCE it's equivalent to defining the corresponding _POSIX_C_SOURCE), it seems that neither of these can/should be set while using C++.

Just for some information, I found that Oracle's Solaris posix(5) man page says this:

"C++ bindings are not defined for POSIX or X/Open CAE, so specifying feature test macros such as _POSIX_SOURCE, _POSIX_C_SOURCE, and _XOPEN_SOURCE can result in compilation errors due to conflicting requirements of standard C++ and those specifications." (https://docs.oracle.com/cd/E86824_01/html/E54776/posix-5.html)

Does all of this imply that it's invalid to call POSIX code from C++?  On FreeBSD, at least, it "works" just fine if you define _XOPEN_SOURCE for C++, but of course that might be incidental, given that _POSIX_C_SOURCE alone causes this failure (it's valid in general to ask for POSIX support without the XSI extension, e.g. to defined only _POSIX_C_SOURCE).
Comment 3 Warner Losh freebsd_committer freebsd_triage 2021-08-14 03:45:27 UTC
It's not illegal to call POSIX code from C++. They are just functions after all.

What's undefined is to ask for a strict POSIX namespace using the feature test macros. Without them, everything will be visible. Since the C++ headers use POSIX features in unspecified ways, I don't think you can come up with a set of feature test macros that's guaranteed to work in that environment. Since these feature test macros are for the user to request things outside of the POSIX standard defines not be defined, the simplest workaround is to not define them.

I've not kept up with the Austin Group's standardization process to know if they are including C++ or not with their next refresh of the standard. We've not had anything other than technical corrections since 2008.
Comment 4 Warner Losh freebsd_committer freebsd_triage 2021-08-14 03:46:24 UTC
I should have said 'C++ headers use posix and non-posix features in unspecified ways'.